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("anglebinwidth"); + posbinwidth_ = pset.getUntrackedParameter("posbinwidth"); + + // MAXIMA SEARCH CONFIGURATION + maxdeltaAngDeg_ = pset.getUntrackedParameter("maxdeltaAngDeg"); + maxdeltaPos_ = pset.getUntrackedParameter("maxdeltaPos"); + upperNumber_ = (unsigned short int)pset.getUntrackedParameter("UpperNumber"); + lowerNumber_ = (unsigned short int)pset.getUntrackedParameter("LowerNumber"); + + // HITS ASSOCIATION CONFIGURATION + maxDistanceToWire_ = pset.getUntrackedParameter("MaxDistanceToWire"); + + // CANDIDATE QUALITY CONFIGURATION + minNLayerHits_ = (unsigned short int)pset.getUntrackedParameter("minNLayerHits"); + minSingleSLHitsMax_ = (unsigned short int)pset.getUntrackedParameter("minSingleSLHitsMax"); + minSingleSLHitsMin_ = (unsigned short int)pset.getUntrackedParameter("minSingleSLHitsMin"); + allowUncorrelatedPatterns_ = pset.getUntrackedParameter("allowUncorrelatedPatterns"); + minUncorrelatedHits_ = (unsigned short int)pset.getUntrackedParameter("minUncorrelatedHits"); + + dtGeomH = iC.esConsumes(); +} + +HoughGrouping::~HoughGrouping() { + if (debug_) + LogDebug("HoughGrouping") << "HoughGrouping: destructor" << endl; +} + +// ============================================================================ +// Main methods (initialise, run, finish) +// ============================================================================ +void HoughGrouping::initialise(const edm::EventSetup& iEventSetup) { + if (debug_) + LogDebug("HoughGrouping") << "initialise"; + + resetAttributes(); + + maxrads_ = 0.5 * M_PI - atan(angletan_); + minangle_ = (double)convertDegToRad(anglebinwidth_); + halfanglebins_ = round(maxrads_ / minangle_ + 1); + anglebins_ = (unsigned short int)2 * halfanglebins_; + oneanglebin_ = maxrads_ / halfanglebins_; + + maxdeltaAng_ = maxdeltaAngDeg_ * 2 * M_PI / 360; + + // Initialisation of anglemap. Posmap depends on the size of the chamber. + double phi = 0; + anglemap_ = {}; + for (unsigned short int ab = 0; ab < halfanglebins_; ab++) { + anglemap_[ab] = phi; + phi += oneanglebin_; + } + + phi = (M_PI - maxrads_); + for (unsigned short int ab = halfanglebins_; ab < anglebins_; ab++) { + anglemap_[ab] = phi; + phi += oneanglebin_; + } + + if (debug_) { + LogDebug("HoughGrouping") + << "\nHoughGrouping::ResetAttributes - Information from the initialisation of HoughGrouping:"; + LogDebug("HoughGrouping") << "ResetAttributes - maxrads: " << maxrads_; + LogDebug("HoughGrouping") << "ResetAttributes - anglebinwidth: " << anglebinwidth_; + LogDebug("HoughGrouping") << "ResetAttributes - minangle: " << minangle_; + LogDebug("HoughGrouping") << "ResetAttributes - halfanglebins: " << halfanglebins_; + LogDebug("HoughGrouping") << "ResetAttributes - anglebins: " << anglebins_; + LogDebug("HoughGrouping") << "ResetAttributes - oneanglebin: " << oneanglebin_; + LogDebug("HoughGrouping") << "ResetAttributes - posbinwidth: " << posbinwidth_; + } + + const MuonGeometryRecord& geom = iEventSetup.get(); + dtGeo_ = &geom.get(dtGeomH); +} + +void HoughGrouping::run(edm::Event& iEvent, + const edm::EventSetup& iEventSetup, + const DTDigiCollection& digis, + MuonPathPtrs& outMpath) { + if (debug_) + LogDebug("HoughGrouping") << "\nHoughGrouping::run"; + + resetAttributes(); + + if (debug_) + LogDebug("HoughGrouping") << "run - Beginning digis' loop..."; + LocalPoint wirePosInLay, wirePosInChamber; + GlobalPoint wirePosGlob; + for (DTDigiCollection::DigiRangeIterator dtLayerIdIt = digis.begin(); dtLayerIdIt != digis.end(); dtLayerIdIt++) { + const DTLayer* lay = dtGeo_->layer((*dtLayerIdIt).first); + for (DTDigiCollection::const_iterator digiIt = ((*dtLayerIdIt).second).first; + digiIt != ((*dtLayerIdIt).second).second; + digiIt++) { + if (debug_) { + LogDebug("HoughGrouping") << "\nHoughGrouping::run - Digi number " << idigi_; + LogDebug("HoughGrouping") << "run - Wheel: " << (*dtLayerIdIt).first.wheel(); + LogDebug("HoughGrouping") << "run - Chamber: " << (*dtLayerIdIt).first.station(); + LogDebug("HoughGrouping") << "run - Sector: " << (*dtLayerIdIt).first.sector(); + LogDebug("HoughGrouping") << "run - Superlayer: " << (*dtLayerIdIt).first.superLayer(); + LogDebug("HoughGrouping") << "run - Layer: " << (*dtLayerIdIt).first.layer(); + LogDebug("HoughGrouping") << "run - Wire: " << (*digiIt).wire(); + LogDebug("HoughGrouping") << "run - First wire: " << lay->specificTopology().firstChannel(); + LogDebug("HoughGrouping") << "run - Last wire: " << lay->specificTopology().lastChannel(); + LogDebug("HoughGrouping") << "run - First wire x: " + << lay->specificTopology().wirePosition(lay->specificTopology().firstChannel()); + LogDebug("HoughGrouping") << "run - Last wire x: " + << lay->specificTopology().wirePosition(lay->specificTopology().lastChannel()); + LogDebug("HoughGrouping") << "run - Cell width: " << lay->specificTopology().cellWidth(); + LogDebug("HoughGrouping") << "run - Cell height: " << lay->specificTopology().cellHeight(); + } + if ((*dtLayerIdIt).first.superLayer() == 2) + continue; + + wirePosInLay = LocalPoint(lay->specificTopology().wirePosition((*digiIt).wire()), 0, 0); + wirePosGlob = lay->toGlobal(wirePosInLay); + wirePosInChamber = lay->chamber()->toLocal(wirePosGlob); + + if ((*dtLayerIdIt).first.superLayer() == 3) { + digimap_[(*dtLayerIdIt).first.layer() + 3][(*digiIt).wire()] = DTPrimitive(); + digimap_[(*dtLayerIdIt).first.layer() + 3][(*digiIt).wire()].setTDCTimeStamp((*digiIt).time()); + digimap_[(*dtLayerIdIt).first.layer() + 3][(*digiIt).wire()].setChannelId((*digiIt).wire()); + digimap_[(*dtLayerIdIt).first.layer() + 3][(*digiIt).wire()].setLayerId((*dtLayerIdIt).first.layer()); + digimap_[(*dtLayerIdIt).first.layer() + 3][(*digiIt).wire()].setSuperLayerId((*dtLayerIdIt).first.superLayer()); + digimap_[(*dtLayerIdIt).first.layer() + 3][(*digiIt).wire()].setCameraId((*dtLayerIdIt).first.rawId()); + } else { + digimap_[(*dtLayerIdIt).first.layer() - 1][(*digiIt).wire()] = DTPrimitive(); + digimap_[(*dtLayerIdIt).first.layer() - 1][(*digiIt).wire()].setTDCTimeStamp((*digiIt).time()); + digimap_[(*dtLayerIdIt).first.layer() - 1][(*digiIt).wire()].setChannelId((*digiIt).wire()); + digimap_[(*dtLayerIdIt).first.layer() - 1][(*digiIt).wire()].setLayerId((*dtLayerIdIt).first.layer()); + digimap_[(*dtLayerIdIt).first.layer() - 1][(*digiIt).wire()].setSuperLayerId((*dtLayerIdIt).first.superLayer()); + digimap_[(*dtLayerIdIt).first.layer() - 1][(*digiIt).wire()].setCameraId((*dtLayerIdIt).first.rawId()); + } + + // Obtaining geometrical info of the chosen chamber + if (xlowlim_ == 0 && xhighlim_ == 0 && zlowlim_ == 0 && zhighlim_ == 0) { + thewheel_ = (*dtLayerIdIt).first.wheel(); + thestation_ = (*dtLayerIdIt).first.station(); + thesector_ = (*dtLayerIdIt).first.sector(); + obtainGeometricalBorders(lay); + } + + if (debug_) { + LogDebug("HoughGrouping") << "run - X position of the cell (chamber frame of reference): " + << wirePosInChamber.x(); + LogDebug("HoughGrouping") << "run - Y position of the cell (chamber frame of reference): " + << wirePosInChamber.y(); + LogDebug("HoughGrouping") << "run - Z position of the cell (chamber frame of reference): " + << wirePosInChamber.z(); + } + + hitvec_.push_back({wirePosInChamber.x() - 1.05, wirePosInChamber.z()}); + hitvec_.push_back({wirePosInChamber.x() + 1.05, wirePosInChamber.z()}); + nhits_ += 2; + + idigi_++; + } + } + + if (debug_) { + LogDebug("HoughGrouping") << "\nHoughGrouping::run - nhits: " << nhits_; + LogDebug("HoughGrouping") << "run - idigi: " << idigi_; + } + + if (hitvec_.empty()) { + if (debug_) + LogDebug("HoughGrouping") << "run - No digis present in this chamber."; + return; + } + + // Perform the Hough transform of the inputs. + doHoughTransform(); + + // Obtain the maxima + maxima_ = getMaximaVector(); + resetPosElementsOfLinespace(); + + if (maxima_.empty()) { + if (debug_) + LogDebug("HoughGrouping") << "run - No good maxima found in this event."; + return; + } + + DTChamberId TheChambId(thewheel_, thestation_, thesector_); + const DTChamber* TheChamb = dtGeo_->chamber(TheChambId); + std::vector cands; + + for (unsigned short int ican = 0; ican < maxima_.size(); ican++) { + if (debug_) + LogDebug("HoughGrouping") << "\nHoughGrouping::run - Candidate number: " << ican; + cands.push_back(associateHits(TheChamb, maxima_.at(ican).first, maxima_.at(ican).second)); + } + + // Now we filter them: + orderAndFilter(cands, outMpath); + if (debug_) + LogDebug("HoughGrouping") << "run - now we have our muonpaths! It has " << outMpath.size() << " elements"; + + cands.clear(); + return; +} + +void HoughGrouping::finish() { + if (debug_) + LogDebug("HoughGrouping") << "finish"; + return; +} + +// ============================================================================ +// Other methods +// ============================================================================ +void HoughGrouping::resetAttributes() { + if (debug_) + LogDebug("HoughGrouping") << "ResetAttributes"; + // std::vector's: + maxima_.clear(); + hitvec_.clear(); + + // Integer-type variables: + spacebins_ = 0; + idigi_ = 0; + nhits_ = 0; + xlowlim_ = 0; + xhighlim_ = 0; + zlowlim_ = 0; + zhighlim_ = 0; + thestation_ = 0; + thesector_ = 0; + thewheel_ = 0; + + // Arrays: + // NOTE: linespace array is treated and reset separately + + // Maps (dictionaries): + posmap_.clear(); + for (unsigned short int abslay = 0; abslay < 8; abslay++) + digimap_[abslay].clear(); +} + +void HoughGrouping::resetPosElementsOfLinespace() { + if (debug_) + LogDebug("HoughGrouping") << "ResetPosElementsOfLinespace"; + for (unsigned short int ab = 0; ab < anglebins_; ab++) { + linespace_[ab].clear(); + } + linespace_.clear(); +} + +void HoughGrouping::obtainGeometricalBorders(const DTLayer* lay) { + if (debug_) + LogDebug("HoughGrouping") << "ObtainGeometricalBorders"; + LocalPoint FirstWireLocal(lay->chamber()->superLayer(1)->layer(1)->specificTopology().wirePosition( + lay->chamber()->superLayer(1)->layer(1)->specificTopology().firstChannel()), + 0, + 0); // TAKING INFO FROM L1 OF SL1 OF THE CHOSEN CHAMBER + GlobalPoint FirstWireGlobal = lay->chamber()->superLayer(1)->layer(1)->toGlobal(FirstWireLocal); + LocalPoint FirstWireLocalCh = lay->chamber()->toLocal(FirstWireGlobal); + + LocalPoint LastWireLocal(lay->chamber()->superLayer(1)->layer(1)->specificTopology().wirePosition( + lay->chamber()->superLayer(1)->layer(1)->specificTopology().lastChannel()), + 0, + 0); + GlobalPoint LastWireGlobal = lay->chamber()->superLayer(1)->layer(1)->toGlobal(LastWireLocal); + LocalPoint LastWireLocalCh = lay->chamber()->toLocal(LastWireGlobal); + + // unsigned short int upsl = thestation == 4 ? 2 : 3; + unsigned short int upsl = thestation_ == 4 ? 3 : 3; + if (debug_) + LogDebug("HoughGrouping") << "ObtainGeometricalBorders - uppersuperlayer: " << upsl; + + LocalPoint FirstWireLocalUp(lay->chamber()->superLayer(upsl)->layer(4)->specificTopology().wirePosition( + lay->chamber()->superLayer(upsl)->layer(4)->specificTopology().firstChannel()), + 0, + 0); // TAKING INFO FROM L1 OF SL1 OF THE CHOSEN CHAMBER + GlobalPoint FirstWireGlobalUp = lay->chamber()->superLayer(upsl)->layer(4)->toGlobal(FirstWireLocalUp); + LocalPoint FirstWireLocalChUp = lay->chamber()->toLocal(FirstWireGlobalUp); + + xlowlim_ = FirstWireLocalCh.x() - lay->chamber()->superLayer(1)->layer(1)->specificTopology().cellWidth() / 2; + xhighlim_ = LastWireLocalCh.x() + lay->chamber()->superLayer(1)->layer(1)->specificTopology().cellWidth() / 2; + zlowlim_ = FirstWireLocalChUp.z() - lay->chamber()->superLayer(upsl)->layer(4)->specificTopology().cellHeight() / 2; + zhighlim_ = LastWireLocalCh.z() + lay->chamber()->superLayer(1)->layer(1)->specificTopology().cellHeight() / 2; + + spacebins_ = round(std::abs(xhighlim_ - xlowlim_) / posbinwidth_); +} + +void HoughGrouping::doHoughTransform() { + if (debug_) + LogDebug("HoughGrouping") << "DoHoughTransform"; + // First we want to obtain the number of bins in angle that we want. To do so, we will consider at first a maximum angle of + // (in rad.) pi/2 - arctan(0.3) (i.e. ~73º) and a resolution (width of bin angle) of 2º. + + if (debug_) { + LogDebug("HoughGrouping") << "DoHoughTransform - maxrads: " << maxrads_; + LogDebug("HoughGrouping") << "DoHoughTransform - minangle: " << minangle_; + LogDebug("HoughGrouping") << "DoHoughTransform - halfanglebins: " << halfanglebins_; + LogDebug("HoughGrouping") << "DoHoughTransform - anglebins: " << anglebins_; + LogDebug("HoughGrouping") << "DoHoughTransform - oneanglebin: " << oneanglebin_; + LogDebug("HoughGrouping") << "DoHoughTransform - spacebins: " << spacebins_; + } + + double rho = 0, phi = 0, sbx = 0; + double lowinitsb = xlowlim_ + posbinwidth_ / 2; + + // Initialisation + linespace_.resize(anglebins_, std::vector(spacebins_)); + for (unsigned short int ab = 0; ab < anglebins_; ab++) { + sbx = lowinitsb; + for (unsigned short int sb = 0; sb < spacebins_; sb++) { + posmap_[sb] = sbx; + linespace_[ab][sb] = 0; + sbx += posbinwidth_; + } + } + + // Filling of the double array and actually doing the transform + for (unsigned short int i = 0; i < hitvec_.size(); i++) { + for (unsigned short int ab = 0; ab < anglebins_; ab++) { + phi = anglemap_[ab]; + rho = hitvec_.at(i).first * cos(phi) + hitvec_.at(i).second * sin(phi); + sbx = lowinitsb - posbinwidth_ / 2; + for (unsigned short int sb = 0; sb < spacebins_; sb++) { + if (rho < sbx) { + linespace_[ab][sb]++; + break; + } + sbx += posbinwidth_; + } + } + } +} + +PointsInPlane HoughGrouping::getMaximaVector() { + if (debug_) + LogDebug("HoughGrouping") << "getMaximaVector"; + PointTuples tmpvec; + + bool flagsearched = false; + unsigned short int numbertolookat = upperNumber_; + + while (!flagsearched) { + for (unsigned short int ab = 0; ab < anglebins_; ab++) { + for (unsigned short int sb = 0; sb < spacebins_; sb++) { + if (linespace_[ab][sb] >= numbertolookat) + tmpvec.push_back({anglemap_[ab], posmap_[sb], linespace_[ab][sb]}); + } + } + if (((numbertolookat - 1) < lowerNumber_) || (!tmpvec.empty())) + flagsearched = true; + else + numbertolookat--; + } + + if (tmpvec.empty()) { + if (debug_) + LogDebug("HoughGrouping") << "GetMaximaVector - No maxima could be found"; + PointsInPlane finalvec; + return finalvec; + } else { + PointsInPlane finalvec = findTheMaxima(tmpvec); + + // And now obtain the values of m and n of the lines. + for (unsigned short int i = 0; i < finalvec.size(); i++) + finalvec.at(i) = transformPair(finalvec.at(i)); + return finalvec; + } +} + +PointInPlane HoughGrouping::transformPair(const PointInPlane& inputpair) { + if (debug_) + LogDebug("HoughGrouping") << "transformPair"; + // input: (ang, pos); output: (m, n) + if (inputpair.first == 0) + return {1000, -1000 * inputpair.second}; + else + return {-1. / tan(inputpair.first), inputpair.second / sin(inputpair.first)}; +} + +PointsInPlane HoughGrouping::findTheMaxima(PointTuples& inputvec) { + if (debug_) + LogDebug("HoughGrouping") << "findTheMaxima"; + bool fullyreduced = false; + unsigned short int ind = 0; + + std::vector chosenvec; + PointsInPlane resultvec; + PointInPlane finalpair = {}; + + if (debug_) + LogDebug("HoughGrouping") << "findTheMaxima - prewhile"; + while (!fullyreduced) { + if (debug_) { + LogDebug("HoughGrouping") << "\nHoughGrouping::findTheMaxima - New iteration"; + LogDebug("HoughGrouping") << "findTheMaxima - inputvec size: " << inputvec.size(); + LogDebug("HoughGrouping") << "findTheMaxima - ind: " << ind; + LogDebug("HoughGrouping") << "findTheMaxima - maximum deltaang: " << maxdeltaAng_ + << " and maximum deltapos: " << maxdeltaPos_; + } + chosenvec.clear(); + //calculate distances and check out the ones that are near + if (debug_) + LogDebug("HoughGrouping") << "findTheMaxima - Ours have " << get<2>(inputvec.at(ind)) + << " entries, ang.: " << get<0>(inputvec.at(ind)) + << " and pos.: " << get<1>(inputvec.at(ind)); + + for (unsigned short int j = ind + 1; j < inputvec.size(); j++) { + if (getTwoDelta(inputvec.at(ind), inputvec.at(j)).first <= maxdeltaAng_ && + getTwoDelta(inputvec.at(ind), inputvec.at(j)).second <= maxdeltaPos_) { + chosenvec.push_back(j); + if (debug_) + LogDebug("HoughGrouping") << "findTheMaxima - - Adding num. " << j + << " with deltaang: " << getTwoDelta(inputvec.at(ind), inputvec.at(j)).first + << ", and deltapos: " << getTwoDelta(inputvec.at(ind), inputvec.at(j)).second + << " and with " << get<2>(inputvec.at(j)) + << " entries, ang.: " << get<0>(inputvec.at(j)) + << " and pos.: " << get<1>(inputvec.at(j)); + } else if (debug_) + LogDebug("HoughGrouping") << "findTheMaxima - - Ignoring num. " << j + << " with deltaang: " << getTwoDelta(inputvec.at(ind), inputvec.at(j)).first + << ", and deltapos: " << getTwoDelta(inputvec.at(ind), inputvec.at(j)).second + << " and with " << get<2>(inputvec.at(j)) << " entries."; + } + + if (debug_) + LogDebug("HoughGrouping") << "findTheMaxima - chosenvecsize: " << chosenvec.size(); + + if (chosenvec.empty()) { + if (ind + 1 >= (unsigned short int)inputvec.size()) + fullyreduced = true; + if ((get<0>(inputvec.at(ind)) <= maxrads_) || (get<0>(inputvec.at(ind)) >= M_PI - maxrads_)) + resultvec.push_back({get<0>(inputvec.at(ind)), get<1>(inputvec.at(ind))}); + else if (debug_) + LogDebug("HoughGrouping") << "findTheMaxima - - Candidate dropped due to an excess in angle"; + ind++; + continue; + } + + // Now average them + finalpair = getAveragePoint(inputvec, ind, chosenvec); + + // Erase the ones you used + inputvec.erase(inputvec.begin() + ind); + for (short int j = chosenvec.size() - 1; j > -1; j--) { + if (debug_) + LogDebug("HoughGrouping") << "findTheMaxima - erasing index: " << chosenvec.at(j) - 1; + inputvec.erase(inputvec.begin() + chosenvec.at(j) - 1); + } + + if (debug_) + LogDebug("HoughGrouping") << "findTheMaxima - inputvec size: " << inputvec.size(); + + // And add the one you calculated: + if ((finalpair.first <= maxrads_) || (finalpair.first >= M_PI - maxrads_)) + resultvec.push_back(finalpair); + else if (debug_) + LogDebug("HoughGrouping") << "findTheMaxima - - Candidate dropped due to an excess in angle"; + + if (ind + 1 >= (unsigned short int)inputvec.size()) + fullyreduced = true; + if (debug_) + LogDebug("HoughGrouping") << "findTheMaxima - iteration ends"; + ind++; + } + if (debug_) + LogDebug("HoughGrouping") << "findTheMaxima - postwhile"; + return resultvec; +} + +PointInPlane HoughGrouping::getTwoDelta(const PointTuple& pair1, const PointTuple& pair2) { + if (debug_) + LogDebug("HoughGrouping") << "getTwoDelta"; + return {abs(get<0>(pair1) - get<0>(pair2)), abs(get<1>(pair1) - get<1>(pair2))}; +} + +PointInPlane HoughGrouping::getAveragePoint(const PointTuples& inputvec, + unsigned short int firstindex, + const std::vector& indexlist) { + if (debug_) + LogDebug("HoughGrouping") << "getAveragePoint"; + std::vector xs; + std::vector ys; + std::vector ws; + xs.push_back(get<0>(inputvec.at(firstindex))); + ys.push_back(get<1>(inputvec.at(firstindex))); + ws.push_back(exp(get<2>(inputvec.at(firstindex)))); + for (unsigned short int i = 0; i < indexlist.size(); i++) { + xs.push_back(get<0>(inputvec.at(indexlist.at(i)))); + ys.push_back(get<1>(inputvec.at(indexlist.at(i)))); + ws.push_back(exp(get<2>(inputvec.at(indexlist.at(i))))); + } + return {TMath::Mean(xs.begin(), xs.end(), ws.begin()), TMath::Mean(ys.begin(), ys.end(), ws.begin())}; +} + +ProtoCand HoughGrouping::associateHits(const DTChamber* thechamb, double m, double n) { + if (debug_) + LogDebug("HoughGrouping") << "associateHits"; + LocalPoint tmpLocal, AWireLocal, AWireLocalCh, tmpLocalCh, thepoint; + GlobalPoint tmpGlobal, AWireGlobal; + double tmpx = 0; + double distleft = 0; + double distright = 0; + unsigned short int tmpwire = 0; + unsigned short int abslay = 0; + LATERAL_CASES lat = NONE; + bool isleft = false; + bool isright = false; + + ProtoCand returnPC; + for (auto l = 0; l < NUM_LAYERS_2SL; l++) { + returnPC.isThereHitInLayer_.push_back(false); + returnPC.isThereNeighBourHitInLayer_.push_back(false); + returnPC.xDistToPattern_.push_back(0); + returnPC.dtHits_.push_back(DTPrimitive()); + } + + if (debug_) + LogDebug("HoughGrouping") << "associateHits - Beginning SL loop"; + for (unsigned short int sl = 1; sl < 3 + 1; sl++) { + if (sl == 2) + continue; + if (debug_) + LogDebug("HoughGrouping") << "associateHits - SL: " << sl; + + for (unsigned short int l = 1; l < 4 + 1; l++) { + if (debug_) + LogDebug("HoughGrouping") << "associateHits - L: " << l; + isleft = false; + isright = false; + lat = NONE; + distleft = 0; + distright = 0; + if (sl == 1) + abslay = l - 1; + else + abslay = l + 3; + AWireLocal = LocalPoint(thechamb->superLayer(sl)->layer(l)->specificTopology().wirePosition( + thechamb->superLayer(sl)->layer(l)->specificTopology().firstChannel()), + 0, + 0); + AWireGlobal = thechamb->superLayer(sl)->layer(l)->toGlobal(AWireLocal); + AWireLocalCh = thechamb->toLocal(AWireGlobal); + tmpx = (AWireLocalCh.z() - n) / m; + + if ((tmpx <= xlowlim_) || (tmpx >= xhighlim_)) { + returnPC.dtHits_[abslay] = DTPrimitive(); // empty primitive + continue; + } + + thepoint = LocalPoint(tmpx, 0, AWireLocalCh.z()); + tmpwire = thechamb->superLayer(sl)->layer(l)->specificTopology().channel(thepoint); + if (debug_) + LogDebug("HoughGrouping") << "associateHits - Wire number: " << tmpwire; + if (debug_) + LogDebug("HoughGrouping") << "associateHits - First channel in layer: " + << thechamb->superLayer(sl)->layer(l)->specificTopology().firstChannel(); + if ((digimap_[abslay]).count(tmpwire)) { + // OK, we have a digi, let's choose the laterality, if we can: + tmpLocal = LocalPoint(thechamb->superLayer(sl)->layer(l)->specificTopology().wirePosition(tmpwire), 0, 0); + tmpGlobal = thechamb->superLayer(sl)->layer(l)->toGlobal(tmpLocal); + tmpLocalCh = thechamb->toLocal(tmpGlobal); + + if (abs(tmpLocalCh.x() - thepoint.x()) >= maxDistanceToWire_) { + // The distance where lateralities are not put is 0.03 cm, which is a conservative threshold for the resolution of the cells. + if ((tmpLocalCh.x() - thepoint.x()) > 0) + lat = LEFT; + else + lat = RIGHT; + } + + // Filling info + returnPC.nLayersWithHits_++; + returnPC.isThereHitInLayer_[abslay] = true; + returnPC.isThereNeighBourHitInLayer_[abslay] = true; + if (lat == LEFT) + returnPC.xDistToPattern_[abslay] = abs(tmpx - (tmpLocalCh.x() - 1.05)); + else if (lat == RIGHT) + returnPC.xDistToPattern_[abslay] = abs(tmpx - (tmpLocalCh.x() + 1.05)); + else + returnPC.xDistToPattern_[abslay] = abs(tmpx - tmpLocalCh.x()); + returnPC.dtHits_[abslay] = DTPrimitive(digimap_[abslay][tmpwire]); + returnPC.dtHits_[abslay].setLaterality(lat); + } else { + if (debug_) + LogDebug("HoughGrouping") << "associateHits - No hit in the crossing cell"; + if ((digimap_[abslay]).count(tmpwire - 1)) + isleft = true; + if ((digimap_[abslay]).count(tmpwire + 1)) + isright = true; + if (debug_) + LogDebug("HoughGrouping") << "associateHits - There is in the left: " << (int)isleft; + if (debug_) + LogDebug("HoughGrouping") << "associateHits - There is in the right: " << (int)isright; + + if ((isleft) && (!isright)) { + tmpLocal = LocalPoint(thechamb->superLayer(sl)->layer(l)->specificTopology().wirePosition(tmpwire - 1), 0, 0); + tmpGlobal = thechamb->superLayer(sl)->layer(l)->toGlobal(tmpLocal); + tmpLocalCh = thechamb->toLocal(tmpGlobal); + + // Filling info + returnPC.nLayersWithHits_++; + returnPC.isThereNeighBourHitInLayer_[abslay] = true; + returnPC.xDistToPattern_[abslay] = abs(tmpx - (tmpLocalCh.x() + 1.05)); + returnPC.dtHits_[abslay] = DTPrimitive(digimap_[abslay][tmpwire - 1]); + returnPC.dtHits_[abslay].setLaterality(RIGHT); + + } else if ((!isleft) && (isright)) { + tmpLocal = LocalPoint(thechamb->superLayer(sl)->layer(l)->specificTopology().wirePosition(tmpwire + 1), 0, 0); + tmpGlobal = thechamb->superLayer(sl)->layer(l)->toGlobal(tmpLocal); + tmpLocalCh = thechamb->toLocal(tmpGlobal); + + // Filling info + returnPC.nLayersWithHits_++; + returnPC.isThereNeighBourHitInLayer_[abslay] = true; + returnPC.xDistToPattern_[abslay] = abs(tmpx - (tmpLocalCh.x() - 1.05)); + returnPC.dtHits_[abslay] = DTPrimitive(digimap_[abslay][tmpwire + 1]); + returnPC.dtHits_[abslay].setLaterality(LEFT); + } else if ((isleft) && (isright)) { + LocalPoint tmpLocal_l = + LocalPoint(thechamb->superLayer(sl)->layer(l)->specificTopology().wirePosition(tmpwire - 1), 0, 0); + GlobalPoint tmpGlobal_l = thechamb->superLayer(sl)->layer(l)->toGlobal(tmpLocal_l); + LocalPoint tmpLocalCh_l = thechamb->toLocal(tmpGlobal_l); + + LocalPoint tmpLocal_r = + LocalPoint(thechamb->superLayer(sl)->layer(l)->specificTopology().wirePosition(tmpwire + 1), 0, 0); + GlobalPoint tmpGlobal_r = thechamb->superLayer(sl)->layer(l)->toGlobal(tmpLocal_r); + LocalPoint tmpLocalCh_r = thechamb->toLocal(tmpGlobal_r); + + distleft = std::abs(thepoint.x() - tmpLocalCh_l.x()); + distright = std::abs(thepoint.x() - tmpLocalCh_r.x()); + + // Filling info + returnPC.nLayersWithHits_++; + returnPC.isThereNeighBourHitInLayer_[abslay] = true; + + returnPC.xDistToPattern_[abslay] = abs(tmpx - (tmpLocalCh.x() - 1.05)); + returnPC.dtHits_[abslay] = DTPrimitive(digimap_[abslay][tmpwire + 1]); + returnPC.dtHits_[abslay].setLaterality(LEFT); + + if (distleft < distright) { + returnPC.xDistToPattern_[abslay] = std::abs(tmpx - (tmpLocalCh.x() + 1.05)); + returnPC.dtHits_[abslay] = DTPrimitive(digimap_[abslay][tmpwire - 1]); + returnPC.dtHits_[abslay].setLaterality(RIGHT); + } else { + returnPC.xDistToPattern_[abslay] = std::abs(tmpx - (tmpLocalCh.x() - 1.05)); + returnPC.dtHits_[abslay] = DTPrimitive(digimap_[abslay][tmpwire + 1]); + returnPC.dtHits_[abslay].setLaterality(LEFT); + } + } else { // case where there are no digis + returnPC.dtHits_[abslay] = DTPrimitive(); // empty primitive + } + } + } + } + + setDifferenceBetweenSL(returnPC); + if (debug_) { + LogDebug("HoughGrouping") << "associateHits - Finishing with the candidate. We have found the following of it:"; + LogDebug("HoughGrouping") << "associateHits - # of layers with hits: " << returnPC.nLayersWithHits_; + for (unsigned short int lay = 0; lay < 8; lay++) { + LogDebug("HoughGrouping") << "associateHits - For absolute layer: " << lay; + LogDebug("HoughGrouping") << "associateHits - # of HQ hits: " << returnPC.isThereHitInLayer_[lay]; + LogDebug("HoughGrouping") << "associateHits - # of LQ hits: " << returnPC.isThereNeighBourHitInLayer_[lay]; + } + LogDebug("HoughGrouping") << "associateHits - Abs. diff. between SL1 and SL3 hits: " << returnPC.nHitsDiff_; + for (unsigned short int lay = 0; lay < 8; lay++) { + LogDebug("HoughGrouping") << "associateHits - For absolute layer: " << lay; + LogDebug("HoughGrouping") << "associateHits - Abs. distance to digi: " << returnPC.xDistToPattern_[lay]; + } + } + return returnPC; +} + +void HoughGrouping::setDifferenceBetweenSL(ProtoCand& tupl) { + if (debug_) + LogDebug("HoughGrouping") << "setDifferenceBetweenSL"; + short int absres = 0; + for (unsigned short int lay = 0; lay < 8; lay++) { + if (tupl.dtHits_[lay].channelId() > 0) { + if (lay <= 3) + absres++; + else + absres--; + } + } + + if (absres >= 0) + tupl.nHitsDiff_ = absres; + else + tupl.nHitsDiff_ = (unsigned short int)(-absres); +} + +void HoughGrouping::orderAndFilter(std::vector& invector, MuonPathPtrs& outMuonPath) { + if (debug_) + LogDebug("HoughGrouping") << "orderAndFilter"; + // 0: # of layers with hits. + // 1: # of hits of high quality (the expected line crosses the cell). + // 2: # of hits of low quality (the expected line is in a neighbouring cell). + // 3: absolute diff. between the number of hits in SL1 and SL3. + // 4: absolute distance to all hits of the segment. + // 5: DTPrimitive of the candidate. + + std::vector elstoremove; + // ordering: + if (debug_) + LogDebug("HoughGrouping") << "orderAndFilter - First ordering"; + std::sort(invector.begin(), invector.end(), HoughOrdering); + + // Now filtering: + unsigned short int ind = 0; + bool filtered = false; + if (debug_) + LogDebug("HoughGrouping") << "orderAndFilter - Entering while"; + while (!filtered) { + if (debug_) + LogDebug("HoughGrouping") << "\nHoughGrouping::orderAndFilter - New iteration with ind: " << ind; + elstoremove.clear(); + for (unsigned short int i = ind + 1; i < invector.size(); i++) { + if (debug_) + LogDebug("HoughGrouping") << "orderAndFilter - Checking index: " << i; + for (unsigned short int lay = 0; lay < 8; lay++) { + if (debug_) + LogDebug("HoughGrouping") << "orderAndFilter - Checking layer number: " << lay; + if (invector.at(i).dtHits_[lay].channelId() == invector.at(ind).dtHits_[lay].channelId() && + invector.at(ind).dtHits_[lay].channelId() != -1) { + invector.at(i).nLayersWithHits_--; + invector.at(i).isThereHitInLayer_[lay] = false; + invector.at(i).isThereNeighBourHitInLayer_[lay] = false; + setDifferenceBetweenSL(invector.at(i)); + // We check that if its a different laterality, the best candidate of the two of them changes its laterality to not-known (that is, both). + if (invector.at(i).dtHits_[lay].laterality() != invector.at(ind).dtHits_[lay].laterality()) + invector.at(ind).dtHits_[lay].setLaterality(NONE); + + invector.at(i).dtHits_[lay] = DTPrimitive(); + } + } + if (debug_) + LogDebug("HoughGrouping") + << "orderAndFilter - Finished checking all the layers, now seeing if we should remove the " + "candidate"; + + if (!areThereEnoughHits(invector.at(i))) { + if (debug_) + LogDebug("HoughGrouping") << "orderAndFilter - This candidate shall be removed!"; + elstoremove.push_back((unsigned short int)i); + } + } + + if (debug_) + LogDebug("HoughGrouping") << "orderAndFilter - We are gonna erase " << elstoremove.size() << " elements"; + + for (short int el = (elstoremove.size() - 1); el > -1; el--) { + invector.erase(invector.begin() + elstoremove.at(el)); + } + + if (ind + 1 == (unsigned short int)invector.size()) + filtered = true; + else + std::sort(invector.begin() + ind + 1, invector.end(), HoughOrdering); + ind++; + } + + // Ultimate filter: if the remaining do not fill the requirements (configurable through pset arguments), they are removed also. + for (short int el = (invector.size() - 1); el > -1; el--) { + if (!areThereEnoughHits(invector.at(el))) { + invector.erase(invector.begin() + el); + } + } + + if (invector.empty()) { + if (debug_) + LogDebug("HoughGrouping") << "OrderAndFilter - We do not have candidates with the minimum hits required."; + return; + } else if (debug_) + LogDebug("HoughGrouping") << "OrderAndFilter - At the end, we have only " << invector.size() << " good paths!"; + + // Packing dt primitives + for (unsigned short int i = 0; i < invector.size(); i++) { + DTPrimitivePtrs ptrPrimitive; + unsigned short int tmplowfill = 0; + unsigned short int tmpupfill = 0; + for (unsigned short int lay = 0; lay < 8; lay++) { + auto dtAux = std::make_shared(invector.at(i).dtHits_[lay]); + ptrPrimitive.push_back(std::move(dtAux)); + if (debug_) { + LogDebug("HoughGrouping") << "\nHoughGrouping::OrderAndFilter - cameraid: " << ptrPrimitive[lay]->cameraId(); + LogDebug("HoughGrouping") << "OrderAndFilter - channelid (GOOD): " << ptrPrimitive[lay]->channelId(); + LogDebug("HoughGrouping") << "OrderAndFilter - channelid (AM): " << ptrPrimitive[lay]->channelId() - 1; + } + // Fixing channel ID to AM conventions... + if (ptrPrimitive[lay]->channelId() != -1) + ptrPrimitive[lay]->setChannelId(ptrPrimitive[lay]->channelId() - 1); + + if (ptrPrimitive[lay]->cameraId() > 0) { + if (lay < 4) + tmplowfill++; + else + tmpupfill++; + } + } + + auto ptrMuonPath = std::make_shared(ptrPrimitive, tmplowfill, tmpupfill); + outMuonPath.push_back(ptrMuonPath); + if (debug_) { + for (unsigned short int lay = 0; lay < 8; lay++) { + LogDebug("HoughGrouping") << "OrderAndFilter - Final cameraID: " + << outMuonPath.back()->primitive(lay)->cameraId(); + LogDebug("HoughGrouping") << "OrderAndFilter - Final channelID: " + << outMuonPath.back()->primitive(lay)->channelId(); + LogDebug("HoughGrouping") << "OrderAndFilter - Final time: " + << outMuonPath.back()->primitive(lay)->tdcTimeStamp(); + } + } + } + return; +} + +bool HoughGrouping::areThereEnoughHits(const ProtoCand& tupl) { + if (debug_) + LogDebug("HoughGrouping") << "areThereEnoughHits"; + unsigned short int numhitssl1 = 0; + unsigned short int numhitssl3 = 0; + for (unsigned short int lay = 0; lay < 8; lay++) { + if ((tupl.dtHits_[lay].channelId() > 0) && (lay < 4)) + numhitssl1++; + else if (tupl.dtHits_[lay].channelId() > 0) + numhitssl3++; + } + + if (debug_) + LogDebug("HoughGrouping") << "areThereEnoughHits - Hits in SL1: " << numhitssl1; + if (debug_) + LogDebug("HoughGrouping") << "areThereEnoughHits - Hits in SL3: " << numhitssl3; + + if ((numhitssl1 != 0) && (numhitssl3 != 0)) { // Correlated candidates + if ((numhitssl1 + numhitssl3) >= minNLayerHits_) { + if (numhitssl1 > numhitssl3) { + return ((numhitssl1 >= minSingleSLHitsMax_) && (numhitssl3 >= minSingleSLHitsMin_)); + } else if (numhitssl3 > numhitssl1) { + return ((numhitssl3 >= minSingleSLHitsMax_) && (numhitssl1 >= minSingleSLHitsMin_)); + } else + return true; + } + } else if (allowUncorrelatedPatterns_) { // Uncorrelated candidates + return ((numhitssl1 + numhitssl3) >= minNLayerHits_); + } + return false; +} diff --git a/L1Trigger/DTTriggerPhase2/src/InitialGrouping.cc b/L1Trigger/DTTriggerPhase2/src/InitialGrouping.cc new file mode 100644 index 0000000000000..9f45dde0550dc --- /dev/null +++ b/L1Trigger/DTTriggerPhase2/src/InitialGrouping.cc @@ -0,0 +1,349 @@ +#include + +#include "FWCore/MessageLogger/interface/MessageLogger.h" + +#include "L1Trigger/DTTriggerPhase2/interface/InitialGrouping.h" + +using namespace edm; +using namespace std; +using namespace cmsdt; +using namespace dtamgrouping; +// ============================================================================ +// Constructors and destructor +// ============================================================================ +InitialGrouping::InitialGrouping(const ParameterSet &pset, edm::ConsumesCollector &iC) + : MotherGrouping(pset, iC), currentBaseChannel_(-1) { + // Obtention of parameters + debug_ = pset.getUntrackedParameter("debug"); + if (debug_) + LogDebug("InitialGrouping") << "InitialGrouping: constructor"; + + // Initialisation of channelIn array + chInDummy_.push_back(DTPrimitive()); + for (int lay = 0; lay < NUM_LAYERS; lay++) { + for (int ch = 0; ch < NUM_CH_PER_LAYER; ch++) { + channelIn_[lay][ch] = {chInDummy_}; + channelIn_[lay][ch].clear(); + } + } +} + +InitialGrouping::~InitialGrouping() { + if (debug_) + LogDebug("InitialGrouping") << "InitialGrouping: destructor"; +} + +// ============================================================================ +// Main methods (initialise, run, finish) +// ============================================================================ +void InitialGrouping::initialise(const edm::EventSetup &iEventSetup) { + if (debug_) + LogDebug("InitialGrouping") << "InitialGrouping::initialiase"; +} + +void InitialGrouping::run(Event &iEvent, + const EventSetup &iEventSetup, + const DTDigiCollection &digis, + MuonPathPtrs &mpaths) { + // This function returns the analyzable mpath collection back to the the main function + // so it can be fitted. This is in fact doing the so-called grouping. + + for (int supLayer = 0; supLayer < NUM_SUPERLAYERS; supLayer++) { // for each SL: + if (debug_) + LogDebug("InitialGrouping") << "InitialGrouping::run Reading SL" << supLayer; + setInChannels(&digis, supLayer); + + for (int baseCh = 0; baseCh < TOTAL_BTI; baseCh++) { + currentBaseChannel_ = baseCh; + selectInChannels(currentBaseChannel_); //map a number of wires for a given base channel + if (notEnoughDataInChannels()) + continue; + + if (debug_) + LogDebug("InitialGrouping") << "InitialGrouping::run --> now check pathId"; + for (int pathId = 0; pathId < 8; pathId++) { + resetPrvTDCTStamp(); + if (debug_) + LogDebug("InitialGrouping") << "[InitialGrouping::run] mixChannels calling"; + mixChannels(supLayer, pathId, mpaths); + if (debug_) + LogDebug("InitialGrouping") << "[InitialGrouping::run] mixChannels end"; + } + } + } + if (debug_) + LogDebug("InitialGrouping") << "[InitialGrouping::run] end"; +} + +void InitialGrouping::finish() { return; }; + +// ============================================================================ +// Other methods +// ============================================================================ +void InitialGrouping::setInChannels(const DTDigiCollection *digis, int sl) { + // before setting channels we need to clear + for (int lay = 0; lay < NUM_LAYERS; lay++) { + for (int ch = 0; ch < NUM_CH_PER_LAYER; ch++) { + channelIn_[lay][ch].clear(); + } + } + + // now fill with those primitives that makes sense: + for (const auto &dtLayerId_It : *digis) { + const DTLayerId dtLId = dtLayerId_It.first; + if (dtLId.superlayer() != sl + 1) + continue; //skip digis not in SL... + + for (DTDigiCollection::const_iterator digiIt = (dtLayerId_It.second).first; digiIt != (dtLayerId_It.second).second; + ++digiIt) { + int layer = dtLId.layer() - 1; + int wire = (*digiIt).wire() - 1; + int digiTIME = (*digiIt).time(); + int digiTIMEPhase2 = digiTIME; + + if (debug_) + LogDebug("InitialGrouping") << "[InitialGrouping::setInChannels] SL" << sl << " L" << layer << " : " << wire + << " " << digiTIMEPhase2; + auto dtpAux = DTPrimitive(); + dtpAux.setTDCTimeStamp(digiTIMEPhase2); + dtpAux.setChannelId(wire); + dtpAux.setLayerId(layer); // L=0,1,2,3 + dtpAux.setSuperLayerId(sl); // SL=0,1,2 + dtpAux.setCameraId(dtLId.rawId()); + channelIn_[layer][wire].push_back(dtpAux); + } + } +} + +void InitialGrouping::selectInChannels(int baseChannel) { + // Channels are labeled following next schema: + // Input Muxer Indexes + // --------------------------------- + // | 6 | 7 | 8 | 9 | + // --------------------------------- + // | 3 | 4 | 5 | + // ------------------------- + // | 1 | 2 | + // ----------------- + // | 0 | + // --------- + + // ****** LAYER 0 ****** + muxInChannels_[0] = channelIn_[0][baseChannel]; + + // ****** LAYER 1 ****** + muxInChannels_[1] = channelIn_[1][baseChannel]; + + if (baseChannel + 1 < NUM_CH_PER_LAYER) + muxInChannels_[2] = channelIn_[1][baseChannel + 1]; + else + muxInChannels_[2] = chInDummy_; + + // ****** LAYER 2 ****** + if (baseChannel - 1 >= 0) + muxInChannels_[3] = channelIn_[2][baseChannel - 1]; + else + muxInChannels_[3] = chInDummy_; + + muxInChannels_[4] = channelIn_[2][baseChannel]; + + if (baseChannel + 1 < NUM_CH_PER_LAYER) + muxInChannels_[5] = channelIn_[2][baseChannel + 1]; + else + muxInChannels_[5] = chInDummy_; + + // ****** LAYER 3 ****** + if (baseChannel - 1 >= 0) + muxInChannels_[6] = channelIn_[3][baseChannel - 1]; + else + muxInChannels_[6] = chInDummy_; + + muxInChannels_[7] = channelIn_[3][baseChannel]; + + if (baseChannel + 1 < NUM_CH_PER_LAYER) + muxInChannels_[8] = channelIn_[3][baseChannel + 1]; + else + muxInChannels_[8] = chInDummy_; + + if (baseChannel + 2 < NUM_CH_PER_LAYER) + muxInChannels_[9] = channelIn_[3][baseChannel + 2]; + else + muxInChannels_[9] = chInDummy_; +} + +bool InitialGrouping::notEnoughDataInChannels(void) { + // Empty layer indicators + bool lEmpty[4]; + + lEmpty[0] = muxInChannels_[0].empty(); + + lEmpty[1] = muxInChannels_[1].empty() && muxInChannels_[2].empty(); + + lEmpty[2] = muxInChannels_[3].empty() && muxInChannels_[4].empty() && muxInChannels_[5].empty(); + + lEmpty[3] = + muxInChannels_[6].empty() && muxInChannels_[7].empty() && muxInChannels_[8].empty() && muxInChannels_[9].empty(); + + // If there are at least two empty layers, you cannot link it to a possible trace + if ((lEmpty[0] && lEmpty[1]) or (lEmpty[0] && lEmpty[2]) or (lEmpty[0] && lEmpty[3]) or (lEmpty[1] && lEmpty[2]) or + (lEmpty[1] && lEmpty[3]) or (lEmpty[2] && lEmpty[3])) { + return true; + } else { + return false; + } +} + +void InitialGrouping::resetPrvTDCTStamp(void) { + for (int i = 0; i < NUM_LAYERS; i++) + prevTDCTimeStamps_[i] = -1; +} + +bool InitialGrouping::isEqualComb2Previous(DTPrimitives &dtPrims) { + bool answer = true; + + for (int i = 0; i < NUM_LAYERS; i++) { + if (prevTDCTimeStamps_[i] != dtPrims[i].tdcTimeStamp()) { + answer = false; + for (int j = 0; j < NUM_LAYERS; j++) { + prevTDCTimeStamps_[j] = dtPrims[j].tdcTimeStamp(); + } + break; + } + } + return answer; +} + +void InitialGrouping::mixChannels(int supLayer, int pathId, MuonPathPtrs &outMuonPath) { + if (debug_) + LogDebug("InitialGrouping") << "[InitialGrouping::mixChannel] begin"; + DTPrimitives data[4]; + + // Real amount of values extracted from each channel. + int numPrimsPerLayer[4] = {0, 0, 0, 0}; + unsigned int canal; + int channelEmptyCnt = 0; + for (int layer = 0; layer <= 3; layer++) { + canal = CHANNELS_PATH_ARRANGEMENTS[pathId][layer]; + if (muxInChannels_[canal].empty()) + channelEmptyCnt++; + } + + if (channelEmptyCnt >= 2) + return; + // + + // We extract the number of elements necesary from each channel as the combination requires + for (int layer = 0; layer < NUM_LAYERS; layer++) { + canal = CHANNELS_PATH_ARRANGEMENTS[pathId][layer]; + unsigned int maxPrimsToBeRetrieved = muxInChannels_[canal].size(); + /* + If the number of primitives is zero, in order to avoid that only one + empty channel avoids mixing data from the other three, we, at least, + consider one dummy element from this channel. + In other cases, where two or more channels has zero elements, the final + combination will be not analyzable (the condition for being analyzable is + that it has at least three good TDC time values, not dummy), so it will + be discarded and not sent to the analyzer. + */ + if (maxPrimsToBeRetrieved == 0) + maxPrimsToBeRetrieved = 1; + + for (unsigned int items = 0; items < maxPrimsToBeRetrieved; items++) { + auto dtpAux = DTPrimitive(); + if (!muxInChannels_[canal].empty()) + dtpAux = DTPrimitive(&(muxInChannels_[canal].at(items))); + + /* + I won't allow a whole loop cycle. When a DTPrimitive has an invalid + time-stamp (TDC value = -1) it means that the buffer is empty or the + buffer has reached the last element within the configurable time window. + In this case the loop is broken, but only if there is, at least, one + DTPrim (even invalid) on the outgoing array. This is mandatory to cope + with the idea explained in the previous comment block + */ + if (dtpAux.tdcTimeStamp() < 0 && items > 0) + break; + + // In this new schema, if the hit corresponds with the SL over which + // you are doing the mixings, it is sent to the intermediate mixing + // buffer. In the opposite case, a blank and invalid copy is sent to + // allow them mixing to be complete, as it was done in the one SL case. + + // This is a kind of quick solution in which there will be no few cases + // where you will have invalid mixings. Because of that, the verification + // that is done later, where the segment is analysed to check whether it + // can be analysed is essential. + if (dtpAux.superLayerId() == supLayer) + data[layer].push_back(dtpAux); // values are 0, 1, 2 + else + data[layer].push_back(DTPrimitive()); + numPrimsPerLayer[layer]++; + } + } + + if (debug_) + LogDebug("InitialGrouping") << "[InitialGrouping::mixChannels] filled data"; + + // Here we do the different combinations and send them to the output FIFO. + DTPrimitives ptrPrimitive; + int chIdx[4]; + for (chIdx[0] = 0; chIdx[0] < numPrimsPerLayer[0]; chIdx[0]++) { + for (chIdx[1] = 0; chIdx[1] < numPrimsPerLayer[1]; chIdx[1]++) { + for (chIdx[2] = 0; chIdx[2] < numPrimsPerLayer[2]; chIdx[2]++) { + for (chIdx[3] = 0; chIdx[3] < numPrimsPerLayer[3]; chIdx[3]++) { + // We build a copy of the object so that we can manipulate each one + // in each thread of the process independently, allowing us also to + // delete them whenever it is necessary, without relying upon a + // unique reference all over the code. + + for (int i = 0; i < NUM_LAYERS; i++) { + ptrPrimitive.push_back((data[i])[chIdx[i]]); + if (debug_) + LogDebug("InitialGrouping") + << "[InitialGrouping::mixChannels] reading " << ptrPrimitive[i].tdcTimeStamp(); + } + + auto ptrMuonPath = std::make_shared(ptrPrimitive); + ptrMuonPath->setCellHorizontalLayout(CELL_HORIZONTAL_LAYOUTS[pathId]); + + /* + This new version of this code is redundant with PathAnalyzer code, + where every MuonPath not analyzable is discarded. + I insert this discarding mechanism here, as well, to avoid inserting + not-analyzable MuonPath into the candidate FIFO. + Equivalent code must be removed in the future from PathAnalyzer, but + it the mean time, at least during the testing state, I'll preserve + both. + Code in the PathAnalyzer should be doing nothing now. + */ + if (debug_) + LogDebug("InitialGrouping") << "[InitialGrouping::mixChannels] muonPath is analyzable? " << ptrMuonPath; + if (ptrMuonPath->isAnalyzable()) { + if (debug_) + LogDebug("InitialGrouping") << "[InitialGrouping::mixChannels] YES"; + /* + This is a very simple filter because, during the tests, it has been + detected that many consecutive MuonPaths are duplicated mainly due + to buffers empty (or dummy) that give a TDC time-stamp = -1 + With this filter, I'm removing those consecutive identical + combinations. + + If duplicated combinations are not consecutive, they won't be + detected here + */ + if (!isEqualComb2Previous(ptrPrimitive)) { + if (debug_) + LogDebug("InitialGrouping") << "[InitialGrouping::mixChannels] isNOT equal to previous"; + ptrMuonPath->setBaseChannelId(currentBaseChannel_); + outMuonPath.push_back(std::move(ptrMuonPath)); + } + ptrPrimitive.clear(); + } + } + } + } + } + for (int layer = 0; layer < NUM_LAYERS; layer++) { + data[layer].clear(); + } +} diff --git a/L1Trigger/DTTriggerPhase2/src/MPFilter.cc b/L1Trigger/DTTriggerPhase2/src/MPFilter.cc new file mode 100644 index 0000000000000..8cae5a7884a88 --- /dev/null +++ b/L1Trigger/DTTriggerPhase2/src/MPFilter.cc @@ -0,0 +1,14 @@ +#include "L1Trigger/DTTriggerPhase2/interface/MPFilter.h" + +using namespace edm; +using namespace std; + +// ============================================================================ +// Constructors and destructor +// ============================================================================ +MPFilter::MPFilter(const ParameterSet& pset) { + // Obtention of parameters + debug_ = pset.getUntrackedParameter("debug"); +} + +MPFilter::~MPFilter() {} diff --git a/L1Trigger/DTTriggerPhase2/src/MPQualityEnhancerFilter.cc b/L1Trigger/DTTriggerPhase2/src/MPQualityEnhancerFilter.cc new file mode 100644 index 0000000000000..4ce76b41c6042 --- /dev/null +++ b/L1Trigger/DTTriggerPhase2/src/MPQualityEnhancerFilter.cc @@ -0,0 +1,237 @@ +#include "L1Trigger/DTTriggerPhase2/interface/MPQualityEnhancerFilter.h" +#include "FWCore/MessageLogger/interface/MessageLogger.h" + +using namespace edm; +using namespace std; +using namespace cmsdt; +; + +// ============================================================================ +// Constructors and destructor +// ============================================================================ +MPQualityEnhancerFilter::MPQualityEnhancerFilter(const ParameterSet &pset) : MPFilter(pset) { + // Obtention of parameters + debug_ = pset.getUntrackedParameter("debug"); + filter_cousins_ = pset.getUntrackedParameter("filter_cousins"); +} + +MPQualityEnhancerFilter::~MPQualityEnhancerFilter() {} + +// ============================================================================ +// Main methods (initialise, run, finish) +// ============================================================================ +void MPQualityEnhancerFilter::initialise(const edm::EventSetup &iEventSetup) {} + +void MPQualityEnhancerFilter::run(edm::Event &iEvent, + const edm::EventSetup &iEventSetup, + std::vector &inMPaths, + std::vector &outMPaths) { + std::vector buff; + std::vector buff2; + + filterCousins(inMPaths, buff); + if (debug_) { + LogDebug("MPQualityEnhancerFilter") << "Ended Cousins Filter. The final primitives before Refiltering are: "; + for (unsigned int i = 0; i < buff.size(); i++) { + printmP(buff[i]); + } + LogDebug("MPQualityEnhancerFilter") << "Total Primitives = " << buff.size(); + } + refilteringCousins(buff, buff2); + if (debug_) { + LogDebug("MPQualityEnhancerFilter") << "Ended Cousins Refilter. The final primitives before UniqueFilter are: "; + for (unsigned int i = 0; i < buff2.size(); i++) { + printmP(buff2[i]); + } + LogDebug("MPQualityEnhancerFilter") << "Total Primitives = " << buff2.size(); + } + filterUnique(buff2, outMPaths); + + if (debug_) { + LogDebug("MPQualityEnhancerFilter") << "Ended Unique Filter. The final primitives are: "; + for (unsigned int i = 0; i < outMPaths.size(); i++) { + printmP(outMPaths[i]); + LogDebug("MPQualityEnhancerFilter"); + } + LogDebug("MPQualityEnhancerFilter") << "Total Primitives = " << outMPaths.size(); + } + + buff.clear(); + buff2.clear(); +} + +void MPQualityEnhancerFilter::finish(){}; + +/////////////////////////// +/// OTHER METHODS +int MPQualityEnhancerFilter::areCousins(metaPrimitive mp, metaPrimitive second_mp) { + if (mp.rawId != second_mp.rawId) + return 0; + if (mp.wi1 == second_mp.wi1 and mp.wi1 != -1 and mp.tdc1 != -1) + return 1; + if (mp.wi2 == second_mp.wi2 and mp.wi2 != -1 and mp.tdc2 != -1) + return 2; + if (mp.wi3 == second_mp.wi3 and mp.wi3 != -1 and mp.tdc3 != -1) + return 3; + if (mp.wi4 == second_mp.wi4 and mp.wi4 != -1 and mp.tdc4 != -1) + return 4; + return 0; +} + +int MPQualityEnhancerFilter::rango(metaPrimitive mp) { + if (mp.quality == 1 or mp.quality == 2) + return 3; + if (mp.quality == 3 or mp.quality == 4) + return 4; + return 0; +} + +void MPQualityEnhancerFilter::filterCousins(std::vector &inMPaths, + std::vector &outMPaths) { + int primo_index = 0; + bool oneof4 = false; + int bestI = -1; + double bestChi2 = 9999; + if (inMPaths.size() == 1) { + if (debug_) { + printmP(inMPaths[0]); + } + outMPaths.push_back(inMPaths[0]); + } else if (inMPaths.size() > 1) { + for (int i = 0; i < int(inMPaths.size()); i++) { + if (debug_) { + printmP(inMPaths[i]); + } + if (areCousins(inMPaths[i], inMPaths[i - primo_index]) == 0) { + if (oneof4) { + outMPaths.push_back(inMPaths[bestI]); + + bestI = -1; + bestChi2 = 9999; + oneof4 = false; + } else { + for (int j = i - primo_index; j < i; j++) { + outMPaths.push_back(inMPaths[j]); + } + } + i--; + primo_index = 0; + continue; + } + if (rango(inMPaths[i]) == 4) { + oneof4 = true; + if (bestChi2 > inMPaths[i].chi2) { + bestChi2 = inMPaths[i].chi2; + bestI = i; + } + } + if (areCousins(inMPaths[i], inMPaths[i + 1]) != 0) { + primo_index++; + } else { //areCousing==0 + if (oneof4) { + outMPaths.push_back(inMPaths[bestI]); + bestI = -1; + bestChi2 = 9999; + oneof4 = false; + } else { + for (int j = i - primo_index; j <= i; j++) { + outMPaths.push_back(inMPaths[j]); + } + } + primo_index = 0; + } + } + } + +} //End filterCousins + +void MPQualityEnhancerFilter::refilteringCousins(std::vector &inMPaths, + std::vector &outMPaths) { + if (debug_) + std::cout << "filtering: starting cousins refiltering" << std::endl; + int bestI = -1; + double bestChi2 = 9999; + bool oneOf4 = false; + int back = 0; + + if (inMPaths.size() > 1) { + for (unsigned int i = 0; i < inMPaths.size(); i++) { + if (debug_) { + LogDebug("MPQualityEnhancerFilter") << "filtering: starting with mp " << i << ": "; + printmP(inMPaths[i]); + LogDebug("MPQualityEnhancerFilter"); + } + if (rango(inMPaths[i]) == 4 && bestChi2 > inMPaths[i].chi2) { // 4h prim with a smaller chi2 + if (debug_) { + LogDebug("MPQualityEnhancerFilter") << "filtering: mp " << i << " is the best 4h primitive"; + } + oneOf4 = true; + bestI = i; + bestChi2 = inMPaths[i].chi2; + } + if (i == inMPaths.size() - 1) { //You can't compare the last one with the next one + if (oneOf4) { + outMPaths.push_back(inMPaths[bestI]); + } else { + for (unsigned int j = i - back; j <= i; j++) { + outMPaths.push_back(inMPaths[j]); + } + } + } else { + if (areCousins(inMPaths[i], inMPaths[i + 1]) == 0) { //they arent cousins + if (debug_) { + LogDebug("MPQualityEnhancerFilter") << "mp " << i << " and mp " << i + 1 << " are not cousins"; + } + if (oneOf4) { + outMPaths.push_back(inMPaths[bestI]); + if (debug_) + LogDebug("MPQualityEnhancerFilter") << "kept4 mp " << bestI; + oneOf4 = false; //reset 4h variables + bestI = -1; + bestChi2 = 9999; + } else { + for (unsigned int j = i - back; j <= i; j++) { + outMPaths.push_back(inMPaths[j]); + if (debug_) + LogDebug("MPQualityEnhancerFilter") << "kept3 mp " << j; + } + } + back = 0; + } else { // they are cousins + back++; + } + } + } + } else if (inMPaths.size() == 1) { + outMPaths.push_back(inMPaths[0]); + } +} + +void MPQualityEnhancerFilter::filterUnique(std::vector &inMPaths, + std::vector &outMPaths) { + constexpr double xTh = 0.001; + constexpr double tPhiTh = 0.001; + constexpr double t0Th = 0.001; + for (size_t i = 0; i < inMPaths.size(); i++) { + bool visto = false; + for (size_t j = i + 1; j < inMPaths.size(); j++) { + if ((std::abs(inMPaths[i].x - inMPaths[j].x) <= xTh) && + (std::abs(inMPaths[i].tanPhi - inMPaths[j].tanPhi) <= tPhiTh) && + (std::abs(inMPaths[i].t0 - inMPaths[j].t0) <= t0Th)) + visto = true; + } + if (!visto) + outMPaths.push_back(inMPaths[i]); + } +} + +void MPQualityEnhancerFilter::printmP(metaPrimitive mP) { + DTSuperLayerId slId(mP.rawId); + LogDebug("MPQualityEnhancerFilter") << 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); +} diff --git a/L1Trigger/DTTriggerPhase2/src/MPRedundantFilter.cc b/L1Trigger/DTTriggerPhase2/src/MPRedundantFilter.cc new file mode 100644 index 0000000000000..5fde33e50630e --- /dev/null +++ b/L1Trigger/DTTriggerPhase2/src/MPRedundantFilter.cc @@ -0,0 +1,62 @@ +#include +#include "L1Trigger/DTTriggerPhase2/interface/MPRedundantFilter.h" + +using namespace edm; +using namespace std; +using namespace cmsdt; + +// ============================================================================ +// Constructors and destructor +// ============================================================================ +MPRedundantFilter::MPRedundantFilter(const ParameterSet& pset) : MPFilter(pset), maxBufferSize_(8) { + // Obtention of parameters + debug_ = pset.getUntrackedParameter("debug"); +} + +MPRedundantFilter::~MPRedundantFilter() {} + +// ============================================================================ +// Main methods (initialise, run, finish) +// ============================================================================ +void MPRedundantFilter::initialise(const edm::EventSetup& iEventSetup) { buffer_.clear(); } + +void MPRedundantFilter::run(edm::Event& iEvent, + const edm::EventSetup& iEventSetup, + MuonPathPtrs& inMPaths, + MuonPathPtrs& outMPaths) { + buffer_.clear(); + for (auto muonpath = inMPaths.begin(); muonpath != inMPaths.end(); ++muonpath) { + filter(*muonpath, outMPaths); + } + buffer_.clear(); +} + +void MPRedundantFilter::filter(MuonPathPtr& mPath, MuonPathPtrs& outMPaths) { + if (mPath == nullptr) + return; + + if (!isInBuffer(mPath)) { + // Remove the first element (the oldest) + if (buffer_.size() == maxBufferSize_) + buffer_.pop_front(); + // Insert last path as new element + buffer_.push_back(mPath); + + // Send a copy + auto mpAux = std::make_shared(mPath); + outMPaths.push_back(mpAux); + } +} + +bool MPRedundantFilter::isInBuffer(MuonPathPtr& mPath) { + bool ans = false; + + if (!buffer_.empty()) { + for (unsigned int i = 0; i < buffer_.size(); i++) + if (mPath->isEqualTo((MuonPath*)buffer_.at(i).get())) { + ans = true; + break; + } + } + return ans; +} diff --git a/L1Trigger/DTTriggerPhase2/src/MotherGrouping.cc b/L1Trigger/DTTriggerPhase2/src/MotherGrouping.cc new file mode 100644 index 0000000000000..9eba4d08be667 --- /dev/null +++ b/L1Trigger/DTTriggerPhase2/src/MotherGrouping.cc @@ -0,0 +1,27 @@ +#include "L1Trigger/DTTriggerPhase2/interface/MotherGrouping.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" + +using namespace edm; +using namespace std; + +// ============================================================================ +// Constructors and destructor +// ============================================================================ +MotherGrouping::MotherGrouping(const ParameterSet& pset, edm::ConsumesCollector& iC) { + // Obtention of parameters + debug_ = pset.getUntrackedParameter("debug"); +} + +MotherGrouping::~MotherGrouping() {} + +// ============================================================================ +// Main methods (initialise, run, finish) +// ============================================================================ +void MotherGrouping::initialise(const edm::EventSetup& iEventSetup) {} + +void MotherGrouping::run(Event& iEvent, + const EventSetup& iEventSetup, + const DTDigiCollection& digis, + MuonPathPtrs& mpaths) {} + +void MotherGrouping::finish(){}; diff --git a/L1Trigger/DTTriggerPhase2/src/MuonPath.cc b/L1Trigger/DTTriggerPhase2/src/MuonPath.cc new file mode 100644 index 0000000000000..77939e1c51913 --- /dev/null +++ b/L1Trigger/DTTriggerPhase2/src/MuonPath.cc @@ -0,0 +1,204 @@ +#include "L1Trigger/DTTriggerPhase2/interface/MuonPath.h" + +#include +#include +#include + +using namespace cmsdt; + +MuonPath::MuonPath() { + quality_ = NOPATH; + baseChannelId_ = -1; + + for (int i = 0; i < NUM_LAYERS_2SL; i++) { + prim_.push_back(std::make_shared()); + } + + nprimitives_ = NUM_LAYERS; + bxTimeValue_ = -1; + bxNumId_ = -1; + tanPhi_ = 0; + horizPos_ = 0; + chiSquare_ = 0; + for (int i = 0; i < NUM_LAYERS; i++) { + lateralComb_[i] = LEFT; + setXCoorCell(0, i); + setDriftDistance(0, i); + } +} + +MuonPath::MuonPath(DTPrimitivePtrs &ptrPrimitive, int nprimUp, int nprimDown) { + if (nprimUp > 0 && nprimDown > 0) + nprimitives_ = NUM_LAYERS_2SL; //Instead of nprimUp + nprimDown; + else { + nprimitives_ = NUM_LAYERS; + } + nprimitivesUp_ = nprimUp; + nprimitivesDown_ = nprimDown; + rawId_ = 0; + quality_ = NOPATH; + baseChannelId_ = -1; + bxTimeValue_ = -1; + bxNumId_ = -1; + tanPhi_ = 0; + horizPos_ = 0; + chiSquare_ = 0; + phi_ = 0; + phiB_ = 0; + + for (short i = 0; i < nprimitives_; i++) { + lateralComb_[i] = LEFT; + prim_.push_back(std::make_shared(ptrPrimitive[i])); + + setXCoorCell(0, i); + setDriftDistance(0, i); + setXWirePos(0, i); + setZWirePos(0, i); + setTWireTDC(0, i); + } +} + +MuonPath::MuonPath(DTPrimitives &ptrPrimitive, int nprimUp, int nprimDown) { + if (nprimUp > 0 && nprimDown > 0) + nprimitives_ = NUM_LAYERS_2SL; //Instead of nprimUp + nprimDown; + else { + nprimitives_ = NUM_LAYERS; + } + nprimitivesUp_ = nprimUp; + nprimitivesDown_ = nprimDown; + rawId_ = 0; + quality_ = NOPATH; + baseChannelId_ = -1; + bxTimeValue_ = -1; + bxNumId_ = -1; + tanPhi_ = 0; + horizPos_ = 0; + chiSquare_ = 0; + phi_ = 0; + phiB_ = 0; + + for (short i = 0; i < nprimitives_; i++) { + lateralComb_[i] = LEFT; + prim_.push_back(std::make_shared(ptrPrimitive[i])); + + setXCoorCell(0, i); + setDriftDistance(0, i); + setXWirePos(0, i); + setZWirePos(0, i); + setTWireTDC(0, i); + } +} + +MuonPath::MuonPath(MuonPathPtr &ptr) { + setRawId(ptr->rawId()); + setPhi(ptr->phi()); + setPhiB(ptr->phiB()); + setQuality(ptr->quality()); + setBaseChannelId(ptr->baseChannelId()); + setCellHorizontalLayout(ptr->cellLayout()); + setNPrimitives(ptr->nprimitives()); + + setLateralComb(ptr->lateralComb()); + setBxTimeValue(ptr->bxTimeValue()); + setTanPhi(ptr->tanPhi()); + setHorizPos(ptr->horizPos()); + setChiSquare(ptr->chiSquare()); + + for (int i = 0; i < ptr->nprimitives(); i++) { + prim_.push_back(ptr->primitive(i)); + + setXCoorCell(ptr->xCoorCell(i), i); + setDriftDistance(ptr->xDriftDistance(i), i); + setXWirePos(ptr->xWirePos(i), i); + setZWirePos(ptr->zWirePos(i), i); + setTWireTDC(ptr->tWireTDC(i), i); + } +} + +//------------------------------------------------------------------ +//--- Public +//------------------------------------------------------------------ +void MuonPath::setPrimitive(DTPrimitivePtr &ptr, int layer) { + if (ptr == nullptr) + std::cout << "NULL 'Primitive'." << std::endl; + prim_[layer] = std::move(ptr); +} + +void MuonPath::setCellHorizontalLayout(int layout[4]) { + for (int i = 0; i < NUM_LAYERS; i++) + cellLayout_[i] = layout[i]; +} + +void MuonPath::setCellHorizontalLayout(const int *layout) { + for (int i = 0; i < NUM_LAYERS; i++) + cellLayout_[i] = layout[i]; +} + +bool MuonPath::isEqualTo(MuonPath *ptr) { + for (int i = 0; i < ptr->nprimitives(); i++) { + if (this->primitive(i)->isValidTime() && ptr->primitive(i)->isValidTime()) { + if (ptr->primitive(i)->superLayerId() != this->primitive(i)->superLayerId() || + + ptr->primitive(i)->channelId() != this->primitive(i)->channelId() || + + ptr->primitive(i)->tdcTimeStamp() != this->primitive(i)->tdcTimeStamp() || + + ptr->primitive(i)->orbit() != this->primitive(i)->orbit() || + (ptr->lateralComb())[i] != (this->lateralComb())[i]) + return false; + } else { + if (!this->primitive(i)->isValidTime() && !ptr->primitive(i)->isValidTime()) + continue; + + else + return false; + } + } + + return true; +} + +bool MuonPath::isAnalyzable() { + short countValidHits = 0; + for (int i = 0; i < this->nprimitives(); i++) { + // if (!this->primitive(i)) + // continue; + if (this->primitive(i)->isValidTime()) + countValidHits++; + } + + if (countValidHits >= 3) + return true; + return false; +} + +bool MuonPath::completeMP() { + return (prim_[0]->isValidTime() && prim_[1]->isValidTime() && prim_[2]->isValidTime() && prim_[3]->isValidTime()); +} + +void MuonPath::setBxTimeValue(int time) { + bxTimeValue_ = time; + + float auxBxId = float(time) / LHC_CLK_FREQ; + bxNumId_ = int(auxBxId); + if ((auxBxId - int(auxBxId)) >= 0.5) + bxNumId_ = int(bxNumId_ + 1); +} + +void MuonPath::setLateralCombFromPrimitives() { + for (int i = 0; i < nprimitives_; i++) { + if (!this->primitive(i)->isValidTime()) + continue; + lateralComb_[i] = this->primitive(i)->laterality(); + } +} + +void MuonPath::setLateralComb(LATERAL_CASES latComb[4]) { + for (int i = 0; i < NUM_LAYERS; i++) + lateralComb_[i] = latComb[i]; +} + +void MuonPath::setLateralComb(const LATERAL_CASES *latComb) { + for (int i = 0; i < NUM_LAYERS; i++) + lateralComb_[i] = latComb[i]; +} diff --git a/L1Trigger/DTTriggerPhase2/src/MuonPathAnalyzer.cc b/L1Trigger/DTTriggerPhase2/src/MuonPathAnalyzer.cc new file mode 100644 index 0000000000000..744ee7f8b7438 --- /dev/null +++ b/L1Trigger/DTTriggerPhase2/src/MuonPathAnalyzer.cc @@ -0,0 +1,21 @@ +#include "L1Trigger/DTTriggerPhase2/interface/MuonPathAnalyzer.h" + +using namespace edm; +using namespace std; + +// ============================================================================ +// Constructors and destructor +// ============================================================================ +MuonPathAnalyzer::MuonPathAnalyzer(const ParameterSet& pset, edm::ConsumesCollector& iC) { + // Obtention of parameters + debug_ = pset.getUntrackedParameter("debug"); +} + +MuonPathAnalyzer::~MuonPathAnalyzer() {} + +// ============================================================================ +// Main methods (initialise, run, finish) +// ============================================================================ +void MuonPathAnalyzer::initialise(const edm::EventSetup& iEventSetup) {} + +void MuonPathAnalyzer::finish(){}; diff --git a/L1Trigger/DTTriggerPhase2/src/MuonPathAnalyzerInChamber.cc b/L1Trigger/DTTriggerPhase2/src/MuonPathAnalyzerInChamber.cc new file mode 100644 index 0000000000000..42a0aadd2144e --- /dev/null +++ b/L1Trigger/DTTriggerPhase2/src/MuonPathAnalyzerInChamber.cc @@ -0,0 +1,551 @@ +#include "L1Trigger/DTTriggerPhase2/interface/MuonPathAnalyzerInChamber.h" +#include +#include + +using namespace edm; +using namespace std; +using namespace cmsdt; +// ============================================================================ +// Constructors and destructor +// ============================================================================ +MuonPathAnalyzerInChamber::MuonPathAnalyzerInChamber(const ParameterSet &pset, edm::ConsumesCollector &iC) + : MuonPathAnalyzer(pset, iC), + debug_(pset.getUntrackedParameter("debug")), + chi2Th_(pset.getUntrackedParameter("chi2Th")), + shift_filename_(pset.getParameter("shift_filename")), + bxTolerance_(30), + minQuality_(LOWQGHOST), + chiSquareThreshold_(50), + minHits4Fit_(pset.getUntrackedParameter("minHits4Fit")) { + // Obtention of parameters + + if (debug_) + LogDebug("MuonPathAnalyzerInChamber") << "MuonPathAnalyzer: constructor"; + + setChiSquareThreshold(chi2Th_ * 100.); + + //shift + int rawId; + std::ifstream ifin3(shift_filename_.fullPath()); + double shift; + if (ifin3.fail()) { + throw cms::Exception("Missing Input File") + << "MuonPathAnalyzerInChamber::MuonPathAnalyzerInChamber() - Cannot find " << shift_filename_.fullPath(); + } + while (ifin3.good()) { + ifin3 >> rawId >> shift; + shiftinfo_[rawId] = shift; + } + + dtGeomH = iC.esConsumes(); +} + +MuonPathAnalyzerInChamber::~MuonPathAnalyzerInChamber() { + if (debug_) + LogDebug("MuonPathAnalyzerInChamber") << "MuonPathAnalyzer: destructor"; +} + +// ============================================================================ +// Main methods (initialise, run, finish) +// ============================================================================ +void MuonPathAnalyzerInChamber::initialise(const edm::EventSetup &iEventSetup) { + if (debug_) + LogDebug("MuonPathAnalyzerInChamber") << "MuonPathAnalyzerInChamber::initialiase"; + + const MuonGeometryRecord &geom = iEventSetup.get(); + dtGeo_ = &geom.get(dtGeomH); +} + +void MuonPathAnalyzerInChamber::run(edm::Event &iEvent, + const edm::EventSetup &iEventSetup, + MuonPathPtrs &muonpaths, + MuonPathPtrs &outmuonpaths) { + if (debug_) + LogDebug("MuonPathAnalyzerInChamber") << "MuonPathAnalyzerInChamber: run"; + + // fit per SL (need to allow for multiple outputs for a single mpath) + for (auto muonpath = muonpaths.begin(); muonpath != muonpaths.end(); ++muonpath) { + analyze(*muonpath, outmuonpaths); + } +} + +void MuonPathAnalyzerInChamber::finish() { + if (debug_) + LogDebug("MuonPathAnalyzerInChamber") << "MuonPathAnalyzer: finish"; +}; + +//------------------------------------------------------------------ +//--- Private method +//------------------------------------------------------------------ +void MuonPathAnalyzerInChamber::analyze(MuonPathPtr &inMPath, MuonPathPtrs &outMPath) { + if (debug_) + LogDebug("MuonPathAnalyzerInChamber") << "DTp2:analyze \t\t\t\t starts"; + + // Clone the analyzed object + if (debug_) + LogDebug("MuonPathAnalyzerInChamber") << inMPath->nprimitives(); + auto mPath = std::make_shared(inMPath); + + if (debug_) { + LogDebug("MuonPathAnalyzerInChamber") << "DTp2::analyze, looking at mPath: "; + for (int i = 0; i < mPath->nprimitives(); i++) + LogDebug("MuonPathAnalyzerInChamber") + << mPath->primitive(i)->layerId() << " , " << mPath->primitive(i)->superLayerId() << " , " + << mPath->primitive(i)->channelId() << " , " << mPath->primitive(i)->laterality(); + } + + if (debug_) + LogDebug("MuonPathAnalyzerInChamber") << "DTp2:analyze \t\t\t\t\t is Analyzable? "; + if (!mPath->isAnalyzable()) + return; + if (debug_) + LogDebug("MuonPathAnalyzerInChamber") << "DTp2:analyze \t\t\t\t\t yes it is analyzable " << mPath->isAnalyzable(); + + // first of all, get info from primitives, so we can reduce the number of latereralities: + buildLateralities(mPath); + setWirePosAndTimeInMP(mPath); + + std::shared_ptr mpAux; + int bestI = -1; + float best_chi2 = 99999.; + for (int i = 0; i < totalNumValLateralities_; i++) { // LOOP for all lateralities: + if (debug_) + LogDebug("MuonPathAnalyzerInChamber") << "DTp2:analyze \t\t\t\t\t Start with combination " << i; + int NTotalHits = NUM_LAYERS_2SL; + float xwire[NUM_LAYERS_2SL]; + int present_layer[NUM_LAYERS_2SL]; + for (int ii = 0; ii < 8; ii++) { + xwire[ii] = mPath->xWirePos(ii); + if (xwire[ii] == 0) { + present_layer[ii] = 0; + NTotalHits--; + } else { + present_layer[ii] = 1; + } + } + + while (NTotalHits >= minHits4Fit_) { + mPath->setChiSquare(0); + calculateFitParameters(mPath, lateralities_[i], present_layer); + if (mPath->chiSquare() != 0) + break; + NTotalHits--; + } + if (mPath->chiSquare() > chiSquareThreshold_) + continue; + + evaluateQuality(mPath); + + if (mPath->quality() < minQuality_) + continue; + + double z = 0; + double jm_x = (mPath->horizPos()); + int selected_Id = 0; + for (int i = 0; i < mPath->nprimitives(); i++) { + if (mPath->primitive(i)->isValidTime()) { + selected_Id = mPath->primitive(i)->cameraId(); + mPath->setRawId(selected_Id); + break; + } + } + DTLayerId thisLId(selected_Id); + if (thisLId.station() >= 3) + z = Z_SHIFT_MB4; + + DTSuperLayerId MuonPathSLId(thisLId.wheel(), thisLId.station(), thisLId.sector(), thisLId.superLayer()); + GlobalPoint jm_x_cmssw_global = dtGeo_->chamber(MuonPathSLId)->toGlobal(LocalPoint(jm_x, 0., z)); + //jm_x is already extrapolated to the middle of the SL + int thisec = MuonPathSLId.sector(); + if (thisec == 13) + thisec = 4; + if (thisec == 14) + thisec = 10; + double phi = jm_x_cmssw_global.phi() - PHI_CONV * (thisec - 1); + double psi = atan(mPath->tanPhi()); + mPath->setPhi(jm_x_cmssw_global.phi() - PHI_CONV * (thisec - 1)); + mPath->setPhiB(hasPosRF(MuonPathSLId.wheel(), MuonPathSLId.sector()) ? psi - phi : -psi - phi); + + if (mPath->chiSquare() < best_chi2 && mPath->chiSquare() > 0) { + mpAux = std::make_shared(mPath); + bestI = i; + best_chi2 = mPath->chiSquare(); + } + } + if (mpAux != nullptr) { + outMPath.push_back(std::move(mpAux)); + if (debug_) + LogDebug("MuonPathAnalyzerInChamber") + << "DTp2:analize \t\t\t\t\t Laterality " << bestI << " is the one with smaller chi2"; + } else { + if (debug_) + LogDebug("MuonPathAnalyzerInChamber") + << "DTp2:analize \t\t\t\t\t No Laterality found with chi2 smaller than threshold"; + } + if (debug_) + LogDebug("MuonPathAnalyzerInChamber") << "DTp2:analize \t\t\t\t\t Ended working with this set of lateralities"; +} + +void MuonPathAnalyzerInChamber::setCellLayout(MuonPathPtr &mpath) { + for (int i = 0; i <= mpath->nprimitives(); i++) { + if (mpath->primitive(i)->isValidTime()) + cellLayout_[i] = mpath->primitive(i)->channelId(); + else + cellLayout_[i] = -99; + } + + // putting info back into the mpath: + mpath->setCellHorizontalLayout(cellLayout_); + for (int i = 0; i <= mpath->nprimitives(); i++) { + if (cellLayout_[i] >= 0) { + mpath->setBaseChannelId(cellLayout_[i]); + break; + } + } +} + +/** + * For a combination of up to 8 cells, build all the lateralities to be tested, + */ +void MuonPathAnalyzerInChamber::buildLateralities(MuonPathPtr &mpath) { + if (debug_) + LogDebug("MuonPathAnalyzerInChamber") << "MPAnalyzer::buildLateralities << setLateralitiesFromPrims "; + mpath->setLateralCombFromPrimitives(); + + totalNumValLateralities_ = 0; + lateralities_.clear(); + latQuality_.clear(); + + /* We generate all the possible laterality combinations compatible with the built + group in the previous step*/ + lateralities_.push_back(TLateralities()); + for (int ilat = 0; ilat < NLayers; ilat++) { + // Get value from input + LATERAL_CASES lr = (mpath->lateralComb())[ilat]; + if (debug_) + LogDebug("MuonPathAnalyzerInChamber") << "[DEBUG_] Input[" << ilat << "]: " << lr; + + // If left/right fill number + if (lr != NONE) { + if (debug_) + LogDebug("MuonPathAnalyzerInChamber") << "[DEBUG_] - Adding it to " << lateralities_.size() << " lists..."; + for (unsigned int iall = 0; iall < lateralities_.size(); iall++) { + lateralities_[iall][ilat] = lr; + } + } + // both possibilites + else { + // Get the number of possible options now + auto ncurrentoptions = lateralities_.size(); + + // Duplicate them + if (debug_) + LogDebug("MuonPathAnalyzerInChamber") << "[DEBUG_] - Duplicating " << ncurrentoptions << " lists..."; + copy(lateralities_.begin(), lateralities_.end(), back_inserter(lateralities_)); + if (debug_) + LogDebug("MuonPathAnalyzerInChamber") << "[DEBUG_] - Now we have " << lateralities_.size() << " lists..."; + + // Asign LEFT to first ncurrentoptions and RIGHT to the last + for (unsigned int iall = 0; iall < ncurrentoptions; iall++) { + lateralities_[iall][ilat] = LEFT; + lateralities_[iall + ncurrentoptions][ilat] = RIGHT; + } + } // else + } // Iterate over input array + + totalNumValLateralities_ = (int)lateralities_.size(); + if (totalNumValLateralities_ > 128) { + // ADD PROTECTION! + LogDebug("MuonPathAnalyzerInChamber") << "[WARNING]: TOO MANY LATERALITIES TO CHECK !!"; + LogDebug("MuonPathAnalyzerInChamber") << "[WARNING]: skipping this muon"; + lateralities_.clear(); + latQuality_.clear(); + totalNumValLateralities_ = 0; + } + + // Dump values + if (debug_) { + for (unsigned int iall = 0; iall < lateralities_.size(); iall++) { + LogDebug("MuonPathAnalyzerInChamber") << iall << " -> ["; + for (int ilat = 0; ilat < NLayers; ilat++) { + if (ilat != 0) + LogDebug("MuonPathAnalyzerInChamber") << ","; + LogDebug("MuonPathAnalyzerInChamber") << lateralities_[iall][ilat]; + } + LogDebug("MuonPathAnalyzerInChamber") << "]"; + } + } +} +void MuonPathAnalyzerInChamber::setLateralitiesInMP(MuonPathPtr &mpath, TLateralities lat) { + LATERAL_CASES tmp[NUM_LAYERS_2SL]; + for (int i = 0; i < 8; i++) + tmp[i] = lat[i]; + + mpath->setLateralComb(tmp); +} +void MuonPathAnalyzerInChamber::setWirePosAndTimeInMP(MuonPathPtr &mpath) { + int selected_Id = 0; + for (int i = 0; i < mpath->nprimitives(); i++) { + if (mpath->primitive(i)->isValidTime()) { + selected_Id = mpath->primitive(i)->cameraId(); + mpath->setRawId(selected_Id); + break; + } + } + DTLayerId thisLId(selected_Id); + DTChamberId chId(thisLId.wheel(), thisLId.station(), thisLId.sector()); + if (debug_) + LogDebug("MuonPathAnalyzerInChamber") + << "Id " << chId.rawId() << " Wh " << chId.wheel() << " St " << chId.station() << " Se " << chId.sector(); + mpath->setRawId(chId.rawId()); + + DTSuperLayerId MuonPathSLId1(thisLId.wheel(), thisLId.station(), thisLId.sector(), 1); + DTSuperLayerId MuonPathSLId3(thisLId.wheel(), thisLId.station(), thisLId.sector(), 3); + DTWireId wireId1(MuonPathSLId1, 2, 1); + DTWireId wireId3(MuonPathSLId3, 2, 1); + + if (debug_) + LogDebug("MuonPathAnalyzerInChamber") + << "shift1=" << shiftinfo_[wireId1.rawId()] << " shift3=" << shiftinfo_[wireId3.rawId()]; + + float delta = 42000; //um + float zwire[NUM_LAYERS_2SL] = {-13.7, -12.4, -11.1, -9.8002, 9.79999, 11.1, 12.4, 13.7}; // mm + for (int i = 0; i < mpath->nprimitives(); i++) { + if (mpath->primitive(i)->isValidTime()) { + if (i < 4) + mpath->setXWirePos(10000 * shiftinfo_[wireId1.rawId()] + + (mpath->primitive(i)->channelId() + 0.5 * (double)((i + 1) % 2)) * delta, + i); + if (i >= 4) + mpath->setXWirePos(10000 * shiftinfo_[wireId3.rawId()] + + (mpath->primitive(i)->channelId() + 0.5 * (double)((i + 1) % 2)) * delta, + i); + mpath->setZWirePos(zwire[i] * 1000, i); // in um + mpath->setTWireTDC(mpath->primitive(i)->tdcTimeStamp() * DRIFT_SPEED, i); + } else { + mpath->setXWirePos(0., i); + mpath->setZWirePos(0., i); + mpath->setTWireTDC(-1 * DRIFT_SPEED, i); + } + if (debug_) + LogDebug("MuonPathAnalyzerInChamber") << mpath->primitive(i)->tdcTimeStamp() << " "; + } + if (debug_) + LogDebug("MuonPathAnalyzerInChamber"); +} +void MuonPathAnalyzerInChamber::calculateFitParameters(MuonPathPtr &mpath, + TLateralities laterality, + int present_layer[NUM_LAYERS_2SL]) { + // First prepare mpath for fit: + float xwire[NUM_LAYERS_2SL], zwire[NUM_LAYERS_2SL], tTDCvdrift[NUM_LAYERS_2SL]; + double b[NUM_LAYERS_2SL]; + for (int i = 0; i < 8; i++) { + xwire[i] = mpath->xWirePos(i); + zwire[i] = mpath->zWirePos(i); + tTDCvdrift[i] = mpath->tWireTDC(i); + b[i] = 1; + } + + //// NOW Start FITTING: + + // fill hit position + float xhit[NUM_LAYERS_2SL]; + for (int lay = 0; lay < 8; lay++) { + if (debug_) + LogDebug("MuonPathAnalyzerInChamber") << "In fitPerLat " << lay << " xwire " << xwire[lay] << " zwire " + << zwire[lay] << " tTDCvdrift " << tTDCvdrift[lay]; + xhit[lay] = xwire[lay] + (-1 + 2 * laterality[lay]) * 1000 * tTDCvdrift[lay]; + if (debug_) + LogDebug("MuonPathAnalyzerInChamber") << "In fitPerLat " << lay << " xhit " << xhit[lay]; + } + + //Proceed with calculation of fit parameters + double cbscal = 0.0; + double zbscal = 0.0; + double czscal = 0.0; + double bbscal = 0.0; + double zzscal = 0.0; + double ccscal = 0.0; + + for (int lay = 0; lay < 8; lay++) { + if (present_layer[lay] == 0) + continue; + if (debug_) + LogDebug("MuonPathAnalyzerInChamber") + << " For layer " << lay + 1 << " xwire[lay] " << xwire[lay] << " zwire " << zwire[lay] << " b " << b[lay]; + if (debug_) + LogDebug("MuonPathAnalyzerInChamber") << " xhit[lat][lay] " << xhit[lay]; + cbscal = (-1 + 2 * laterality[lay]) * b[lay] + cbscal; + zbscal = zwire[lay] * b[lay] + zbscal; //it actually does not depend on laterality + czscal = (-1 + 2 * laterality[lay]) * zwire[lay] + czscal; + + bbscal = b[lay] * b[lay] + bbscal; //it actually does not depend on laterality + zzscal = zwire[lay] * zwire[lay] + zzscal; //it actually does not depend on laterality + ccscal = (-1 + 2 * laterality[lay]) * (-1 + 2 * laterality[lay]) + ccscal; + } + + double cz = 0.0; + double cb = 0.0; + double zb = 0.0; + double zc = 0.0; + double bc = 0.0; + double bz = 0.0; + + cz = (cbscal * zbscal - czscal * bbscal) / (zzscal * bbscal - zbscal * zbscal); + cb = (czscal * zbscal - cbscal * zzscal) / (zzscal * bbscal - zbscal * zbscal); + + zb = (czscal * cbscal - zbscal * ccscal) / (bbscal * ccscal - cbscal * cbscal); + zc = (zbscal * cbscal - czscal * bbscal) / (bbscal * ccscal - cbscal * cbscal); + + bc = (zbscal * czscal - cbscal * zzscal) / (ccscal * zzscal - czscal * czscal); + bz = (cbscal * czscal - zbscal * ccscal) / (ccscal * zzscal - czscal * czscal); + + double c_tilde[NUM_LAYERS_2SL]; + double z_tilde[NUM_LAYERS_2SL]; + double b_tilde[NUM_LAYERS_2SL]; + + for (int lay = 0; lay < 8; lay++) { + if (present_layer[lay] == 0) + continue; + if (debug_) + LogDebug("MuonPathAnalyzerInChamber") + << " For layer " << lay + 1 << " xwire[lay] " << xwire[lay] << " zwire " << zwire[lay] << " b " << b[lay]; + c_tilde[lay] = (-1 + 2 * laterality[lay]) + cz * zwire[lay] + cb * b[lay]; + z_tilde[lay] = zwire[lay] + zb * b[lay] + zc * (-1 + 2 * laterality[lay]); + b_tilde[lay] = b[lay] + bc * (-1 + 2 * laterality[lay]) + bz * zwire[lay]; + } + + //Calculate results per lat + double xctilde = 0.0; + double xztilde = 0.0; + double xbtilde = 0.0; + double ctildectilde = 0.0; + double ztildeztilde = 0.0; + double btildebtilde = 0.0; + + double rect0vdrift = 0.0; + double recslope = 0.0; + double recpos = 0.0; + + for (int lay = 0; lay < 8; lay++) { + if (present_layer[lay] == 0) + continue; + xctilde = xhit[lay] * c_tilde[lay] + xctilde; + ctildectilde = c_tilde[lay] * c_tilde[lay] + ctildectilde; + xztilde = xhit[lay] * z_tilde[lay] + xztilde; + ztildeztilde = z_tilde[lay] * z_tilde[lay] + ztildeztilde; + xbtilde = xhit[lay] * b_tilde[lay] + xbtilde; + btildebtilde = b_tilde[lay] * b_tilde[lay] + btildebtilde; + } + + //Results for t0vdrift (BX), slope and position per lat + rect0vdrift = xctilde / ctildectilde; + recslope = xztilde / ztildeztilde; + recpos = xbtilde / btildebtilde; + if (debug_) { + LogDebug("MuonPathAnalyzerInChamber") << " In fitPerLat Reconstructed values per lat " + << " rect0vdrift " << rect0vdrift; + LogDebug("MuonPathAnalyzerInChamber") + << "rect0 " << rect0vdrift / DRIFT_SPEED << " recBX " << rect0vdrift / DRIFT_SPEED / 25 << " recslope " + << recslope << " recpos " << recpos; + } + + //Get t*v and residuals per layer, and chi2 per laterality + double rectdriftvdrift[NUM_LAYERS_2SL]; + double recres[NUM_LAYERS_2SL]; + double recchi2 = 0.0; + int sign_tdriftvdrift = {0}; + int incell_tdriftvdrift = {0}; + int physical_slope = {0}; + + // Select the worst hit in order to get rid of it + double maxDif = -1; + int maxInt = -1; + + for (int lay = 0; lay < 8; lay++) { + if (present_layer[lay] == 0) + continue; + rectdriftvdrift[lay] = tTDCvdrift[lay] - rect0vdrift / 1000; + if (debug_) + LogDebug("MuonPathAnalyzerInChamber") << rectdriftvdrift[lay]; + recres[lay] = xhit[lay] - zwire[lay] * recslope - b[lay] * recpos - (-1 + 2 * laterality[lay]) * rect0vdrift; + if ((present_layer[lay] == 1) && (rectdriftvdrift[lay] < -0.1)) { + sign_tdriftvdrift = -1; + if (-0.1 - rectdriftvdrift[lay] > maxDif) { + maxDif = -0.1 - rectdriftvdrift[lay]; + maxInt = lay; + } + } + if ((present_layer[lay] == 1) && (abs(rectdriftvdrift[lay]) > 21.1)) { + incell_tdriftvdrift = -1; //Changed to 2.11 to account for resolution effects + if (rectdriftvdrift[lay] - 21.1 > maxDif) { + maxDif = rectdriftvdrift[lay] - 21.1; + maxInt = lay; + } + } + } + + if (fabs(recslope / 10) > 1.3) + physical_slope = -1; + + if (physical_slope == -1 && debug_) + LogDebug("MuonPathAnalyzerInChamber") << "Combination with UNPHYSICAL slope "; + if (sign_tdriftvdrift == -1 && debug_) + LogDebug("MuonPathAnalyzerInChamber") << "Combination with negative tdrift-vdrift "; + if (incell_tdriftvdrift == -1 && debug_) + LogDebug("MuonPathAnalyzerInChamber") << "Combination with tdrift-vdrift larger than half cell "; + + for (int lay = 0; lay < 8; lay++) { + if (present_layer[lay] == 0) + continue; + recchi2 = recres[lay] * recres[lay] + recchi2; + } + if (debug_) + LogDebug("MuonPathAnalyzerInChamber") + << "In fitPerLat Chi2 " << recchi2 << " with sign " << sign_tdriftvdrift << " within cell " + << incell_tdriftvdrift << " physical_slope " << physical_slope; + + //LATERALITY IS NOT VALID + if (true && maxInt != -1) { + present_layer[maxInt] = 0; + if (debug_) + LogDebug("MuonPathAnalyzerInChamber") << "We get rid of hit in layer " << maxInt; + } + + // LATERALITY IS VALID... + if (!(sign_tdriftvdrift == -1) && !(incell_tdriftvdrift == -1) && !(physical_slope == -1)) { + mpath->setBxTimeValue((rect0vdrift / DRIFT_SPEED) / 1000); + mpath->setTanPhi(-1 * recslope / 10); + mpath->setHorizPos(recpos / 10000); + mpath->setChiSquare(recchi2 / 100000000); + setLateralitiesInMP(mpath, laterality); + if (debug_) + LogDebug("MuonPathAnalyzerInChamber") + << "In fitPerLat " + << "t0 " << mpath->bxTimeValue() << " slope " << mpath->tanPhi() << " pos " << mpath->horizPos() << " chi2 " + << mpath->chiSquare() << " rawId " << mpath->rawId(); + } +} +void MuonPathAnalyzerInChamber::evaluateQuality(MuonPathPtr &mPath) { + mPath->setQuality(NOPATH); + + if (mPath->nprimitivesUp() >= 4 && mPath->nprimitivesDown() >= 4) { + mPath->setQuality(HIGHHIGHQ); + } else if ((mPath->nprimitivesUp() == 4 && mPath->nprimitivesDown() == 3) || + (mPath->nprimitivesUp() == 3 && mPath->nprimitivesDown() == 4)) { + mPath->setQuality(HIGHLOWQ); + } else if ((mPath->nprimitivesUp() == 4 && mPath->nprimitivesDown() <= 2 && mPath->nprimitivesDown() > 0) || + (mPath->nprimitivesUp() <= 2 && mPath->nprimitivesUp() > 0 && mPath->nprimitivesDown() == 4)) { + mPath->setQuality(CHIGHQ); + } else if ((mPath->nprimitivesUp() == 3 && mPath->nprimitivesDown() == 3)) { + mPath->setQuality(LOWLOWQ); + } else if ((mPath->nprimitivesUp() == 3 && mPath->nprimitivesDown() <= 2 && mPath->nprimitivesDown() > 0) || + (mPath->nprimitivesUp() <= 2 && mPath->nprimitivesUp() > 0 && mPath->nprimitivesDown() == 3) || + (mPath->nprimitivesUp() == 2 && mPath->nprimitivesDown() == 2)) { + mPath->setQuality(CLOWQ); + } else if (mPath->nprimitivesUp() >= 4 || mPath->nprimitivesDown() >= 4) { + mPath->setQuality(HIGHQ); + } else if (mPath->nprimitivesUp() == 3 || mPath->nprimitivesDown() == 3) { + mPath->setQuality(LOWQ); + } +} diff --git a/L1Trigger/DTTriggerPhase2/src/MuonPathAnalyzerPerSL.cc b/L1Trigger/DTTriggerPhase2/src/MuonPathAnalyzerPerSL.cc new file mode 100644 index 0000000000000..3fa3436fe06b4 --- /dev/null +++ b/L1Trigger/DTTriggerPhase2/src/MuonPathAnalyzerPerSL.cc @@ -0,0 +1,1076 @@ +#include "L1Trigger/DTTriggerPhase2/interface/MuonPathAnalyzerPerSL.h" +#include +#include + +using namespace edm; +using namespace std; +using namespace cmsdt; +// ============================================================================ +// Constructors and destructor +// ============================================================================ +MuonPathAnalyzerPerSL::MuonPathAnalyzerPerSL(const ParameterSet &pset, edm::ConsumesCollector &iC) + : MuonPathAnalyzer(pset, iC), + bxTolerance_(30), + minQuality_(LOWQGHOST), + chiSquareThreshold_(50), + debug_(pset.getUntrackedParameter("debug")), + chi2Th_(pset.getUntrackedParameter("chi2Th")), + tanPhiTh_(pset.getUntrackedParameter("tanPhiTh")), + use_LSB_(pset.getUntrackedParameter("use_LSB")), + tanPsi_precision_(pset.getUntrackedParameter("tanPsi_precision")), + x_precision_(pset.getUntrackedParameter("x_precision")) { + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") << "MuonPathAnalyzer: constructor"; + + setChiSquareThreshold(chi2Th_ * 100.); + + //shift + int rawId; + shift_filename_ = pset.getParameter("shift_filename"); + std::ifstream ifin3(shift_filename_.fullPath()); + double shift; + if (ifin3.fail()) { + throw cms::Exception("Missing Input File") + << "MuonPathAnalyzerPerSL::MuonPathAnalyzerPerSL() - Cannot find " << shift_filename_.fullPath(); + } + while (ifin3.good()) { + ifin3 >> rawId >> shift; + shiftinfo_[rawId] = shift; + } + + chosen_sl_ = pset.getUntrackedParameter("trigger_with_sl"); + + if (chosen_sl_ != 1 && chosen_sl_ != 3 && chosen_sl_ != 4) { + LogDebug("MuonPathAnalyzerPerSL") << "chosen sl must be 1,3 or 4(both superlayers)"; + assert(chosen_sl_ != 1 && chosen_sl_ != 3 && chosen_sl_ != 4); //4 means run using the two superlayers + } + + dtGeomH = iC.esConsumes(); +} + +MuonPathAnalyzerPerSL::~MuonPathAnalyzerPerSL() { + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") << "MuonPathAnalyzer: destructor"; +} + +// ============================================================================ +// Main methods (initialise, run, finish) +// ============================================================================ +void MuonPathAnalyzerPerSL::initialise(const edm::EventSetup &iEventSetup) { + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") << "MuonPathAnalyzerPerSL::initialiase"; + + const MuonGeometryRecord &geom = iEventSetup.get(); + dtGeo_ = &geom.get(dtGeomH); +} + +void MuonPathAnalyzerPerSL::run(edm::Event &iEvent, + const edm::EventSetup &iEventSetup, + MuonPathPtrs &muonpaths, + std::vector &metaPrimitives) { + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") << "MuonPathAnalyzerPerSL: run"; + + // fit per SL (need to allow for multiple outputs for a single mpath) + for (auto &muonpath : muonpaths) { + analyze(muonpath, metaPrimitives); + } +} + +void MuonPathAnalyzerPerSL::finish() { + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") << "MuonPathAnalyzer: finish"; +}; + +constexpr int MuonPathAnalyzerPerSL::LAYER_ARRANGEMENTS_[NUM_LAYERS][NUM_CELL_COMB] = { + {0, 1, 2}, + {1, 2, 3}, // Consecutive groups + {0, 1, 3}, + {0, 2, 3} // Non-consecutive groups +}; + +//------------------------------------------------------------------ +//--- Métodos privados +//------------------------------------------------------------------ + +void MuonPathAnalyzerPerSL::analyze(MuonPathPtr &inMPath, std::vector &metaPrimitives) { + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") << "DTp2:analyze \t\t\t\t starts"; + + // LOCATE MPATH + int selected_Id = 0; + if (inMPath->primitive(0)->tdcTimeStamp() != -1) + selected_Id = inMPath->primitive(0)->cameraId(); + else if (inMPath->primitive(1)->tdcTimeStamp() != -1) + selected_Id = inMPath->primitive(1)->cameraId(); + else if (inMPath->primitive(2)->tdcTimeStamp() != -1) + selected_Id = inMPath->primitive(2)->cameraId(); + else if (inMPath->primitive(3)->tdcTimeStamp() != -1) + selected_Id = inMPath->primitive(3)->cameraId(); + + DTLayerId thisLId(selected_Id); + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") << "Building up MuonPathSLId from rawId in the Primitive"; + DTSuperLayerId MuonPathSLId(thisLId.wheel(), thisLId.station(), thisLId.sector(), thisLId.superLayer()); + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") << "The MuonPathSLId is" << MuonPathSLId; + + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") + << "DTp2:analyze \t\t\t\t In analyze function checking if inMPath->isAnalyzable() " << inMPath->isAnalyzable(); + + if (chosen_sl_ < 4 && thisLId.superLayer() != chosen_sl_) + return; // avoid running when mpath not in chosen SL (for 1SL fitting) + + auto mPath = std::make_shared(inMPath); + + if (mPath->isAnalyzable()) { + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") << "DTp2:analyze \t\t\t\t\t yes it is analyzable " << mPath->isAnalyzable(); + setCellLayout(mPath->cellLayout()); + evaluatePathQuality(mPath); + } else { + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") << "DTp2:analyze \t\t\t\t\t no it is NOT analyzable " << mPath->isAnalyzable(); + return; + } + + int wi[8], tdc[8], lat[8]; + DTPrimitivePtr Prim0(mPath->primitive(0)); + wi[0] = Prim0->channelId(); + tdc[0] = Prim0->tdcTimeStamp(); + DTPrimitivePtr Prim1(mPath->primitive(1)); + wi[1] = Prim1->channelId(); + tdc[1] = Prim1->tdcTimeStamp(); + DTPrimitivePtr Prim2(mPath->primitive(2)); + wi[2] = Prim2->channelId(); + tdc[2] = Prim2->tdcTimeStamp(); + DTPrimitivePtr Prim3(mPath->primitive(3)); + wi[3] = Prim3->channelId(); + tdc[3] = Prim3->tdcTimeStamp(); + for (int i = 4; i < 8; i++) { + wi[i] = -1; + tdc[i] = -1; + lat[i] = -1; + } + + DTWireId wireId(MuonPathSLId, 2, 1); + + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") << "DTp2:analyze \t\t\t\t checking if it passes the min quality cut " + << mPath->quality() << ">" << minQuality_; + if (mPath->quality() >= minQuality_) { + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") << "DTp2:analyze \t\t\t\t min quality achievedCalidad: " << mPath->quality(); + for (int i = 0; i <= 3; i++) { + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") + << "DTp2:analyze \t\t\t\t Capa: " << mPath->primitive(i)->layerId() + << " Canal: " << mPath->primitive(i)->channelId() << " TDCTime: " << mPath->primitive(i)->tdcTimeStamp(); + } + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") << "DTp2:analyze \t\t\t\t Starting lateralities loop, totalNumValLateralities: " + << totalNumValLateralities_; + + double best_chi2 = 99999.; + double chi2_jm_tanPhi = 999; + double chi2_jm_x = -1; + double chi2_jm_t0 = -1; + double chi2_phi = -1; + double chi2_phiB = -1; + double chi2_chi2 = -1; + int chi2_quality = -1; + int bestLat[8]; + for (int i = 0; i < 8; i++) { + bestLat[i] = -1; + } + + for (int i = 0; i < totalNumValLateralities_; i++) { //here + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") << "DTp2:analyze \t\t\t\t\t laterality #- " << i; + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") << "DTp2:analyze \t\t\t\t\t laterality #- " << i << " checking quality:"; + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") + << "DTp2:analyze \t\t\t\t\t laterality #- " << i << " checking mPath Quality=" << mPath->quality(); + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") + << "DTp2:analyze \t\t\t\t\t laterality #- " << i << " latQuality_[i].val=" << latQuality_[i].valid; + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") << "DTp2:analyze \t\t\t\t\t laterality #- " << i << " before if:"; + + if (latQuality_[i].valid and + (((mPath->quality() == HIGHQ or mPath->quality() == HIGHQGHOST) and latQuality_[i].quality == HIGHQ) or + ((mPath->quality() == LOWQ or mPath->quality() == LOWQGHOST) and latQuality_[i].quality == LOWQ))) { + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") << "DTp2:analyze \t\t\t\t\t laterality #- " << i << " inside if"; + mPath->setBxTimeValue(latQuality_[i].bxValue); + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") + << "DTp2:analyze \t\t\t\t\t laterality #- " << i << " settingLateralCombination"; + mPath->setLateralComb(lateralities_[i]); + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") + << "DTp2:analyze \t\t\t\t\t laterality #- " << i << " done settingLateralCombination"; + + // Clonamos el objeto analizado. + auto mpAux = std::make_shared(mPath); + lat[0] = mpAux->lateralComb()[0]; + lat[1] = mpAux->lateralComb()[1]; + lat[2] = mpAux->lateralComb()[2]; + lat[3] = mpAux->lateralComb()[3]; + + int wiOk[NUM_LAYERS], tdcOk[NUM_LAYERS], latOk[NUM_LAYERS]; + for (int lay = 0; lay < 4; lay++) { + if (latQuality_[i].invalidateHitIdx == lay) { + wiOk[lay] = -1; + tdcOk[lay] = -1; + latOk[lay] = -1; + } else { + wiOk[lay] = wi[lay]; + tdcOk[lay] = tdc[lay]; + latOk[lay] = lat[lay]; + } + } + + int idxHitNotValid = latQuality_[i].invalidateHitIdx; + if (idxHitNotValid >= 0) { + auto dtpAux = std::make_shared(); + mpAux->setPrimitive(dtpAux, idxHitNotValid); + } + + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") << "DTp2:analyze \t\t\t\t\t calculating parameters "; + calculatePathParameters(mpAux); + /* + * After calculating the parameters, and if it is a 4-hit fit, + * if the resultant chi2 is higher than the programmed threshold, + * the mpath is eliminated and we go to the next element + */ + if ((mpAux->quality() == HIGHQ or mpAux->quality() == HIGHQGHOST) && + mpAux->chiSquare() > chiSquareThreshold_) { //check this if!!! + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") + << "DTp2:analyze \t\t\t\t\t HIGHQ or HIGHQGHOST but min chi2 or Q test not satisfied "; + } else { + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") << "DTp2:analyze \t\t\t\t\t inside else, returning values: "; + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") << "DTp2:analyze \t\t\t\t\t BX Time = " << mpAux->bxTimeValue(); + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") << "DTp2:analyze \t\t\t\t\t BX Id = " << mpAux->bxNumId(); + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") << "DTp2:analyze \t\t\t\t\t XCoor = " << mpAux->horizPos(); + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") << "DTp2:analyze \t\t\t\t\t tan(Phi)= " << mpAux->tanPhi(); + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") << "DTp2:analyze \t\t\t\t\t chi2= " << mpAux->chiSquare(); + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") << "DTp2:analyze \t\t\t\t\t lateralities = " + << " " << mpAux->lateralComb()[0] << " " << mpAux->lateralComb()[1] << " " + << mpAux->lateralComb()[2] << " " << mpAux->lateralComb()[3]; + + DTChamberId ChId(MuonPathSLId.wheel(), MuonPathSLId.station(), MuonPathSLId.sector()); + + double jm_tanPhi = -1. * mpAux->tanPhi(); //testing with this line + if (use_LSB_) + jm_tanPhi = floor(jm_tanPhi / tanPsi_precision_) * tanPsi_precision_; + double jm_x = + (((double)mpAux->horizPos()) / 10.) + x_precision_ * (round(shiftinfo_[wireId.rawId()] / x_precision_)); + if (use_LSB_) + jm_x = ((double)round(((double)jm_x) / x_precision_)) * x_precision_; + //changing to chamber frame or reference: + double jm_t0 = mpAux->bxTimeValue(); + int quality = mpAux->quality(); + + //computing phi and phiB + double z = 0; + double z1 = Z_POS_SL; + double z3 = -1. * z1; + if (ChId.station() == 3 or ChId.station() == 4) { + z1 = z1 + Z_SHIFT_MB4; + z3 = z3 + Z_SHIFT_MB4; + } else if (MuonPathSLId.superLayer() == 1) + z = z1; + else if (MuonPathSLId.superLayer() == 3) + z = z3; + + GlobalPoint jm_x_cmssw_global = dtGeo_->chamber(ChId)->toGlobal(LocalPoint(jm_x, 0., z)); + int thisec = MuonPathSLId.sector(); + if (thisec == 13) + thisec = 4; + if (thisec == 14) + thisec = 10; + double phi = jm_x_cmssw_global.phi() - PHI_CONV * (thisec - 1); + double psi = atan(jm_tanPhi); + double phiB = hasPosRF(MuonPathSLId.wheel(), MuonPathSLId.sector()) ? psi - phi : -psi - phi; + double chi2 = mpAux->chiSquare() * 0.01; //in cmssw we need cm, 1 cm^2 = 100 mm^2 + + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") + << "DTp2:analyze \t\t\t\t\t\t\t\t pushing back metaPrimitive at x=" << jm_x << " tanPhi:" << jm_tanPhi + << " t0:" << jm_t0; + + if (mpAux->quality() == HIGHQ or + mpAux->quality() == HIGHQGHOST) { //keep only the values with the best chi2 among lateralities + if ((chi2 < best_chi2) && (std::abs(jm_tanPhi) <= tanPhiTh_)) { + chi2_jm_tanPhi = jm_tanPhi; + chi2_jm_x = (mpAux->horizPos() / 10.) + shiftinfo_[wireId.rawId()]; + chi2_jm_t0 = mpAux->bxTimeValue(); + chi2_phi = phi; + chi2_phiB = phiB; + chi2_chi2 = chi2; + best_chi2 = chi2; + chi2_quality = mpAux->quality(); + for (int i = 0; i < 4; i++) { + bestLat[i] = lat[i]; + } + } + } else if (std::abs(jm_tanPhi) <= + tanPhiTh_) { //write the metaprimitive in case no HIGHQ or HIGHQGHOST and tanPhi range + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") + << "DTp2:analyze \t\t\t\t\t\t\t\t pushing back metaprimitive no HIGHQ or HIGHQGHOST"; + metaPrimitives.emplace_back(metaPrimitive({MuonPathSLId.rawId(), + jm_t0, + jm_x, + jm_tanPhi, + phi, + phiB, + chi2, + quality, + wiOk[0], + tdcOk[0], + latOk[0], + wiOk[1], + tdcOk[1], + latOk[1], + wiOk[2], + tdcOk[2], + latOk[2], + wiOk[3], + tdcOk[3], + latOk[3], + wi[4], + tdc[4], + lat[4], + wi[5], + tdc[5], + lat[5], + wi[6], + tdc[6], + lat[6], + wi[7], + tdc[7], + lat[7], + -1})); + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") + << "DTp2:analyze \t\t\t\t\t\t\t\t done pushing back metaprimitive no HIGHQ or HIGHQGHOST"; + } + } + } else { + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") + << "DTp2:analyze \t\t\t\t\t\t\t\t latQuality_[i].valid and (((mPath->quality()==HIGHQ or " + "mPath->quality()==HIGHQGHOST) and latQuality_[i].quality==HIGHQ) or ((mPath->quality() " + "== LOWQ or mPath->quality()==LOWQGHOST) and latQuality_[i].quality==LOWQ)) not passed"; + } + } + if (chi2_jm_tanPhi != 999 and std::abs(chi2_jm_tanPhi) < tanPhiTh_) { // + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") << "DTp2:analyze \t\t\t\t\t\t\t\t pushing back best chi2 metaPrimitive"; + metaPrimitives.emplace_back(metaPrimitive({MuonPathSLId.rawId(), + chi2_jm_t0, + chi2_jm_x, + chi2_jm_tanPhi, + chi2_phi, + chi2_phiB, + chi2_chi2, + chi2_quality, + wi[0], + tdc[0], + bestLat[0], + wi[1], + tdc[1], + bestLat[1], + wi[2], + tdc[2], + bestLat[2], + wi[3], + tdc[3], + bestLat[3], + wi[4], + tdc[4], + bestLat[4], + wi[5], + tdc[5], + bestLat[5], + wi[6], + tdc[6], + bestLat[6], + wi[7], + tdc[7], + bestLat[7], + -1})); + } + } + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") << "DTp2:analyze \t\t\t\t finishes"; +} + +void MuonPathAnalyzerPerSL::setCellLayout(const int layout[NUM_LAYERS]) { + memcpy(cellLayout_, layout, 4 * sizeof(int)); + + buildLateralities(); +} + +/** + * For a given 4-cell combination (one per layer), all the possible lateralities + * combinations that are compatible with a straight line are generated. + */ +void MuonPathAnalyzerPerSL::buildLateralities(void) { + LATERAL_CASES(*validCase)[NUM_LAYERS], sideComb[NUM_LAYERS]; + + totalNumValLateralities_ = 0; + /* We generate all the possible lateralities combination for a given group + of cells */ + for (int lowLay = LEFT; lowLay <= RIGHT; lowLay++) + for (int midLowLay = LEFT; midLowLay <= RIGHT; midLowLay++) + for (int midHigLay = LEFT; midHigLay <= RIGHT; midHigLay++) + for (int higLay = LEFT; higLay <= RIGHT; higLay++) { + sideComb[0] = static_cast(lowLay); + sideComb[1] = static_cast(midLowLay); + sideComb[2] = static_cast(midHigLay); + sideComb[3] = static_cast(higLay); + + /* If a laterality combination is valid, we store it */ + if (isStraightPath(sideComb)) { + validCase = lateralities_ + totalNumValLateralities_; + memcpy(validCase, sideComb, 4 * sizeof(LATERAL_CASES)); + + latQuality_[totalNumValLateralities_].valid = false; + latQuality_[totalNumValLateralities_].bxValue = 0; + latQuality_[totalNumValLateralities_].quality = NOPATH; + latQuality_[totalNumValLateralities_].invalidateHitIdx = -1; + + totalNumValLateralities_++; + } + } +} + +/** + * This method checks whether a given combination conform a straight line or not + */ +bool MuonPathAnalyzerPerSL::isStraightPath(LATERAL_CASES sideComb[NUM_LAYERS]) { + return true; //trying with all lateralities to be confirmed + + int i, ajustedLayout[NUM_LAYERS], pairDiff[3], desfase[3]; + + for (i = 0; i <= 3; i++) + ajustedLayout[i] = cellLayout_[i] + sideComb[i]; + for (i = 0; i <= 2; i++) + pairDiff[i] = ajustedLayout[i + 1] - ajustedLayout[i]; + for (i = 0; i <= 1; i++) + desfase[i] = abs(pairDiff[i + 1] - pairDiff[i]); + desfase[2] = abs(pairDiff[2] - pairDiff[0]); + bool resultado = (desfase[0] > 1 or desfase[1] > 1 or desfase[2] > 1); + + return (!resultado); +} +void MuonPathAnalyzerPerSL::evaluatePathQuality(MuonPathPtr &mPath) { + int totalHighQ = 0, totalLowQ = 0; + + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") + << "DTp2:evaluatePathQuality \t\t\t\t\t En evaluatePathQuality Evaluando PathQ. Celda base: " + << mPath->baseChannelId(); + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") << "DTp2:evaluatePathQuality \t\t\t\t\t Total lateralidades: " + << totalNumValLateralities_; + + mPath->setQuality(NOPATH); + + for (int latIdx = 0; latIdx < totalNumValLateralities_; latIdx++) { + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") << "DTp2:evaluatePathQuality \t\t\t\t\t Analizando combinacion de lateralidad: " + << lateralities_[latIdx][0] << " " << lateralities_[latIdx][1] << " " + << lateralities_[latIdx][2] << " " << lateralities_[latIdx][3]; + + evaluateLateralQuality(latIdx, mPath, &(latQuality_[latIdx])); + + if (latQuality_[latIdx].quality == HIGHQ) { + totalHighQ++; + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") << "DTp2:evaluatePathQuality \t\t\t\t\t\t Lateralidad HIGHQ"; + } + if (latQuality_[latIdx].quality == LOWQ) { + totalLowQ++; + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") << "DTp2:evaluatePathQuality \t\t\t\t\t\t Lateralidad LOWQ"; + } + } + /* + * Quality stablishment + */ + if (totalHighQ == 1) { + mPath->setQuality(HIGHQ); + } else if (totalHighQ > 1) { + mPath->setQuality(HIGHQGHOST); + } else if (totalLowQ == 1) { + mPath->setQuality(LOWQ); + } else if (totalLowQ > 1) { + mPath->setQuality(LOWQGHOST); + } +} + +void MuonPathAnalyzerPerSL::evaluateLateralQuality(int latIdx, MuonPathPtr &mPath, LATQ_TYPE *latQuality) { + int layerGroup[3]; + LATERAL_CASES sideComb[3]; + PARTIAL_LATQ_TYPE latQResult[NUM_LAYERS] = {{false, 0}, {false, 0}, {false, 0}, {false, 0}}; + + // Default values. + latQuality->valid = false; + latQuality->bxValue = 0; + latQuality->quality = NOPATH; + latQuality->invalidateHitIdx = -1; + + /* If, for a given laterality combination, the two consecutive 3-layer combinations + were a valid track, we will have found a right high-quality track, hence + it will be unnecessary to check the remaining 2 combinations. + In order to mimic the FPGA behaviour, we build a code that analyzes the 4 combinations + with an additional logic to discriminate the final quality of the track + */ + for (int i = 0; i <= 3; i++) { + memcpy(layerGroup, LAYER_ARRANGEMENTS_[i], 3 * sizeof(int)); + + // Pick the laterality combination for each cell + for (int j = 0; j < 3; j++) + sideComb[j] = lateralities_[latIdx][layerGroup[j]]; + + validate(sideComb, layerGroup, mPath, &(latQResult[i])); + } + /* + Impose the condition for a complete laterality combination, that all combinations + should give the same BX vale to give a consistent track. + */ + if (!sameBXValue(latQResult)) { + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") + << "DTp2:evaluateLateralQuality \t\t\t\t\t Lateralidad DESCARTADA. Tolerancia de BX excedida"; + return; + } + + // two complementary valid tracks => full muon track. + if ((latQResult[0].latQValid && latQResult[1].latQValid) or (latQResult[0].latQValid && latQResult[2].latQValid) or + (latQResult[0].latQValid && latQResult[3].latQValid) or (latQResult[1].latQValid && latQResult[2].latQValid) or + (latQResult[1].latQValid && latQResult[3].latQValid) or (latQResult[2].latQValid && latQResult[3].latQValid)) { + latQuality->valid = true; + + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") << "DTp2:analyze \t\t\t\t\t\t Valid BXs"; + long int sumBX = 0, numValid = 0; + for (int i = 0; i <= 3; i++) { + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") << "DTp2:analyze \t\t\t\t\t\t " + << "[" << latQResult[i].bxValue << "," << latQResult[i].latQValid << "]"; + if (latQResult[i].latQValid) { + sumBX += latQResult[i].bxValue; + numValid++; + } + } + + // mean time of all lateralities. + if (numValid == 1) + latQuality->bxValue = sumBX; + else if (numValid == 2) + latQuality->bxValue = (sumBX * (MEANTIME_2LAT)) / std::pow(2, 15); + else if (numValid == 3) + latQuality->bxValue = (sumBX * (MEANTIME_3LAT)) / std::pow(2, 15); + else if (numValid == 4) + latQuality->bxValue = (sumBX * (MEANTIME_4LAT)) / std::pow(2, 15); + + latQuality->quality = HIGHQ; + + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") << "DTp2:evaluateLateralQuality \t\t\t\t\t Lateralidad ACEPTADA. HIGHQ."; + } else { + if (latQResult[0].latQValid or latQResult[1].latQValid or latQResult[2].latQValid or latQResult[3].latQValid) { + latQuality->valid = true; + latQuality->quality = LOWQ; + for (int i = 0; i < 4; i++) + if (latQResult[i].latQValid) { + latQuality->bxValue = latQResult[i].bxValue; + latQuality->invalidateHitIdx = omittedHit(i); + break; + } + + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") << "DTp2:evaluateLateralQuality \t\t\t\t\t Lateralidad ACEPTADA. LOWQ."; + } else { + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") << "DTp2:evaluateLateralQuality \t\t\t\t\t Lateralidad DESCARTADA. NOPATH."; + } + } +} + +/** + * Validate, for a layer combination (3), cells and lateralities, if the temporal values + * fullfill the mean-timer criteria. + */ +void MuonPathAnalyzerPerSL::validate(LATERAL_CASES sideComb[3], + int layerIndex[3], + MuonPathPtr &mPath, + PARTIAL_LATQ_TYPE *latq) { + // Valor por defecto. + latq->bxValue = 0; + latq->latQValid = false; + + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") << "DTp2:validate \t\t\t\t\t\t\t In validate, checking muon path for layers: " + << layerIndex[0] << "/" << layerIndex[1] << "/" << layerIndex[2]; + + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") << "DTp2:validate \t\t\t\t\t\t\t Partial lateralities: " << sideComb[0] << "/" + << sideComb[1] << "/" << sideComb[2]; + + int validCells = 0; + for (int j = 0; j < 3; j++) + if (mPath->primitive(layerIndex[j])->isValidTime()) + validCells++; + + if (validCells != 3) { + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") << "DTp2:validate \t\t\t\t\t\t\t There is no valid cells."; + return; + } + + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") << "DTp2:validate \t\t\t\t\t\t\t TDC values: " + << mPath->primitive(layerIndex[0])->tdcTimeStamp() << "/" + << mPath->primitive(layerIndex[1])->tdcTimeStamp() << "/" + << mPath->primitive(layerIndex[2])->tdcTimeStamp() << "."; + + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") << "DTp2:validate \t\t\t\t\t\t\t Valid TIMES: " + << mPath->primitive(layerIndex[0])->isValidTime() << "/" + << mPath->primitive(layerIndex[1])->isValidTime() << "/" + << mPath->primitive(layerIndex[2])->isValidTime() << "."; + + /* Vertical distances */ + int dVertMI = layerIndex[1] - layerIndex[0]; + int dVertSM = layerIndex[2] - layerIndex[1]; + + /* Horizontal distances between lower/middle and middle/upper cells */ + int dHorzMI = cellLayout_[layerIndex[1]] - cellLayout_[layerIndex[0]]; + int dHorzSM = cellLayout_[layerIndex[2]] - cellLayout_[layerIndex[1]]; + + /* Pair index of layers that we are using + SM => Upper + Middle + MI => Middle + Lower + We use pointers to simplify the code */ + int *layPairSM = &layerIndex[1]; + int *layPairMI = &layerIndex[0]; + + /* Pair combination of cells to compose the equation. */ + LATERAL_CASES smSides[2], miSides[2]; + + /* Considering the index 0 of "sideComb" the laterality of the lower cells is stored, + we extract the laterality combiantion for SM and MI pairs */ + + memcpy(smSides, &sideComb[1], 2 * sizeof(LATERAL_CASES)); + + memcpy(miSides, &sideComb[0], 2 * sizeof(LATERAL_CASES)); + + long int bxValue = 0; + int coefsAB[2] = {0, 0}, coefsCD[2] = {0, 0}; + /* It's neccesary to be careful with that pointer's indirection. We need to + retrieve the lateral coeficientes (+-1) from the lower/middle and + middle/upper cell's lateral combinations. They are needed to evaluate the + existance of a possible BX value, following it's calculation equation */ + lateralCoeficients(miSides, coefsAB); + lateralCoeficients(smSides, coefsCD); + + /* Each of the summs of the 'coefsCD' & 'coefsAB' give always as results 0, +-2 + */ + + int denominator = dVertMI * (coefsCD[1] + coefsCD[0]) - dVertSM * (coefsAB[1] + coefsAB[0]); + + if (denominator == 0) { + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") << "DTp2:validate \t\t\t\t\t\t\t Imposible to calculate BX."; + return; + } + + long int sumA = (long int)floor(MAXDRIFT * (dVertMI * dHorzSM - dVertSM * dHorzMI)); + long int numerator = + (sumA + dVertMI * eqMainBXTerm(smSides, layPairSM, mPath) - dVertSM * eqMainBXTerm(miSides, layPairMI, mPath)); + + // These magic numbers are for doing divisions in the FW. + // These divisions are done with a precision of 18bits. + if (denominator == -1 * DENOM_TYPE1) + bxValue = (numerator * (-1 * DIVISION_HELPER1)) / std::pow(2, NBITS); + else if (denominator == -1 * DENOM_TYPE2) + bxValue = (numerator * (-1 * DIVISION_HELPER2)) / std::pow(2, NBITS); + else if (denominator == -1 * DENOM_TYPE3) + bxValue = (numerator * (-1 * DIVISION_HELPER3)) / std::pow(2, NBITS); + else if (denominator == DENOM_TYPE3) + bxValue = (numerator * (DIVISION_HELPER3)) / std::pow(2, NBITS); + else if (denominator == DENOM_TYPE2) + bxValue = (numerator * (DIVISION_HELPER2)) / std::pow(2, NBITS); + else if (denominator == DENOM_TYPE1) + bxValue = (numerator * (DIVISION_HELPER1)) / std::pow(2, NBITS); + else + LogDebug("MuonPathAnalyzerPerSL") << "Different!"; + if (bxValue < 0) { + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") << "DTp2:validate \t\t\t\t\t\t\t No-valid combination. Negative BX."; + return; + } + + for (int i = 0; i < 3; i++) + if (mPath->primitive(layerIndex[i])->isValidTime()) { + int diffTime = mPath->primitive(layerIndex[i])->tdcTimeStampNoOffset() - bxValue; + + if (diffTime <= 0 or diffTime > round(MAXDRIFT)) { + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") + << "DTp2:validate \t\t\t\t\t\t\t Invalid BX value. at least one crazt TDC time"; + return; + } + } + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") << "DTp2:validate \t\t\t\t\t\t\t BX: " << bxValue; + + /* If you reach here, the BX and partial laterality are considered are valid + */ + latq->bxValue = bxValue; + latq->latQValid = true; +} +int MuonPathAnalyzerPerSL::eqMainBXTerm(LATERAL_CASES sideComb[2], int layerIdx[2], MuonPathPtr &mPath) { + int eqTerm = 0, coefs[2]; + + lateralCoeficients(sideComb, coefs); + + eqTerm = coefs[0] * mPath->primitive(layerIdx[0])->tdcTimeStampNoOffset() + + coefs[1] * mPath->primitive(layerIdx[1])->tdcTimeStampNoOffset(); + + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") << "DTp2:eqMainBXTerm \t\t\t\t\t In eqMainBXTerm EQTerm(BX): " << eqTerm; + + return (eqTerm); +} +int MuonPathAnalyzerPerSL::eqMainTerm(LATERAL_CASES sideComb[2], int layerIdx[2], MuonPathPtr &mPath, int bxValue) { + int eqTerm = 0, coefs[2]; + + lateralCoeficients(sideComb, coefs); + + if (!use_LSB_) + eqTerm = coefs[0] * (mPath->primitive(layerIdx[0])->tdcTimeStampNoOffset() - bxValue) + + coefs[1] * (mPath->primitive(layerIdx[1])->tdcTimeStampNoOffset() - bxValue); + else + eqTerm = coefs[0] * floor((DRIFT_SPEED / (10 * x_precision_)) * + (mPath->primitive(layerIdx[0])->tdcTimeStampNoOffset() - bxValue)) + + coefs[1] * floor((DRIFT_SPEED / (10 * x_precision_)) * + (mPath->primitive(layerIdx[1])->tdcTimeStampNoOffset() - bxValue)); + + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") << "DTp2:\t\t\t\t\t EQTerm(Main): " << eqTerm; + + return (eqTerm); +} + +void MuonPathAnalyzerPerSL::lateralCoeficients(LATERAL_CASES sideComb[2], int *coefs) { + if ((sideComb[0] == LEFT) && (sideComb[1] == LEFT)) { + *(coefs) = +1; + *(coefs + 1) = -1; + } else if ((sideComb[0] == LEFT) && (sideComb[1] == RIGHT)) { + *(coefs) = +1; + *(coefs + 1) = +1; + } else if ((sideComb[0] == RIGHT) && (sideComb[1] == LEFT)) { + *(coefs) = -1; + *(coefs + 1) = -1; + } else if ((sideComb[0] == RIGHT) && (sideComb[1] == RIGHT)) { + *(coefs) = -1; + *(coefs + 1) = +1; + } +} + +/** + * Determines if all valid partial lateral combinations share the same value + * of 'bxValue'. + */ +bool MuonPathAnalyzerPerSL::sameBXValue(PARTIAL_LATQ_TYPE *latq) { + bool result = true; + + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") << "Dtp2:sameBXValue bxTolerance_: " << bxTolerance_; + + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") << "Dtp2:sameBXValue \t\t\t\t\t\t d01:" << abs(latq[0].bxValue - latq[1].bxValue); + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") << "Dtp2:sameBXValue \t\t\t\t\t\t d02:" << abs(latq[0].bxValue - latq[2].bxValue); + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") << "Dtp2:sameBXValue \t\t\t\t\t\t d03:" << abs(latq[0].bxValue - latq[3].bxValue); + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") << "Dtp2:sameBXValue \t\t\t\t\t\t d12:" << abs(latq[1].bxValue - latq[2].bxValue); + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") << "Dtp2:sameBXValue \t\t\t\t\t\t d13:" << abs(latq[1].bxValue - latq[3].bxValue); + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") << "Dtp2:sameBXValue \t\t\t\t\t\t d23:" << abs(latq[2].bxValue - latq[3].bxValue); + + bool d01, d02, d03, d12, d13, d23; + d01 = (abs(latq[0].bxValue - latq[1].bxValue) <= bxTolerance_) ? true : false; + d02 = (abs(latq[0].bxValue - latq[2].bxValue) <= bxTolerance_) ? true : false; + d03 = (abs(latq[0].bxValue - latq[3].bxValue) <= bxTolerance_) ? true : false; + d12 = (abs(latq[1].bxValue - latq[2].bxValue) <= bxTolerance_) ? true : false; + d13 = (abs(latq[1].bxValue - latq[3].bxValue) <= bxTolerance_) ? true : false; + d23 = (abs(latq[2].bxValue - latq[3].bxValue) <= bxTolerance_) ? true : false; + + /* 4 groups of partial combination of valid lateralities */ + if ((latq[0].latQValid && latq[1].latQValid && latq[2].latQValid && latq[3].latQValid) && !(d01 && d12 && d23)) + result = false; + else + /* 4 posible cases of 3 groups of valid partial lateralities */ + if (((latq[0].latQValid && latq[1].latQValid && latq[2].latQValid) && !(d01 && d12)) or + ((latq[0].latQValid && latq[1].latQValid && latq[3].latQValid) && !(d01 && d13)) or + ((latq[0].latQValid && latq[2].latQValid && latq[3].latQValid) && !(d02 && d23)) or + ((latq[1].latQValid && latq[2].latQValid && latq[3].latQValid) && !(d12 && d23))) + result = false; + else + /* Lastly, the 4 possible cases of partial valid lateralities */ + + if (((latq[0].latQValid && latq[1].latQValid) && !d01) or ((latq[0].latQValid && latq[2].latQValid) && !d02) or + ((latq[0].latQValid && latq[3].latQValid) && !d03) or ((latq[1].latQValid && latq[2].latQValid) && !d12) or + ((latq[1].latQValid && latq[3].latQValid) && !d13) or ((latq[2].latQValid && latq[3].latQValid) && !d23)) + result = false; + + return result; +} + +/** Calculate the parameters of the detected trayectories */ +void MuonPathAnalyzerPerSL::calculatePathParameters(MuonPathPtr &mPath) { + // The order is important. + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") + << "DTp2:calculatePathParameters \t\t\t\t\t\t calculating calcCellDriftAndXcoor(mPath) "; + calcCellDriftAndXcoor(mPath); + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") << "DTp2:calculatePathParameters \t\t\t\t\t\t checking mPath->quality() " + << mPath->quality(); + if (mPath->quality() == HIGHQ or mPath->quality() == HIGHQGHOST) { + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") + << "DTp2:calculatePathParameters \t\t\t\t\t\t\t Quality test passed, now calcTanPhiXPosChamber4Hits(mPath) "; + calcTanPhiXPosChamber4Hits(mPath); + } else { + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") + << "DTp2:calculatePathParameters \t\t\t\t\t\t\t Quality test NOT passed calcTanPhiXPosChamber3Hits(mPath) "; + calcTanPhiXPosChamber3Hits(mPath); + } + + if (debug_) + LogDebug("MuonPathAnalyzerPerSL") << "DTp2:calculatePathParameters \t\t\t\t\t\t calcChiSquare(mPath) "; + calcChiSquare(mPath); +} + +void MuonPathAnalyzerPerSL::calcTanPhiXPosChamber(MuonPathPtr &mPath) { + int layerIdx[2]; + /* + To calculate path's angle are only necessary two valid primitives. + This method should be called only when a 'MuonPath' is determined as valid, + so, at least, three of its primitives must have a valid time. + With this two comparitions (which can be implemented easily as multiplexors + in the FPGA) this method ensures to catch two of those valid primitives to + evaluate the angle. + + The first one is below the middle line of the superlayer, while the other + one is above this line + */ + if (mPath->primitive(0)->isValidTime()) + layerIdx[0] = 0; + else + layerIdx[0] = 1; + + if (mPath->primitive(3)->isValidTime()) + layerIdx[1] = 3; + else + layerIdx[1] = 2; + + /* We identify along which cells' sides the muon travels */ + LATERAL_CASES sideComb[2]; + sideComb[0] = (mPath->lateralComb())[layerIdx[0]]; + sideComb[1] = (mPath->lateralComb())[layerIdx[1]]; + + /* Horizontal gap between cells in cell's semi-length units */ + int dHoriz = (mPath->cellLayout())[layerIdx[1]] - (mPath->cellLayout())[layerIdx[0]]; + + /* Vertical gap between cells in cell's height units */ + int dVert = layerIdx[1] - layerIdx[0]; + + /*-----------------------------------------------------------------*/ + /*--------------------- Phi angle calculation ---------------------*/ + /*-----------------------------------------------------------------*/ + float num = CELL_SEMILENGTH * dHoriz + DRIFT_SPEED * eqMainTerm(sideComb, layerIdx, mPath, mPath->bxTimeValue()); + + float denom = CELL_HEIGHT * dVert; + float tanPhi = num / denom; + + mPath->setTanPhi(tanPhi); + + /*-----------------------------------------------------------------*/ + /*----------------- Horizontal coord. calculation -----------------*/ + /*-----------------------------------------------------------------*/ + + /* + Using known coordinates, relative to superlayer axis reference, (left most + superlayer side, and middle line between 2nd and 3rd layers), calculating + horizontal coordinate implies using a basic line equation: + (y - y0) = (x - x0) * cotg(Phi) + This horizontal coordinate can be obtained setting y = 0 on last equation, + and also setting y0 and x0 with the values of a known muon's path cell + position hit. + It's enough to use the lower cell (layerIdx[0]) coordinates. So: + xC = x0 - y0 * tan(Phi) + */ + float lowerXPHorizPos = mPath->xCoorCell(layerIdx[0]); + + float lowerXPVertPos = 0; // This is only the absolute value distance. + if (layerIdx[0] == 0) + lowerXPVertPos = CELL_HEIGHT + CELL_SEMIHEIGHT; + else + lowerXPVertPos = CELL_SEMIHEIGHT; + + mPath->setHorizPos(lowerXPHorizPos + lowerXPVertPos * tanPhi); +} + +/** + * Coordinate and angle calculations for a 4 HITS cases + */ +void MuonPathAnalyzerPerSL::calcTanPhiXPosChamber4Hits(MuonPathPtr &mPath) { + int x_prec_inv = (int)(1. / (10. * x_precision_)); + int numberOfBits = (int)(round(std::log(x_prec_inv) / std::log(2.))); + int numerator = 3 * (int)round(mPath->xCoorCell(3) / (10 * x_precision_)) + + (int)round(mPath->xCoorCell(2) / (10 * x_precision_)) - + (int)round(mPath->xCoorCell(1) / (10 * x_precision_)) - + 3 * (int)round(mPath->xCoorCell(0) / (10 * x_precision_)); + int CELL_HEIGHT_JM = pow(2, 15) / ((int)(10 * CELL_HEIGHT)); + int tanPhi_x4096 = (numerator * CELL_HEIGHT_JM) >> (3 + numberOfBits); + mPath->setTanPhi(tanPhi_x4096 * tanPsi_precision_); + + float XPos = (mPath->xCoorCell(0) + mPath->xCoorCell(1) + mPath->xCoorCell(2) + mPath->xCoorCell(3)) / 4; + mPath->setHorizPos(floor(XPos / (10 * x_precision_)) * 10 * x_precision_); +} + +/** + * 3 HITS cases + */ +void MuonPathAnalyzerPerSL::calcTanPhiXPosChamber3Hits(MuonPathPtr &mPath) { + int layerIdx[2]; + int x_prec_inv = (int)(1. / (10. * x_precision_)); + int numberOfBits = (int)(round(std::log(x_prec_inv) / std::log(2.))); + + if (mPath->primitive(0)->isValidTime()) + layerIdx[0] = 0; + else + layerIdx[0] = 1; + + if (mPath->primitive(3)->isValidTime()) + layerIdx[1] = 3; + else + layerIdx[1] = 2; + + /*-----------------------------------------------------------------*/ + /*--------------------- Phi angle calculation ---------------------*/ + /*-----------------------------------------------------------------*/ + + int tan_division_denominator_bits = 16; + + int num = + ((int)((int)(x_prec_inv * mPath->xCoorCell(layerIdx[1])) - (int)(x_prec_inv * mPath->xCoorCell(layerIdx[0]))) + << (12 - numberOfBits)); + int denominator = (layerIdx[1] - layerIdx[0]) * CELL_HEIGHT; + int denominator_inv = ((int)(0.5 + pow(2, tan_division_denominator_bits) / float(denominator))); + + float tanPhi = ((num * denominator_inv) >> tan_division_denominator_bits) / ((1. / tanPsi_precision_)); + + mPath->setTanPhi(tanPhi); + + /*-----------------------------------------------------------------*/ + /*----------------- Horizontal coord. calculation -----------------*/ + /*-----------------------------------------------------------------*/ + float XPos = 0; + if (mPath->primitive(0)->isValidTime() and mPath->primitive(3)->isValidTime()) + XPos = (mPath->xCoorCell(0) + mPath->xCoorCell(3)) / 2; + else + XPos = (mPath->xCoorCell(1) + mPath->xCoorCell(2)) / 2; + + mPath->setHorizPos(floor(XPos / (10 * x_precision_)) * 10 * x_precision_); +} + +/** + * Calculate the drift distances of each wire and the horizontal position + */ +void MuonPathAnalyzerPerSL::calcCellDriftAndXcoor(MuonPathPtr &mPath) { + long int drift_speed_new = 889; + long int drift_dist_um_x4; + long int wireHorizPos_x4; + long int pos_mm_x4; + int x_prec_inv = (int)(1. / (10. * x_precision_)); + + for (int i = 0; i <= 3; i++) + if (mPath->primitive(i)->isValidTime()) { + drift_dist_um_x4 = + drift_speed_new * ((long int)mPath->primitive(i)->tdcTimeStampNoOffset() - (long int)mPath->bxTimeValue()); + wireHorizPos_x4 = (long)(mPath->primitive(i)->wireHorizPos() * x_prec_inv); + + if ((mPath->lateralComb())[i] == LEFT) + pos_mm_x4 = wireHorizPos_x4 - (drift_dist_um_x4 >> 10); + else + pos_mm_x4 = wireHorizPos_x4 + (drift_dist_um_x4 >> 10); + + mPath->setXCoorCell(pos_mm_x4 * (10 * x_precision_), i); + mPath->setDriftDistance(((float)(drift_dist_um_x4 >> 10)) * (10 * x_precision_), i); + } +} + +/** + * Calculate the quality estimator of each trayectory. + */ +void MuonPathAnalyzerPerSL::calcChiSquare(MuonPathPtr &mPath) { + int x_prec_inv = (int)(1. / (10. * x_precision_)); + int numberOfBits = (int)(round(std::log(x_prec_inv) / std::log(2.))); + long int Z_FACTOR[NUM_LAYERS] = {-6, -2, 2, 6}; + for (int i = 0; i < 4; i++) { + Z_FACTOR[i] = Z_FACTOR[i] * (long int)CELL_HEIGHT; + } + long int sum_A = 0, sum_B = 0; + long int chi2_mm2_x1024 = 0; + for (int i = 0; i < 4; i++) { + if (mPath->primitive(i)->isValidTime()) { + sum_A = (((int)(mPath->xCoorCell(i) / (10 * x_precision_))) - ((int)(mPath->horizPos() / (10 * x_precision_)))) + << (14 - numberOfBits); + sum_B = Z_FACTOR[i] * ((int)(mPath->tanPhi() / tanPsi_precision_)); + chi2_mm2_x1024 += (sum_A - sum_B) * (sum_A - sum_B); + } + } + chi2_mm2_x1024 = chi2_mm2_x1024 >> 18; + + mPath->setChiSquare(((double)chi2_mm2_x1024 / 1024.)); +} + +int MuonPathAnalyzerPerSL::omittedHit(int idx) { + switch (idx) { + case 0: + return 3; + case 1: + return 0; + case 2: + return 2; + case 3: + return 1; + } + + return -1; +} diff --git a/L1Trigger/DTTriggerPhase2/src/MuonPathAssociator.cc b/L1Trigger/DTTriggerPhase2/src/MuonPathAssociator.cc new file mode 100644 index 0000000000000..b1150be0cc92d --- /dev/null +++ b/L1Trigger/DTTriggerPhase2/src/MuonPathAssociator.cc @@ -0,0 +1,1023 @@ +#include "L1Trigger/DTTriggerPhase2/interface/MuonPathAssociator.h" +#include "L1Trigger/DTTriggerPhase2/interface/MuonPathAnalyzerPerSL.h" +#include "L1Trigger/DTTriggerPhase2/interface/constants.h" +#include "FWCore/MessageLogger/interface/MessageLogger.h" + +using namespace edm; +using namespace std; +using namespace cmsdt; + +// ============================================================================ +// Constructors and destructor +// ============================================================================ +MuonPathAssociator::MuonPathAssociator(const ParameterSet &pset, edm::ConsumesCollector &iC) { + // Obtention of parameters + debug_ = pset.getUntrackedParameter("debug"); + clean_chi2_correlation_ = pset.getUntrackedParameter("clean_chi2_correlation"); + use_LSB_ = pset.getUntrackedParameter("use_LSB"); + tanPsi_precision_ = pset.getUntrackedParameter("tanPsi_precision"); + x_precision_ = pset.getUntrackedParameter("x_precision"); + useBX_correlation_ = pset.getUntrackedParameter("useBX_correlation"); + allow_confirmation_ = pset.getUntrackedParameter("allow_confirmation"); + dT0_correlate_TP_ = pset.getUntrackedParameter("dT0_correlate_TP"); + dBX_correlate_TP_ = pset.getUntrackedParameter("dBX_correlate_TP"); + dTanPsi_correlate_TP_ = pset.getUntrackedParameter("dTanPsi_correlate_TP"); + minx_match_2digis_ = pset.getUntrackedParameter("minx_match_2digis"); + chi2corTh_ = pset.getUntrackedParameter("chi2corTh"); + + if (debug_) + LogDebug("MuonPathAssociator") << "MuonPathAssociator: constructor"; + + //shift + int rawId; + shift_filename_ = pset.getParameter("shift_filename"); + std::ifstream ifin3(shift_filename_.fullPath()); + double shift; + if (ifin3.fail()) { + throw cms::Exception("Missing Input File") + << "MuonPathAnalyzerPerSL::MuonPathAnalyzerPerSL() - Cannot find " << shift_filename_.fullPath(); + } + while (ifin3.good()) { + ifin3 >> rawId >> shift; + shiftinfo_[rawId] = shift; + } + + dtGeomH_ = iC.esConsumes(); +} + +MuonPathAssociator::~MuonPathAssociator() { + if (debug_) + LogDebug("MuonPathAssociator") << "MuonPathAssociator: destructor"; +} + +// ============================================================================ +// Main methods (initialise, run, finish) +// ============================================================================ +void MuonPathAssociator::initialise(const edm::EventSetup &iEventSetup) { + if (debug_) + LogDebug("MuonPathAssociator") << "MuonPathAssociator::initialiase"; + + const MuonGeometryRecord &geom = iEventSetup.get(); + dtGeo_ = &geom.get(dtGeomH_); +} + +void MuonPathAssociator::run(edm::Event &iEvent, + const edm::EventSetup &iEventSetup, + edm::Handle digis, + std::vector &inMPaths, + std::vector &outMPaths) { + if (dT0_correlate_TP_) + correlateMPaths(digis, inMPaths, outMPaths); + else { + outMPaths.insert(outMPaths.end(), inMPaths.begin(), inMPaths.end()); + } +} + +void MuonPathAssociator::finish() { + if (debug_) + LogDebug("MuonPathAssociator") << "MuonPathAssociator: finish"; +}; + +void MuonPathAssociator::correlateMPaths(edm::Handle dtdigis, + std::vector &inMPaths, + std::vector &outMPaths) { + int x_prec_inv = (int)(1. / (10. * x_precision_)); + int numberOfBits = (int)(round(std::log(x_prec_inv) / std::log(2.))); + + //Silvia's code for correlationg filteredMetaPrimitives + + if (debug_) + LogDebug("MuonPathAssociator") << "starting correlation"; + + for (int wh = -2; wh <= 2; wh++) { //wheel num: -2, -1, 0, +1, +2 + for (int st = 1; st <= 4; st++) { //station num (MB): 1, 2, 3, 4 + for (int se = 1; se <= 14; se++) { //sector number: 1-12, special sectors 13, 14 to account for bigger MB4s + if (se >= 13 && st != 4) + continue; + + DTChamberId ChId(wh, st, se); + DTSuperLayerId sl1Id(wh, st, se, 1); + DTSuperLayerId sl3Id(wh, st, se, 3); + + //filterSL1 + std::vector SL1metaPrimitives; + for (const auto &metaprimitiveIt : inMPaths) { + if (metaprimitiveIt.rawId == sl1Id.rawId()) + SL1metaPrimitives.push_back(metaprimitiveIt); + } + + //filterSL3 + std::vector SL3metaPrimitives; + for (const auto &metaprimitiveIt : inMPaths) { + if (metaprimitiveIt.rawId == sl3Id.rawId()) + SL3metaPrimitives.push_back(metaprimitiveIt); + } + + if (SL1metaPrimitives.empty() and SL3metaPrimitives.empty()) + continue; + + if (debug_) + LogDebug("MuonPathAssociator") << "correlating " << SL1metaPrimitives.size() << " metaPrim in SL1 and " + << SL3metaPrimitives.size() << " in SL3 for " << sl3Id; + + bool at_least_one_correlation = false; + bool at_least_one_SL1_confirmation = false; + bool at_least_one_SL3_confirmation = false; + + bool useFitSL1[SL1metaPrimitives.size()]; + for (unsigned int i = 0; i < SL1metaPrimitives.size(); i++) + useFitSL1[i] = false; + bool useFitSL3[SL3metaPrimitives.size()]; + for (unsigned int i = 0; i < SL3metaPrimitives.size(); i++) + useFitSL3[i] = false; + + //SL1-SL3 + vector chamberMetaPrimitives; + vector confirmedMetaPrimitives; + vector normalMetaPrimitives; + int sl1 = 0; + int sl3 = 0; + for (auto SL1metaPrimitive = SL1metaPrimitives.begin(); SL1metaPrimitive != SL1metaPrimitives.end(); + ++SL1metaPrimitive, sl1++, sl3 = -1) { + if (clean_chi2_correlation_) + at_least_one_correlation = false; + for (auto SL3metaPrimitive = SL3metaPrimitives.begin(); SL3metaPrimitive != SL3metaPrimitives.end(); + ++SL3metaPrimitive, sl3++) { + if (std::abs(SL1metaPrimitive->tanPhi - SL3metaPrimitive->tanPhi) > dTanPsi_correlate_TP_) + continue; //TanPsi match, SliceTest only + if (useBX_correlation_) { + if (abs(round(SL1metaPrimitive->t0 / (float)LHC_CLK_FREQ) - + round(SL3metaPrimitive->t0 / (float)LHC_CLK_FREQ)) > dBX_correlate_TP_) + continue; //BX match + } else { + if (std::abs(SL1metaPrimitive->t0 - SL3metaPrimitive->t0) >= dT0_correlate_TP_) + continue; //time match + } + long int PosSL1 = (int)round(10 * SL1metaPrimitive->x / (10 * x_precision_)); + long int PosSL3 = (int)round(10 * SL3metaPrimitive->x / (10 * x_precision_)); + double NewSlope = -999.; + if (use_LSB_) { + long int newConstant = (int)(139.5 * 4); + long int difPos_mm_x4 = PosSL3 - PosSL1; + long int tanPsi_x4096_x128 = (difPos_mm_x4)*newConstant; + long int tanPsi_x4096 = tanPsi_x4096_x128 / ((long int)pow(2, 5 + numberOfBits)); + if (tanPsi_x4096 < 0 && tanPsi_x4096_x128 % ((long int)pow(2, 5 + numberOfBits)) != 0) + tanPsi_x4096--; + NewSlope = -tanPsi_x4096 * tanPsi_precision_; + } + double MeanT0 = (SL1metaPrimitive->t0 + SL3metaPrimitive->t0) / 2; + double MeanPos = (PosSL3 + PosSL1) / (2. / (x_precision_)); + if (use_LSB_) { + MeanPos = floor(round(10. * (MeanPos / x_precision_)) * 0.1) * x_precision_; + } + + DTSuperLayerId SLId1(SL1metaPrimitive->rawId); + DTSuperLayerId SLId3(SL3metaPrimitive->rawId); + DTWireId wireId1(SLId1, 2, 1); + DTWireId wireId3(SLId3, 2, 1); + + int wi[8], tdc[8], lat[8]; + wi[0] = SL1metaPrimitive->wi1; + tdc[0] = SL1metaPrimitive->tdc1; + lat[0] = SL1metaPrimitive->lat1; + wi[1] = SL1metaPrimitive->wi2; + tdc[1] = SL1metaPrimitive->tdc2; + lat[1] = SL1metaPrimitive->lat2; + wi[2] = SL1metaPrimitive->wi3; + tdc[2] = SL1metaPrimitive->tdc3; + lat[2] = SL1metaPrimitive->lat3; + wi[3] = SL1metaPrimitive->wi4; + tdc[3] = SL1metaPrimitive->tdc4; + lat[3] = SL1metaPrimitive->lat4; + wi[4] = SL3metaPrimitive->wi1; + tdc[4] = SL3metaPrimitive->tdc1; + lat[4] = SL3metaPrimitive->lat1; + wi[5] = SL3metaPrimitive->wi2; + tdc[5] = SL3metaPrimitive->tdc2; + lat[5] = SL3metaPrimitive->lat2; + wi[6] = SL3metaPrimitive->wi3; + tdc[6] = SL3metaPrimitive->tdc3; + lat[6] = SL3metaPrimitive->lat3; + wi[7] = SL3metaPrimitive->wi4; + tdc[7] = SL3metaPrimitive->tdc4; + lat[7] = SL3metaPrimitive->lat4; + + long int chi2 = 0; + + long int CH_CENTER_TO_MID_SL_P = (long int)(117.5 * 4); + long int Z_FACTOR_CORR[8] = {-6, -2, 2, 6, -6, -2, 2, 6}; + + for (int i = 0; i < 8; i++) { + int sign = 2 * (i / 4) - 1; + Z_FACTOR_CORR[i] = Z_FACTOR_CORR[i] * CELL_HEIGHT + CH_CENTER_TO_MID_SL_P * sign; + } + long int sum_A, sum_B; + for (int i = 0; i < 8; i++) { + long int shift, slTime; + if (i / 4 == 0) { + shift = round(shiftinfo_[wireId1.rawId()] / x_precision_); + slTime = SL1metaPrimitive->t0; + } else { + shift = round(shiftinfo_[wireId3.rawId()] / x_precision_); + slTime = SL3metaPrimitive->t0; + } + if (wi[i] != -1) { + long int drift_speed_new = 889; + long int drift_dist_um_x4 = drift_speed_new * (((long int)tdc[i]) - slTime); + long int wireHorizPos_x4 = (42 * wi[i] + ((i + 1) % 2) * 21) / (10 * x_precision_); + long int pos_mm_x4; + + if (lat[i] == 0) { + pos_mm_x4 = wireHorizPos_x4 - (drift_dist_um_x4 >> 10); + } else { + pos_mm_x4 = wireHorizPos_x4 + (drift_dist_um_x4 >> 10); + } + sum_A = shift + pos_mm_x4 - (long int)round(MeanPos / x_precision_); + sum_A = sum_A << (14 - numberOfBits); + sum_B = Z_FACTOR_CORR[i] * (long int)round(-NewSlope / tanPsi_precision_); + chi2 += ((sum_A - sum_B) * (sum_A - sum_B)) >> 2; + } + } + + double newChi2 = (double)(chi2 >> 16) / (1024. * 100.); + + if (newChi2 > chi2corTh_) + continue; + + // Fill the used vectors + useFitSL1[sl1] = true; + useFitSL3[sl3] = true; + + int quality = 0; + if (SL3metaPrimitive->quality <= 2 and SL1metaPrimitive->quality <= 2) + quality = 6; + + if ((SL3metaPrimitive->quality >= 3 && SL1metaPrimitive->quality <= 2) or + (SL1metaPrimitive->quality >= 3 && SL3metaPrimitive->quality <= 2)) + quality = 8; + + if (SL3metaPrimitive->quality >= 3 && SL1metaPrimitive->quality >= 3) + quality = 9; + + double z = 0; + if (ChId.station() >= 3) + z = -1.8; + GlobalPoint jm_x_cmssw_global = dtGeo_->chamber(ChId)->toGlobal( + LocalPoint(MeanPos, 0., z)); //Jm_x is already extrapolated to the middle of the SL + int thisec = ChId.sector(); + if (se == 13) + thisec = 4; + if (se == 14) + thisec = 10; + double phi = jm_x_cmssw_global.phi() - 0.5235988 * (thisec - 1); + double psi = atan(NewSlope); + double phiB = hasPosRF(ChId.wheel(), ChId.sector()) ? psi - phi : -psi - phi; + + if (!clean_chi2_correlation_) + outMPaths.emplace_back(ChId.rawId(), + MeanT0, + MeanPos, + NewSlope, + phi, + phiB, + newChi2, + quality, + SL1metaPrimitive->wi1, + SL1metaPrimitive->tdc1, + SL1metaPrimitive->lat1, + SL1metaPrimitive->wi2, + SL1metaPrimitive->tdc2, + SL1metaPrimitive->lat2, + SL1metaPrimitive->wi3, + SL1metaPrimitive->tdc3, + SL1metaPrimitive->lat3, + SL1metaPrimitive->wi4, + SL1metaPrimitive->tdc4, + SL1metaPrimitive->lat4, + SL3metaPrimitive->wi1, + SL3metaPrimitive->tdc1, + SL3metaPrimitive->lat1, + SL3metaPrimitive->wi2, + SL3metaPrimitive->tdc2, + SL3metaPrimitive->lat2, + SL3metaPrimitive->wi3, + SL3metaPrimitive->tdc3, + SL3metaPrimitive->lat3, + SL3metaPrimitive->wi4, + SL3metaPrimitive->tdc4, + SL3metaPrimitive->lat4); + else + chamberMetaPrimitives.emplace_back(ChId.rawId(), + MeanT0, + MeanPos, + NewSlope, + phi, + phiB, + newChi2, + quality, + SL1metaPrimitive->wi1, + SL1metaPrimitive->tdc1, + SL1metaPrimitive->lat1, + SL1metaPrimitive->wi2, + SL1metaPrimitive->tdc2, + SL1metaPrimitive->lat2, + SL1metaPrimitive->wi3, + SL1metaPrimitive->tdc3, + SL1metaPrimitive->lat3, + SL1metaPrimitive->wi4, + SL1metaPrimitive->tdc4, + SL1metaPrimitive->lat4, + SL3metaPrimitive->wi1, + SL3metaPrimitive->tdc1, + SL3metaPrimitive->lat1, + SL3metaPrimitive->wi2, + SL3metaPrimitive->tdc2, + SL3metaPrimitive->lat2, + SL3metaPrimitive->wi3, + SL3metaPrimitive->tdc3, + SL3metaPrimitive->lat3, + SL3metaPrimitive->wi4, + SL3metaPrimitive->tdc4, + SL3metaPrimitive->lat4); + + at_least_one_correlation = true; + } + + if (at_least_one_correlation == false && + allow_confirmation_ == true) { //no correlation was found, trying with pairs of two digis in the other SL + int matched_digis = 0; + double minx = minx_match_2digis_; + double min2x = minx_match_2digis_; + int best_tdc = -1; + int next_tdc = -1; + int best_wire = -1; + int next_wire = -1; + int best_layer = -1; + int next_layer = -1; + int best_lat = -1; + int next_lat = -1; + int lat = -1; + + for (const auto &dtLayerId_It : *dtdigis) { + const DTLayerId dtLId = dtLayerId_It.first; + const DTSuperLayerId &dtSLId(dtLId); + if (dtSLId.rawId() != sl3Id.rawId()) + continue; + double l_shift = 0; + if (dtLId.layer() == 4) + l_shift = X_POS_L4; + else if (dtLId.layer() == 3) + l_shift = X_POS_L3; + else if (dtLId.layer() == 2) + l_shift = -1 * X_POS_L3; + else if (dtLId.layer() == 1) + l_shift = -1 * X_POS_L4; + double x_inSL3 = SL1metaPrimitive->x - SL1metaPrimitive->tanPhi * (23.5 + l_shift); + for (auto digiIt = (dtLayerId_It.second).first; digiIt != (dtLayerId_It.second).second; ++digiIt) { + DTWireId wireId(dtLId, (*digiIt).wire()); + int x_wire = shiftinfo_[wireId.rawId()] + ((*digiIt).time() - SL1metaPrimitive->t0) * 0.00543; + int x_wire_left = shiftinfo_[wireId.rawId()] - ((*digiIt).time() - SL1metaPrimitive->t0) * 0.00543; + lat = 1; + if (std::abs(x_inSL3 - x_wire) > std::abs(x_inSL3 - x_wire_left)) { + x_wire = x_wire_left; //choose the closest laterality + lat = 0; + } + if (std::abs(x_inSL3 - x_wire) < minx) { + minx = std::abs(x_inSL3 - x_wire); + next_wire = best_wire; + next_tdc = best_tdc; + next_layer = best_layer; + next_lat = best_lat; + + best_wire = (*digiIt).wire(); + best_tdc = (*digiIt).time(); + best_layer = dtLId.layer(); + best_lat = lat; + matched_digis++; + } else if ((std::abs(x_inSL3 - x_wire) >= minx) && (std::abs(x_inSL3 - x_wire) < min2x)) { + min2x = std::abs(x_inSL3 - x_wire); + next_wire = (*digiIt).wire(); + next_tdc = (*digiIt).time(); + next_layer = dtLId.layer(); + next_lat = lat; + matched_digis++; + } + } + } + if (matched_digis >= 2 and best_layer != -1 and next_layer != -1) { + int new_quality = 7; + if (SL1metaPrimitive->quality <= 2) + new_quality = 5; + + int wi1 = -1; + int tdc1 = -1; + int lat1 = -1; + int wi2 = -1; + int tdc2 = -1; + int lat2 = -1; + int wi3 = -1; + int tdc3 = -1; + int lat3 = -1; + int wi4 = -1; + int tdc4 = -1; + int lat4 = -1; + + if (next_layer == 1) { + wi1 = next_wire; + tdc1 = next_tdc; + lat1 = next_lat; + } + if (next_layer == 2) { + wi2 = next_wire; + tdc2 = next_tdc; + lat2 = next_lat; + } + if (next_layer == 3) { + wi3 = next_wire; + tdc3 = next_tdc; + lat3 = next_lat; + } + if (next_layer == 4) { + wi4 = next_wire; + tdc4 = next_tdc; + lat4 = next_lat; + } + + if (best_layer == 1) { + wi1 = best_wire; + tdc1 = best_tdc; + lat1 = best_lat; + } + if (best_layer == 2) { + wi2 = best_wire; + tdc2 = best_tdc; + lat2 = best_lat; + } + if (best_layer == 3) { + wi3 = best_wire; + tdc3 = best_tdc; + lat3 = best_lat; + } + if (best_layer == 4) { + wi4 = best_wire; + tdc4 = best_tdc; + lat4 = best_lat; + } + + if (!clean_chi2_correlation_) + outMPaths.emplace_back(metaPrimitive({ChId.rawId(), + SL1metaPrimitive->t0, + SL1metaPrimitive->x, + SL1metaPrimitive->tanPhi, + SL1metaPrimitive->phi, + SL1metaPrimitive->phiB, + SL1metaPrimitive->chi2, + new_quality, + SL1metaPrimitive->wi1, + SL1metaPrimitive->tdc1, + SL1metaPrimitive->lat1, + SL1metaPrimitive->wi2, + SL1metaPrimitive->tdc2, + SL1metaPrimitive->lat2, + SL1metaPrimitive->wi3, + SL1metaPrimitive->tdc3, + SL1metaPrimitive->lat3, + SL1metaPrimitive->wi4, + SL1metaPrimitive->tdc4, + SL1metaPrimitive->lat4, + wi1, + tdc1, + lat1, + wi2, + tdc2, + lat2, + wi3, + tdc3, + lat3, + wi4, + tdc4, + lat4, + -1})); + else + confirmedMetaPrimitives.emplace_back(metaPrimitive({ChId.rawId(), + SL1metaPrimitive->t0, + SL1metaPrimitive->x, + SL1metaPrimitive->tanPhi, + SL1metaPrimitive->phi, + SL1metaPrimitive->phiB, + SL1metaPrimitive->chi2, + new_quality, + SL1metaPrimitive->wi1, + SL1metaPrimitive->tdc1, + SL1metaPrimitive->lat1, + SL1metaPrimitive->wi2, + SL1metaPrimitive->tdc2, + SL1metaPrimitive->lat2, + SL1metaPrimitive->wi3, + SL1metaPrimitive->tdc3, + SL1metaPrimitive->lat3, + SL1metaPrimitive->wi4, + SL1metaPrimitive->tdc4, + SL1metaPrimitive->lat4, + wi1, + tdc1, + lat1, + wi2, + tdc2, + lat2, + wi3, + tdc3, + lat3, + wi4, + tdc4, + lat4, + -1})); + useFitSL1[sl1] = true; + at_least_one_SL1_confirmation = true; + } + } + } + + //finish SL1-SL3 + + //SL3-SL1 + sl3 = 0; + for (auto SL3metaPrimitive = SL3metaPrimitives.begin(); SL3metaPrimitive != SL3metaPrimitives.end(); + ++SL3metaPrimitive, sl3++) { + if (useFitSL3[sl3]) + continue; + if ((at_least_one_correlation == false || clean_chi2_correlation_) && + allow_confirmation_) { //no correlation was found, trying with pairs of two digis in the other SL + + int matched_digis = 0; + double minx = minx_match_2digis_; + double min2x = minx_match_2digis_; + int best_tdc = -1; + int next_tdc = -1; + int best_wire = -1; + int next_wire = -1; + int best_layer = -1; + int next_layer = -1; + int best_lat = -1; + int next_lat = -1; + int lat = -1; + + for (const auto &dtLayerId_It : *dtdigis) { + const DTLayerId dtLId = dtLayerId_It.first; + const DTSuperLayerId &dtSLId(dtLId); + if (dtSLId.rawId() != sl1Id.rawId()) + continue; + double l_shift = 0; + if (dtLId.layer() == 4) + l_shift = 1.95; + if (dtLId.layer() == 3) + l_shift = 0.65; + if (dtLId.layer() == 2) + l_shift = -0.65; + if (dtLId.layer() == 1) + l_shift = -1.95; + double x_inSL1 = SL3metaPrimitive->x + SL3metaPrimitive->tanPhi * (23.5 - l_shift); + for (auto digiIt = (dtLayerId_It.second).first; digiIt != (dtLayerId_It.second).second; ++digiIt) { + DTWireId wireId(dtLId, (*digiIt).wire()); + int x_wire = shiftinfo_[wireId.rawId()] + ((*digiIt).time() - SL3metaPrimitive->t0) * 0.00543; + int x_wire_left = shiftinfo_[wireId.rawId()] - ((*digiIt).time() - SL3metaPrimitive->t0) * 0.00543; + lat = 1; + if (std::abs(x_inSL1 - x_wire) > std::abs(x_inSL1 - x_wire_left)) { + x_wire = x_wire_left; //choose the closest laterality + lat = 0; + } + if (std::abs(x_inSL1 - x_wire) < minx) { + minx = std::abs(x_inSL1 - x_wire); + next_wire = best_wire; + next_tdc = best_tdc; + next_layer = best_layer; + next_lat = best_lat; + + best_wire = (*digiIt).wire(); + best_tdc = (*digiIt).time(); + best_layer = dtLId.layer(); + best_lat = lat; + matched_digis++; + } else if ((std::abs(x_inSL1 - x_wire) >= minx) && (std::abs(x_inSL1 - x_wire) < min2x)) { + minx = std::abs(x_inSL1 - x_wire); + next_wire = (*digiIt).wire(); + next_tdc = (*digiIt).time(); + next_layer = dtLId.layer(); + next_lat = lat; + matched_digis++; + } + } + } + if (matched_digis >= 2 and best_layer != -1 and next_layer != -1) { + int new_quality = 7; + if (SL3metaPrimitive->quality <= 2) + new_quality = 5; + + int wi1 = -1; + int tdc1 = -1; + int lat1 = -1; + int wi2 = -1; + int tdc2 = -1; + int lat2 = -1; + int wi3 = -1; + int tdc3 = -1; + int lat3 = -1; + int wi4 = -1; + int tdc4 = -1; + int lat4 = -1; + + if (next_layer == 1) { + wi1 = next_wire; + tdc1 = next_tdc; + lat1 = next_lat; + } + if (next_layer == 2) { + wi2 = next_wire; + tdc2 = next_tdc; + lat2 = next_lat; + } + if (next_layer == 3) { + wi3 = next_wire; + tdc3 = next_tdc; + lat3 = next_lat; + } + if (next_layer == 4) { + wi4 = next_wire; + tdc4 = next_tdc; + lat4 = next_lat; + } + + if (best_layer == 1) { + wi1 = best_wire; + tdc1 = best_tdc; + lat1 = best_lat; + } + if (best_layer == 2) { + wi2 = best_wire; + tdc2 = best_tdc; + lat2 = best_lat; + } + if (best_layer == 3) { + wi3 = best_wire; + tdc3 = best_tdc; + lat3 = best_lat; + } + if (best_layer == 4) { + wi4 = best_wire; + tdc4 = best_tdc; + lat4 = best_lat; + } + + if (!clean_chi2_correlation_) + outMPaths.push_back(metaPrimitive({ChId.rawId(), + SL3metaPrimitive->t0, + SL3metaPrimitive->x, + SL3metaPrimitive->tanPhi, + SL3metaPrimitive->phi, + SL3metaPrimitive->phiB, + SL3metaPrimitive->chi2, + new_quality, + wi1, + tdc1, + lat1, + wi2, + tdc2, + lat2, + wi3, + tdc3, + lat3, + wi4, + tdc4, + lat4, + SL3metaPrimitive->wi1, + SL3metaPrimitive->tdc1, + SL3metaPrimitive->lat1, + SL3metaPrimitive->wi2, + SL3metaPrimitive->tdc2, + SL3metaPrimitive->lat2, + SL3metaPrimitive->wi3, + SL3metaPrimitive->tdc3, + SL3metaPrimitive->lat3, + SL3metaPrimitive->wi4, + SL3metaPrimitive->tdc4, + SL3metaPrimitive->lat4, + -1})); + else + confirmedMetaPrimitives.push_back(metaPrimitive({ChId.rawId(), + SL3metaPrimitive->t0, + SL3metaPrimitive->x, + SL3metaPrimitive->tanPhi, + SL3metaPrimitive->phi, + SL3metaPrimitive->phiB, + SL3metaPrimitive->chi2, + new_quality, + wi1, + tdc1, + lat1, + wi2, + tdc2, + lat2, + wi3, + tdc3, + lat3, + wi4, + tdc4, + lat4, + SL3metaPrimitive->wi1, + SL3metaPrimitive->tdc1, + SL3metaPrimitive->lat1, + SL3metaPrimitive->wi2, + SL3metaPrimitive->tdc2, + SL3metaPrimitive->lat2, + SL3metaPrimitive->wi3, + SL3metaPrimitive->tdc3, + SL3metaPrimitive->lat3, + SL3metaPrimitive->wi4, + SL3metaPrimitive->tdc4, + SL3metaPrimitive->lat4, + -1})); + useFitSL3[sl3] = true; + at_least_one_SL3_confirmation = true; + } + } + } + // Start correlation cleaning + if (clean_chi2_correlation_) { + if (debug_) + LogDebug("MuonPathAssociator") << "Pushing back correlated MPs to the MPs collection"; + removeSharingFits(chamberMetaPrimitives, outMPaths); + } + if (clean_chi2_correlation_) { + if (debug_) + LogDebug("MuonPathAssociator") << "Pushing back confirmed MPs to the complete vector"; + removeSharingHits(confirmedMetaPrimitives, chamberMetaPrimitives, outMPaths); + } + + //finish SL3-SL1 + if (at_least_one_correlation == false || clean_chi2_correlation_) { + if (debug_ && !at_least_one_correlation) + LogDebug("MuonPathAssociator") + << "correlation we found zero correlations, adding both collections as they are to the outMPaths"; + if (debug_) + LogDebug("MuonPathAssociator") + << "correlation sizes:" << SL1metaPrimitives.size() << " " << SL3metaPrimitives.size(); + if (at_least_one_SL1_confirmation == false || clean_chi2_correlation_) { + sl1 = 0; + for (auto SL1metaPrimitive = SL1metaPrimitives.begin(); SL1metaPrimitive != SL1metaPrimitives.end(); + ++SL1metaPrimitive, sl1++) { + if (useFitSL1[sl1]) + continue; + + DTSuperLayerId SLId(SL1metaPrimitive->rawId); + DTChamberId(SLId.wheel(), SLId.station(), SLId.sector()); + metaPrimitive newSL1metaPrimitive = {ChId.rawId(), + SL1metaPrimitive->t0, + SL1metaPrimitive->x, + SL1metaPrimitive->tanPhi, + SL1metaPrimitive->phi, + SL1metaPrimitive->phiB, + SL1metaPrimitive->chi2, + SL1metaPrimitive->quality, + SL1metaPrimitive->wi1, + SL1metaPrimitive->tdc1, + SL1metaPrimitive->lat1, + SL1metaPrimitive->wi2, + SL1metaPrimitive->tdc2, + SL1metaPrimitive->lat2, + SL1metaPrimitive->wi3, + SL1metaPrimitive->tdc3, + SL1metaPrimitive->lat3, + SL1metaPrimitive->wi4, + SL1metaPrimitive->tdc4, + SL1metaPrimitive->lat4, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1}; + + bool ok = true; + for (auto &metaPrimitive : chamberMetaPrimitives) { + if (!isNotAPrimo(newSL1metaPrimitive, metaPrimitive)) { + ok = false; + break; + } + } + if (!ok) + continue; + + if (!clean_chi2_correlation_) + outMPaths.push_back(newSL1metaPrimitive); + else + normalMetaPrimitives.push_back(newSL1metaPrimitive); + } + } + if (at_least_one_SL3_confirmation == false || clean_chi2_correlation_) { + sl3 = 0; + for (auto SL3metaPrimitive = SL3metaPrimitives.begin(); SL3metaPrimitive != SL3metaPrimitives.end(); + ++SL3metaPrimitive, sl3++) { + if (useFitSL3[sl3]) + continue; + DTSuperLayerId SLId(SL3metaPrimitive->rawId); + DTChamberId(SLId.wheel(), SLId.station(), SLId.sector()); + metaPrimitive newSL3metaPrimitive = {ChId.rawId(), + SL3metaPrimitive->t0, + SL3metaPrimitive->x, + SL3metaPrimitive->tanPhi, + SL3metaPrimitive->phi, + SL3metaPrimitive->phiB, + SL3metaPrimitive->chi2, + SL3metaPrimitive->quality, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + SL3metaPrimitive->wi1, + SL3metaPrimitive->tdc1, + SL3metaPrimitive->lat1, + SL3metaPrimitive->wi2, + SL3metaPrimitive->tdc2, + SL3metaPrimitive->lat2, + SL3metaPrimitive->wi3, + SL3metaPrimitive->tdc3, + SL3metaPrimitive->lat3, + SL3metaPrimitive->wi4, + SL3metaPrimitive->tdc4, + SL3metaPrimitive->lat4, + -1}; + + if (!clean_chi2_correlation_) + outMPaths.push_back(newSL3metaPrimitive); + else + normalMetaPrimitives.push_back(newSL3metaPrimitive); + } + } + } + + SL1metaPrimitives.clear(); + SL1metaPrimitives.erase(SL1metaPrimitives.begin(), SL1metaPrimitives.end()); + SL3metaPrimitives.clear(); + SL3metaPrimitives.erase(SL3metaPrimitives.begin(), SL3metaPrimitives.end()); + + vector auxMetaPrimitives; + if (clean_chi2_correlation_) { + if (debug_) + LogDebug("MuonPathAssociator") << "Pushing back normal MPs to the auxiliar vector"; + removeSharingHits(normalMetaPrimitives, confirmedMetaPrimitives, auxMetaPrimitives); + } + if (clean_chi2_correlation_) { + if (debug_) + LogDebug("MuonPathAssociator") << "Pushing back normal MPs to the MPs collection"; + removeSharingHits(auxMetaPrimitives, chamberMetaPrimitives, outMPaths); + } + } + } + } +} + +void MuonPathAssociator::removeSharingFits(vector &chamberMPaths, vector &allMPaths) { + bool useFit[chamberMPaths.size()]; + for (unsigned int i = 0; i < chamberMPaths.size(); i++) { + useFit[i] = true; + } + for (unsigned int i = 0; i < chamberMPaths.size(); i++) { + if (debug_) + LogDebug("MuonPathAssociator") << "Looking at prim" << i; + if (!useFit[i]) + continue; + for (unsigned int j = i + 1; j < chamberMPaths.size(); j++) { + if (debug_) + LogDebug("MuonPathAssociator") << "Comparing with prim " << j; + if (!useFit[j]) + continue; + metaPrimitive first = chamberMPaths[i]; + metaPrimitive second = chamberMPaths[j]; + if (shareFit(first, second)) { + if (first.quality > second.quality) + useFit[j] = false; + else if (first.quality < second.quality) + useFit[i] = false; + else { + if (first.chi2 < second.chi2) + useFit[j] = false; + else { + useFit[i] = false; + break; + } + } + } + } + if (useFit[i]) { + if (debug_) + printmPC(chamberMPaths[i]); + allMPaths.push_back(chamberMPaths[i]); + } + } + if (debug_) + LogDebug("MuonPathAssociator") << "---Swapping chamber---"; +} + +void MuonPathAssociator::removeSharingHits(std::vector &firstMPaths, + std::vector &secondMPaths, + std::vector &allMPaths) { + for (auto &firstMP : firstMPaths) { + if (debug_) + LogDebug("MuonPathAssociator") << "----------------------------------"; + if (debug_) + LogDebug("MuonPathAssociator") << "Turn for "; + if (debug_) + printmPC(firstMP); + bool ok = true; + for (auto &secondMP : secondMPaths) { + if (debug_) + LogDebug("MuonPathAssociator") << "Comparing with "; + if (debug_) + printmPC(secondMP); + if (!isNotAPrimo(firstMP, secondMP)) { + ok = false; + break; + } + } + if (ok) { + allMPaths.push_back(firstMP); + if (debug_) + printmPC(firstMP); + } + if (debug_) + LogDebug("MuonPathAssociator") << "----------------------------------"; + } +} + +bool MuonPathAssociator::shareFit(metaPrimitive first, metaPrimitive second) { + bool lay1 = (first.wi1 == second.wi1) && (first.tdc1 = second.tdc1); + bool lay2 = (first.wi2 == second.wi2) && (first.tdc2 = second.tdc2); + bool lay3 = (first.wi3 == second.wi3) && (first.tdc3 = second.tdc3); + bool lay4 = (first.wi4 == second.wi4) && (first.tdc4 = second.tdc4); + bool lay5 = (first.wi5 == second.wi5) && (first.tdc5 = second.tdc5); + bool lay6 = (first.wi6 == second.wi6) && (first.tdc6 = second.tdc6); + bool lay7 = (first.wi7 == second.wi7) && (first.tdc7 = second.tdc7); + bool lay8 = (first.wi8 == second.wi8) && (first.tdc8 = second.tdc8); + + if (lay1 && lay2 && lay3 && lay4) { + if (lay5 || lay6 || lay7 || lay8) + return true; + else + return false; + } else if (lay5 && lay6 && lay7 && lay8) { + if (lay1 || lay2 || lay3 || lay4) + return true; + else + return false; + } else + return false; +} + +bool MuonPathAssociator::isNotAPrimo(metaPrimitive first, metaPrimitive second) { + int hitsSL1 = (first.wi1 != -1) + (first.wi2 != -1) + (first.wi3 != -1) + (first.wi4 != -1); + int hitsSL3 = (first.wi5 != -1) + (first.wi6 != -1) + (first.wi7 != -1) + (first.wi8 != -1); + + bool lay1 = (first.wi1 == second.wi1) && (first.tdc1 = second.tdc1) && (first.wi1 != -1); + bool lay2 = (first.wi2 == second.wi2) && (first.tdc2 = second.tdc2) && (first.wi2 != -1); + bool lay3 = (first.wi3 == second.wi3) && (first.tdc3 = second.tdc3) && (first.wi3 != -1); + bool lay4 = (first.wi4 == second.wi4) && (first.tdc4 = second.tdc4) && (first.wi4 != -1); + bool lay5 = (first.wi5 == second.wi5) && (first.tdc5 = second.tdc5) && (first.wi5 != -1); + bool lay6 = (first.wi6 == second.wi6) && (first.tdc6 = second.tdc6) && (first.wi6 != -1); + bool lay7 = (first.wi7 == second.wi7) && (first.tdc7 = second.tdc7) && (first.wi7 != -1); + bool lay8 = (first.wi8 == second.wi8) && (first.tdc8 = second.tdc8) && (first.wi8 != -1); + + return (((!lay1 && !lay2 && !lay3 && !lay4) || hitsSL1 < 3) && ((!lay5 && !lay6 && !lay7 && !lay8) || hitsSL3 < 3)); +} + +void MuonPathAssociator::printmPC(metaPrimitive mP) { + DTChamberId ChId(mP.rawId); + LogDebug("MuonPathAssociator") << 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 << " \n"; +} diff --git a/L1Trigger/DTTriggerPhase2/src/PseudoBayesGrouping.cc b/L1Trigger/DTTriggerPhase2/src/PseudoBayesGrouping.cc new file mode 100644 index 0000000000000..1d0974633d718 --- /dev/null +++ b/L1Trigger/DTTriggerPhase2/src/PseudoBayesGrouping.cc @@ -0,0 +1,471 @@ +#include + +#include "FWCore/Framework/interface/ConsumesCollector.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/MessageLogger/interface/MessageLogger.h" + +#include "TFile.h" + +#include "L1Trigger/DTTriggerPhase2/interface/PseudoBayesGrouping.h" + +using namespace edm; +using namespace std; +using namespace cmsdt; +using namespace dtbayesam; +// ============================================================================ +// Constructors and destructor +// ============================================================================ +PseudoBayesGrouping::PseudoBayesGrouping(const ParameterSet& pset, edm::ConsumesCollector& iC) + : MotherGrouping(pset, iC) { + // Obtention of parameters + debug_ = pset.getUntrackedParameter("debug"); + pattern_filename_ = pset.getUntrackedParameter("pattern_filename").fullPath(); + minNLayerHits_ = pset.getUntrackedParameter("minNLayerHits"); + minSingleSLHitsMax_ = pset.getUntrackedParameter("minSingleSLHitsMax"); + minSingleSLHitsMin_ = pset.getUntrackedParameter("minSingleSLHitsMin"); + allowedVariance_ = pset.getUntrackedParameter("allowedVariance"); + allowDuplicates_ = pset.getUntrackedParameter("allowDuplicates"); + allowUncorrelatedPatterns_ = pset.getUntrackedParameter("allowUncorrelatedPatterns"); + minUncorrelatedHits_ = pset.getUntrackedParameter("minUncorrelatedHits"); + saveOnPlace_ = pset.getUntrackedParameter("saveOnPlace"); + setLateralities_ = pset.getUntrackedParameter("setLateralities"); + if (debug_) + LogDebug("PseudoBayesGrouping") << "PseudoBayesGrouping:: constructor"; +} + +PseudoBayesGrouping::~PseudoBayesGrouping() { + if (debug_) + LogDebug("PseudoBayesGrouping") << "PseudoBayesGrouping:: destructor"; + for (std::vector::iterator pat_it = allPatterns_.begin(); pat_it != allPatterns_.end(); pat_it++) { + delete (*pat_it); + } +} + +// ============================================================================ +// Main methods (initialise, run, finish) +// ============================================================================ +void PseudoBayesGrouping::initialise(const edm::EventSetup& iEventSetup) { + if (debug_) + LogDebug("PseudoBayesGrouping") << "PseudoBayesGrouping::initialiase"; + if (debug_) + LogDebug("PseudoBayesGrouping") << "PseudoBayesGrouping::initialiase using patterns file " << pattern_filename_; + nPatterns_ = 0; + //Load patterns from pattern root file with expected hits information + TFile* f = TFile::Open(TString(pattern_filename_), "READ"); + std::vector>>* pattern_reader = + (std::vector>>*)f->Get("allPatterns"); + for (std::vector>>::iterator itPattern = (*pattern_reader).begin(); + itPattern != (*pattern_reader).end(); + ++itPattern) { + //Loops over all patterns in the loop and constructs the Pattern object for each one + LoadPattern(itPattern); + } + if (debug_) + LogDebug("PseudoBayesGrouping") << "PseudoBayesGrouping::initialiase Total number of loaded patterns: " + << nPatterns_; + f->Close(); + delete f; + + prelimMatches_ = std::make_unique(); + allMatches_ = std::make_unique(); + finalMatches_ = std::make_unique(); +} + +void PseudoBayesGrouping::LoadPattern(std::vector>>::iterator itPattern) { + if (debug_) + LogDebug("PseudoBayesGrouping") << "PseudoBayesGrouping::LoadPattern Loading patterns seeded by: " + << itPattern->at(0).at(0) << ", " << itPattern->at(0).at(1) << ", " + << itPattern->at(0).at(2) << ", "; + + DTPattern p; + // for (auto itHits = itPattern->begin(); itHits != itPattern->end(); ++itHits) { + bool is_seed = true; + for (const auto& itHits : *itPattern) { + //First entry is the seeding information + if (is_seed) { + p = DTPattern(itHits.at(0), itHits.at(1), itHits.at(2)); + is_seed = false; + } + //Other entries are the hits information + else { + if (itHits.begin() == itHits.end()) + continue; + //We need to correct the geometry from pattern generation to reconstruction as they use slightly displaced basis + else if (itHits.at(0) % 2 == 0) { + p.addHit(std::make_tuple(itHits.at(0), itHits.at(1), itHits.at(2))); + } else if (itHits.at(0) % 2 == 1) { + p.addHit(std::make_tuple(itHits.at(0), itHits.at(1) - 1, itHits.at(2))); + } + } + } + //Classified by seeding layers for optimized search later + //TODO::This can be vastly improved using std::bitset<8>, for example + if (p.sl1() == 0) { + if (p.sl2() == 7) + L0L7Patterns_.push_back(&p); + if (p.sl2() == 6) + L0L6Patterns_.push_back(&p); + if (p.sl2() == 5) + L0L5Patterns_.push_back(&p); + if (p.sl2() == 4) + L0L4Patterns_.push_back(&p); + if (p.sl2() == 3) + L0L3Patterns_.push_back(&p); + if (p.sl2() == 2) + L0L2Patterns_.push_back(&p); + if (p.sl2() == 1) + L0L1Patterns_.push_back(&p); + } + if (p.sl1() == 1) { + if (p.sl2() == 7) + L1L7Patterns_.push_back(&p); + if (p.sl2() == 6) + L1L6Patterns_.push_back(&p); + if (p.sl2() == 5) + L1L5Patterns_.push_back(&p); + if (p.sl2() == 4) + L1L4Patterns_.push_back(&p); + if (p.sl2() == 3) + L1L3Patterns_.push_back(&p); + if (p.sl2() == 2) + L1L2Patterns_.push_back(&p); + } + if (p.sl1() == 2) { + if (p.sl2() == 7) + L2L7Patterns_.push_back(&p); + if (p.sl2() == 6) + L2L6Patterns_.push_back(&p); + if (p.sl2() == 5) + L2L5Patterns_.push_back(&p); + if (p.sl2() == 4) + L2L4Patterns_.push_back(&p); + if (p.sl2() == 3) + L2L3Patterns_.push_back(&p); + } + if (p.sl1() == 3) { + if (p.sl2() == 7) + L3L7Patterns_.push_back(&p); + if (p.sl2() == 6) + L3L6Patterns_.push_back(&p); + if (p.sl2() == 5) + L3L5Patterns_.push_back(&p); + if (p.sl2() == 4) + L3L4Patterns_.push_back(&p); + } + + if (p.sl1() == 4) { + if (p.sl2() == 7) + L4L7Patterns_.push_back(&p); + if (p.sl2() == 6) + L4L6Patterns_.push_back(&p); + if (p.sl2() == 5) + L4L5Patterns_.push_back(&p); + } + if (p.sl1() == 5) { + if (p.sl2() == 7) + L5L7Patterns_.push_back(&p); + if (p.sl2() == 6) + L5L6Patterns_.push_back(&p); + } + if (p.sl1() == 6) { + if (p.sl2() == 7) + L6L7Patterns_.push_back(&p); + } + //Also creating a list of all patterns, needed later for deleting and avoid a memory leak + allPatterns_.push_back(&p); + nPatterns_++; +} + +void PseudoBayesGrouping::run(Event& iEvent, + const EventSetup& iEventSetup, + const DTDigiCollection& digis, + MuonPathPtrs& mpaths) { + //Takes dt digis collection and does the grouping for correlated hits, it is saved in a vector of up to 8 (or 4) correlated hits + if (debug_) + LogDebug("PseudoBayesGrouping") << "PseudoBayesGrouping::run"; + //Do initial cleaning + CleanDigisByLayer(); + //Sort digis by layer + FillDigisByLayer(&digis); + //Sarch for patterns + RecognisePatternsByLayerPairs(); + //Now sort patterns by qualities + std::sort(prelimMatches_->begin(), prelimMatches_->end(), CandPointGreat()); + if (debug_ && !prelimMatches_->empty()) { + LogDebug("PseudoBayesGrouping") << "PseudoBayesGrouping::run Pattern qualities before cleaning: "; + for (const auto& cand_it : *prelimMatches_) { + LogDebug("PseudoBayesGrouping") << cand_it->nLayerhits() << ", " << cand_it->nisGood() << ", " << cand_it->nhits() + << ", " << cand_it->quality() << ", " << cand_it->candId(); + } + } + //And ghostbust patterns to retain higher quality ones + ReCleanPatternsAndDigis(); + if (debug_) + LogDebug("PseudoBayesGrouping") << "PseudoBayesGrouping::run Number of found patterns: " << finalMatches_->size(); + + //Last organize candidates information into muonpaths to finalize the grouping + FillMuonPaths(mpaths); + if (debug_) + LogDebug("PseudoBayesGrouping") << "PseudoBayesGrouping::run ended run"; +} + +void PseudoBayesGrouping::FillMuonPaths(MuonPathPtrs& mpaths) { + //Loop over all selected candidates + for (auto itCand = finalMatches_->begin(); itCand != finalMatches_->end(); itCand++) { + if (debug_) + LogDebug("PseudoBayesGrouping") << "PseudoBayesGrouping::run Create pointers "; + DTPrimitivePtrs ptrPrimitive; + for (int i = 0; i < 8; i++) + ptrPrimitive.push_back(std::make_shared()); + + qualitybits qualityDTP; + int intHit = 0; + //And for each candidate loop over all grouped hits + for (auto& itDTP : (*itCand)->candHits()) { + if (debug_) + LogDebug("PseudoBayesGrouping") << "PseudoBayesGrouping::run loop over dt hits to fill pointer"; + + int layerHit = (*itDTP).layerId(); + //Back to the usual basis for SL + if (layerHit >= 4) { + (*itDTP).setLayerId(layerHit - 4); + } + qualitybits ref8Hit(std::pow(2, layerHit)); + //Get the predicted laterality + if (setLateralities_) { + int predLat = (*itCand)->pattern()->latHitIn(layerHit, (*itDTP).channelId(), allowedVariance_); + if (predLat == -10 || predLat == 0) { + (*itDTP).setLaterality(NONE); + } else if (predLat == -1) { + (*itDTP).setLaterality(LEFT); + } else if (predLat == +1) { + (*itDTP).setLaterality(RIGHT); + } + } + //Only fill the DT primitives pointer if there is not one hit already in the layer + if (qualityDTP != (qualityDTP | ref8Hit)) { + if (debug_) + LogDebug("PseudoBayesGrouping") << "PseudoBayesGrouping::run Adding hit to muon path"; + qualityDTP = (qualityDTP | ref8Hit); + if (saveOnPlace_) { + //This will save the primitive in a place of the vector equal to its L position + ptrPrimitive.at(layerHit) = std::make_shared((*itDTP)); + } + if (!saveOnPlace_) { + //This will save the primitive in order + intHit++; + ptrPrimitive.at(intHit) = std::make_shared((*itDTP)); + } + } + } + //Now, if there are empty spaces in the vector fill them full of daylight + int ipow = 1; + for (int i = 0; i <= 7; i++) { + ipow *= 2; + if (qualityDTP != (qualityDTP | qualitybits(1 << i))) { + ptrPrimitive.at(i) = std::make_shared(); + } + } + + mpaths.emplace_back( + std::make_shared(ptrPrimitive, (short)(*itCand)->nLayerUp(), (short)(*itCand)->nLayerDown())); + } +} + +void PseudoBayesGrouping::RecognisePatternsByLayerPairs() { + //Separated from main run function for clarity. Do all pattern recognition steps + pidx_ = 0; + //Compare L0-L7 + RecognisePatterns(digisinL0_, digisinL7_, L0L7Patterns_); + //Compare L0-L6 and L1-L7 + RecognisePatterns(digisinL0_, digisinL6_, L0L6Patterns_); + RecognisePatterns(digisinL1_, digisinL7_, L1L7Patterns_); + //Compare L0-L5, L1-L6, L2-L7 + RecognisePatterns(digisinL0_, digisinL5_, L0L5Patterns_); + RecognisePatterns(digisinL1_, digisinL6_, L1L6Patterns_); + RecognisePatterns(digisinL2_, digisinL7_, L2L7Patterns_); + //L0-L4, L1-L5, L2-L6, L3-L7 + RecognisePatterns(digisinL0_, digisinL4_, L0L4Patterns_); + RecognisePatterns(digisinL1_, digisinL5_, L1L5Patterns_); + RecognisePatterns(digisinL2_, digisinL6_, L2L6Patterns_); + RecognisePatterns(digisinL3_, digisinL7_, L3L7Patterns_); + //L1-L4, L2-L5, L3-L6 + RecognisePatterns(digisinL1_, digisinL4_, L1L4Patterns_); + RecognisePatterns(digisinL2_, digisinL5_, L2L5Patterns_); + RecognisePatterns(digisinL3_, digisinL6_, L3L6Patterns_); + //L2-L4, L3-L5 + RecognisePatterns(digisinL2_, digisinL4_, L2L4Patterns_); + RecognisePatterns(digisinL3_, digisinL5_, L3L5Patterns_); + //L3-L4 + RecognisePatterns(digisinL3_, digisinL4_, L3L4Patterns_); + //Uncorrelated SL1 + RecognisePatterns(digisinL0_, digisinL1_, L0L1Patterns_); + RecognisePatterns(digisinL0_, digisinL2_, L0L2Patterns_); + RecognisePatterns(digisinL0_, digisinL3_, L0L3Patterns_); + RecognisePatterns(digisinL1_, digisinL2_, L1L2Patterns_); + RecognisePatterns(digisinL1_, digisinL3_, L1L3Patterns_); + RecognisePatterns(digisinL2_, digisinL3_, L2L3Patterns_); + //Uncorrelated SL3 + RecognisePatterns(digisinL4_, digisinL5_, L4L5Patterns_); + RecognisePatterns(digisinL4_, digisinL6_, L4L6Patterns_); + RecognisePatterns(digisinL4_, digisinL7_, L4L7Patterns_); + RecognisePatterns(digisinL5_, digisinL6_, L5L6Patterns_); + RecognisePatterns(digisinL5_, digisinL7_, L5L7Patterns_); + RecognisePatterns(digisinL6_, digisinL7_, L6L7Patterns_); +} + +void PseudoBayesGrouping::RecognisePatterns(std::vector digisinLDown, + std::vector digisinLUp, + std::vector patterns) { + //Loop over all hits and search for matching patterns (there will be four + // amongst ~60, accounting for possible lateralities) + for (auto dtPD_it = digisinLDown.begin(); dtPD_it != digisinLDown.end(); dtPD_it++) { + int LDown = dtPD_it->layerId(); + int wireDown = dtPD_it->channelId(); + for (auto dtPU_it = digisinLUp.begin(); dtPU_it != digisinLUp.end(); dtPU_it++) { + int LUp = dtPU_it->layerId(); + int wireUp = dtPU_it->channelId(); + int diff = wireUp - wireDown; + for (auto pat_it = patterns.begin(); pat_it != patterns.end(); pat_it++) { + //For each pair of hits in the layers search for the seeded patterns + if ((*pat_it)->sl1() != (LDown) || (*pat_it)->sl2() != (LUp) || (*pat_it)->diff() != diff) + continue; + //If we are here a pattern was found and we can start comparing + (*pat_it)->setHitDown(wireDown); + auto cand = std::make_shared(*pat_it); + for (auto dtTest_it = alldigis_.begin(); dtTest_it != alldigis_.end(); dtTest_it++) { + //Find hits matching to the pattern + if (((*pat_it)->latHitIn(dtTest_it->layerId(), dtTest_it->channelId(), allowedVariance_)) != -999) { + if (((*pat_it)->latHitIn(dtTest_it->layerId(), dtTest_it->channelId(), allowedVariance_)) == -10) + cand->addHit((*dtTest_it), dtTest_it->layerId(), false); + else + cand->addHit((*dtTest_it), dtTest_it->layerId(), true); + } + } + if ((cand->nhits() >= minNLayerHits_ && + (cand->nLayerUp() >= minSingleSLHitsMax_ || cand->nLayerDown() >= minSingleSLHitsMax_) && + (cand->nLayerUp() >= minSingleSLHitsMin_ && cand->nLayerDown() >= minSingleSLHitsMin_)) || + (allowUncorrelatedPatterns_ && ((cand->nLayerUp() >= minUncorrelatedHits_ && cand->nLayerDown() == 0) || + (cand->nLayerDown() >= minUncorrelatedHits_ && cand->nLayerUp() == 0)))) { + if (debug_) { + LogDebug("PseudoBayesGrouping") << "PseudoBayesGrouping::RecognisePatterns Pattern found for pair in " + << LDown << " ," << wireDown << " ," << LUp << " ," << wireUp; + LogDebug("PseudoBayesGrouping") + << "Candidate has " << cand->nhits() << " hits with quality " << cand->quality(); + LogDebug("PseudoBayesGrouping") << *(*pat_it); + } + //We currently save everything at this level, might want to be more restrictive + pidx_++; + cand->setCandId(pidx_); + prelimMatches_->push_back(std::move(cand)); + allMatches_->push_back(std::move(cand)); + } + } + } + } +} + +void PseudoBayesGrouping::FillDigisByLayer(const DTDigiCollection* digis) { + //First we need to have separated lists of digis by layer + if (debug_) + LogDebug("PseudoBayesGrouping") << "PseudoBayesGrouping::FillDigisByLayer Classifying digis by layer"; + // for (auto dtDigi_It = digis->begin(); dtDigi_It != digis->end(); dtDigi_It++) { + for (const auto& dtDigi_It : *digis) { + const DTLayerId dtLId = dtDigi_It.first; + //Skip digis in SL theta which we are not interested on for the grouping + for (auto digiIt = (dtDigi_It.second).first; digiIt != (dtDigi_It.second).second; digiIt++) { + //Need to change notation slightly here + if (dtLId.superlayer() == 2) + continue; + int layer = dtLId.layer() - 1; + if (dtLId.superlayer() == 3) + layer += 4; + //Use the same format as for InitialGrouping to avoid tons of replicating classes, we will have some not used variables + DTPrimitive dtpAux = DTPrimitive(); + dtpAux.setTDCTimeStamp(digiIt->time()); + dtpAux.setChannelId(digiIt->wire() - 1); + dtpAux.setLayerId(layer); + dtpAux.setSuperLayerId(dtLId.superlayer()); + dtpAux.setCameraId(dtLId.rawId()); + if (debug_) + LogDebug("PseudoBayesGrouping") << "Hit in L " << layer << " SL " << dtLId.superlayer() << " WIRE " + << digiIt->wire() - 1; + if (layer == 0) + digisinL0_.push_back(dtpAux); + else if (layer == 1) + digisinL1_.push_back(dtpAux); + else if (layer == 2) + digisinL2_.push_back(dtpAux); + else if (layer == 3) + digisinL3_.push_back(dtpAux); + else if (layer == 4) + digisinL4_.push_back(dtpAux); + else if (layer == 5) + digisinL5_.push_back(dtpAux); + else if (layer == 6) + digisinL6_.push_back(dtpAux); + else if (layer == 7) + digisinL7_.push_back(dtpAux); + alldigis_.push_back(dtpAux); + } + } +} + +void PseudoBayesGrouping::ReCleanPatternsAndDigis() { + //GhostbustPatterns that share hits and are of lower quality + if (prelimMatches_->empty()) { + return; + }; + while ((prelimMatches_->at(0)->nLayerhits() >= minNLayerHits_ && + (prelimMatches_->at(0)->nLayerUp() >= minSingleSLHitsMax_ || + prelimMatches_->at(0)->nLayerDown() >= minSingleSLHitsMax_) && + (prelimMatches_->at(0)->nLayerUp() >= minSingleSLHitsMin_ && + prelimMatches_->at(0)->nLayerDown() >= minSingleSLHitsMin_)) || + (allowUncorrelatedPatterns_ && + ((prelimMatches_->at(0)->nLayerUp() >= minUncorrelatedHits_ && prelimMatches_->at(0)->nLayerDown() == 0) || + (prelimMatches_->at(0)->nLayerDown() >= minUncorrelatedHits_ && prelimMatches_->at(0)->nLayerUp() == 0)))) { + finalMatches_->push_back(prelimMatches_->at(0)); + auto itSel = finalMatches_->end() - 1; + prelimMatches_->erase(prelimMatches_->begin()); + if (prelimMatches_->empty()) { + return; + }; + for (auto cand_it = prelimMatches_->begin(); cand_it != prelimMatches_->end(); cand_it++) { + if (*(*cand_it) == *(*itSel) && allowDuplicates_) + continue; + for (const auto& dt_it : (*itSel)->candHits()) { //.begin(); dt_it != (*itSel)->candHits().end(); dt_it++) { + (*cand_it)->removeHit((*dt_it)); + } + } + + std::sort(prelimMatches_->begin(), prelimMatches_->end(), CandPointGreat()); + if (debug_) { + LogDebug("PseudoBayesGrouping") << "Pattern qualities: "; + for (const auto& cand_it : *prelimMatches_) { + LogDebug("PseudoBayesGrouping") << cand_it->nLayerhits() << ", " << cand_it->nisGood() << ", " + << cand_it->nhits() << ", " << cand_it->quality() << ", " << cand_it->candId() + << "\n"; + } + } + } +} + +void PseudoBayesGrouping::CleanDigisByLayer() { + digisinL0_.clear(); + digisinL1_.clear(); + digisinL2_.clear(); + digisinL3_.clear(); + digisinL4_.clear(); + digisinL5_.clear(); + digisinL6_.clear(); + digisinL7_.clear(); + alldigis_.clear(); + allMatches_->clear(); + prelimMatches_->clear(); + finalMatches_->clear(); +} + +void PseudoBayesGrouping::finish() { + if (debug_) + LogDebug("PseudoBayesGrouping") << "PseudoBayesGrouping: finish"; +}; diff --git a/L1Trigger/DTTriggerPhase2/src/RPCIntegrator.cc b/L1Trigger/DTTriggerPhase2/src/RPCIntegrator.cc new file mode 100644 index 0000000000000..be8ea54910111 --- /dev/null +++ b/L1Trigger/DTTriggerPhase2/src/RPCIntegrator.cc @@ -0,0 +1,257 @@ +#include "FWCore/Utilities/interface/ESGetToken.h" +#include "FWCore/Utilities/interface/ESInputTag.h" +#include "FWCore/MessageLogger/interface/MessageLogger.h" + +#include "L1Trigger/DTTriggerPhase2/interface/RPCIntegrator.h" + +#include + +#include + +using namespace cmsdt; + +RPCIntegrator::RPCIntegrator(const edm::ParameterSet& pset, edm::ConsumesCollector& iC) { + m_debug_ = pset.getUntrackedParameter("debug"); + if (m_debug_) + LogDebug("RPCIntegrator") << "RPCIntegrator constructor"; + m_max_quality_to_overwrite_t0_ = pset.getUntrackedParameter("max_quality_to_overwrite_t0"); + m_bx_window_ = pset.getUntrackedParameter("bx_window"); + m_phi_window_ = pset.getUntrackedParameter("phi_window"); + m_storeAllRPCHits_ = pset.getUntrackedParameter("storeAllRPCHits"); + + rpcGeomH_ = iC.esConsumes(); + dtGeomH_ = iC.esConsumes(); +} + +RPCIntegrator::~RPCIntegrator() { + if (m_debug_) + LogDebug("RPCIntegrator") << "RPCIntegrator destructor"; +} + +void RPCIntegrator::initialise(const edm::EventSetup& iEventSetup, double shift_back_fromDT) { + if (m_debug_) + LogDebug("RPCIntegrator") << "RPCIntegrator initialisation"; + + if (m_debug_) + LogDebug("RPCIntegrator") << "Getting RPC geometry"; + + const MuonGeometryRecord& geom = iEventSetup.get(); + dtGeo_ = &geom.get(dtGeomH_); + rpcGeo_ = &geom.get(rpcGeomH_); + shift_back_ = shift_back_fromDT; +} + +void RPCIntegrator::finish() {} + +void RPCIntegrator::prepareMetaPrimitives(edm::Handle rpcRecHits) { + RPCMetaprimitives_.clear(); + rpcRecHits_translated_.clear(); + for (const auto& rpcIt : *rpcRecHits) { + RPCDetId rpcDetId = (RPCDetId)(rpcIt).rpcId(); + GlobalPoint global_position = RPCGlobalPosition(rpcDetId, rpcIt); + int rpc_region = rpcDetId.region(); + if (rpc_region != 0) + continue; // Region = 0 Barrel + + // set everyone to rpc single hit (3) not matched to DT flag for now + // change last two elements if dt bx centered at zero again + RPCMetaprimitives_.emplace_back( + rpcDetId, &rpcIt, global_position, RPC_HIT, rpcIt.BunchX() + BX_SHIFT, rpcIt.time() + BX_SHIFT * LHC_CLK_FREQ); + } +} +void RPCIntegrator::matchWithDTAndUseRPCTime(std::vector& dt_metaprimitives) { + for (auto dt_metaprimitive = dt_metaprimitives.begin(); dt_metaprimitive != dt_metaprimitives.end(); + dt_metaprimitive++) { + RPCMetaprimitive* bestMatch_rpcRecHit = matchDTwithRPC(&*dt_metaprimitive); + if (bestMatch_rpcRecHit) { + (*dt_metaprimitive).rpcFlag = RPC_CONFIRM; + if ((*dt_metaprimitive).quality < m_max_quality_to_overwrite_t0_) { + (*dt_metaprimitive).t0 = bestMatch_rpcRecHit->rpc_t0 + 25 * shift_back_; + (*dt_metaprimitive).rpcFlag = RPC_TIME; + } + } + } +} + +void RPCIntegrator::makeRPCOnlySegments() { + std::vector rpc_only_segments; + for (auto& rpc_mp_it_layer1 : RPCMetaprimitives_) { + RPCDetId rpc_id_l1 = rpc_mp_it_layer1.rpc_id; + const RPCRecHit* rpc_cluster_l1 = rpc_mp_it_layer1.rpc_cluster; + GlobalPoint rpc_gp_l1 = rpc_mp_it_layer1.global_position; + if (rpc_id_l1.station() > 2 || rpc_id_l1.layer() != 1 || + (rpc_mp_it_layer1.rpcFlag == RPC_ASSOCIATE && !m_storeAllRPCHits_)) + continue; + // only one RPC layer in station three and four && + // avoid duplicating pairs && + // avoid building RPC only segment if DT segment was already there + int min_dPhi = std::numeric_limits::max(); + RPCMetaprimitive* bestMatch_rpc_mp_layer2 = nullptr; + for (auto& rpc_mp_it_layer2 : RPCMetaprimitives_) { + RPCDetId rpc_id_l2 = rpc_mp_it_layer2.rpc_id; + const RPCRecHit* rpc_cluster_l2 = rpc_mp_it_layer2.rpc_cluster; + GlobalPoint rpc_gp_l2 = rpc_mp_it_layer2.global_position; + if (rpc_id_l2.station() == rpc_id_l1.station() && rpc_id_l2.ring() == rpc_id_l1.ring() && + rpc_id_l2.layer() != rpc_id_l1.layer() // ensure to have layer 1 --> layer 2 + && rpc_id_l2.sector() == rpc_id_l1.sector() && rpc_cluster_l2->BunchX() == rpc_cluster_l1->BunchX() && + (rpc_mp_it_layer2.rpcFlag != RPC_ASSOCIATE || m_storeAllRPCHits_)) { + // avoid building RPC only segment with a hit already matched to DT, + // except if one aske to store all RPC info + float tmp_dPhi = rpc_gp_l1.phi() - rpc_gp_l2.phi(); + if (std::abs(tmp_dPhi) < std::abs(min_dPhi)) { + min_dPhi = tmp_dPhi; + bestMatch_rpc_mp_layer2 = &rpc_mp_it_layer2; + } + } + } + if (bestMatch_rpc_mp_layer2) { + rpc_mp_it_layer1.rpcFlag = 6; + // need a new flag (will be removed later) to differentiate + // between "has been matched to DT" and "Has been used in an RPC only segment" + bestMatch_rpc_mp_layer2->rpcFlag = 6; + double phiB = phiBending(&rpc_mp_it_layer1, &*bestMatch_rpc_mp_layer2); + // Arbitrarily choose the phi from layer 1 + double global_phi = rpc_mp_it_layer1.global_position.phi(); + double t0 = (rpc_mp_it_layer1.rpc_t0 + bestMatch_rpc_mp_layer2->rpc_t0) / 2; + // RPC only segment have rpcFlag==2 + L1Phase2MuDTPhDigi rpc_only_segment = + createL1Phase2MuDTPhDigi(rpc_id_l1, rpc_mp_it_layer1.rpc_bx, t0, global_phi, phiB, 2); + rpc_only_segments.push_back(rpc_only_segment); + } + } + rpcRecHits_translated_.insert(rpcRecHits_translated_.end(), rpc_only_segments.begin(), rpc_only_segments.end()); +} + +void RPCIntegrator::storeRPCSingleHits() { + for (auto rpc_mp_it = RPCMetaprimitives_.begin(); rpc_mp_it != RPCMetaprimitives_.end(); rpc_mp_it++) { + RPCDetId rpcDetId = rpc_mp_it->rpc_id; + if (rpc_mp_it->rpcFlag == 6) + rpc_mp_it->rpcFlag = RPC_ASSOCIATE; + L1Phase2MuDTPhDigi rpc_out = createL1Phase2MuDTPhDigi( + rpcDetId, rpc_mp_it->rpc_bx, rpc_mp_it->rpc_t0, rpc_mp_it->global_position.phi(), -10000, rpc_mp_it->rpcFlag); + rpcRecHits_translated_.push_back(rpc_out); + } +} + +void RPCIntegrator::removeRPCHitsUsed() { + if (m_debug_) + LogDebug("RPCIntegrator") << "RPCIntegrator removeRPCHitsUsed method"; + if (!m_storeAllRPCHits_) { + // Remove RPC hit attached to a DT or RPC segment if required by user + // (avoid having two TP's corresponding to the same physical hit) + auto rpcRecHit_translated_ = rpcRecHits_translated_.begin(); + while (rpcRecHit_translated_ != rpcRecHits_translated_.end()) { + if (rpcRecHit_translated_->rpcFlag() == RPC_ASSOCIATE || rpcRecHit_translated_->rpcFlag() == 6) { + rpcRecHit_translated_ = rpcRecHits_translated_.erase(rpcRecHit_translated_); + } else { + ++rpcRecHit_translated_; + } + } + } +} + +RPCMetaprimitive* RPCIntegrator::matchDTwithRPC(metaPrimitive* dt_metaprimitive) { + // metaprimitive dtChId is still in convention with [1 - 12] + // because at this stage the BX of metaprimitive is not yet computed... + // will also have to subtract 20*25 ns because of the recent change + int dt_bx = (int)round(dt_metaprimitive->t0 / 25.) - shift_back_; + DTChamberId dt_chId = DTChamberId(dt_metaprimitive->rawId); + int dt_sector = dt_chId.sector(); + if (dt_sector == 13) + dt_sector = 4; + if (dt_sector == 14) + dt_sector = 10; + RPCMetaprimitive* bestMatch_rpcRecHit = nullptr; + float min_dPhi = std::numeric_limits::max(); + for (auto rpc_mp_it = RPCMetaprimitives_.begin(); rpc_mp_it != RPCMetaprimitives_.end(); rpc_mp_it++) { + RPCDetId rpc_det_id = rpc_mp_it->rpc_id; + if (rpc_det_id.ring() == dt_chId.wheel() // ring() in barrel RPC corresponds to the wheel + && rpc_det_id.station() == dt_chId.station() && rpc_det_id.sector() == dt_sector && + std::abs(rpc_mp_it->rpc_bx - dt_bx) <= m_bx_window_) { + // Select the RPC hit closest in phi to the DT meta primitive + + // just a trick to apply the phi window cut on what could be accessed to fine tune it + int delta_phi = + (int)round((phi_DT_MP_conv(rpc_mp_it->global_position.phi(), rpc_det_id.sector()) - dt_metaprimitive->phi) * + m_dt_phiB_granularity_); + if (std::abs(delta_phi) < min_dPhi && std::abs(delta_phi) < m_phi_window_) { + min_dPhi = std::abs(delta_phi); + bestMatch_rpcRecHit = &*rpc_mp_it; + } + } + } + if (bestMatch_rpcRecHit) { + bestMatch_rpcRecHit->rpcFlag = RPC_ASSOCIATE; + } + return bestMatch_rpcRecHit; +} + +L1Phase2MuDTPhDigi RPCIntegrator::createL1Phase2MuDTPhDigi( + RPCDetId rpcDetId, int rpc_bx, double rpc_time, double rpc_global_phi, double phiB, int rpc_flag) { + if (m_debug_) + LogDebug("RPCIntegrator") << "Creating DT TP out of RPC recHits"; + int rpc_wheel = rpcDetId.ring(); // In barrel, wheel is accessed via ring() method ([-2,+2]) + int trigger_sector = rpcDetId.sector() - 1; // DT Trigger sector:[0,11] while RPC sector:[1,12] + int rpc_station = rpcDetId.station(); + int rpc_layer = rpcDetId.layer(); + int rpc_trigger_phi = phiInDTTPFormat(rpc_global_phi, rpcDetId.sector()); + int rpc_trigger_phiB = (phiB == -10000) ? phiB : (int)round(phiB * m_dt_phiB_granularity_); + int rpc_quality = -1; // dummy for rpc + int rpc_index = 0; // dummy for rpc + return L1Phase2MuDTPhDigi(rpc_bx, + rpc_wheel, + trigger_sector, + rpc_station, + rpc_layer, //this would be the layer in the new dataformat + rpc_trigger_phi, + rpc_trigger_phiB, + rpc_quality, + rpc_index, + rpc_time, + -1, // no chi2 for RPC + rpc_flag); +} + +double RPCIntegrator::phiBending(RPCMetaprimitive* rpc_hit_1, RPCMetaprimitive* rpc_hit_2) { + DTChamberId DT_chamber(rpc_hit_1->rpc_id.ring(), rpc_hit_1->rpc_id.station(), rpc_hit_1->rpc_id.sector()); + LocalPoint lp_rpc_hit_1_dtconv = dtGeo_->chamber(DT_chamber)->toLocal(rpc_hit_1->global_position); + LocalPoint lp_rpc_hit_2_dtconv = dtGeo_->chamber(DT_chamber)->toLocal(rpc_hit_2->global_position); + double slope = (lp_rpc_hit_1_dtconv.x() - lp_rpc_hit_2_dtconv.x()) / distance_between_two_rpc_layers_; + double average_x = (lp_rpc_hit_1_dtconv.x() + lp_rpc_hit_2_dtconv.x()) / 2; + GlobalPoint seg_middle_global = + dtGeo_->chamber(DT_chamber)->toGlobal(LocalPoint(average_x, 0., 0.)); // for station 1 and 2, z = 0 + double seg_phi = phi_DT_MP_conv(seg_middle_global.phi(), rpc_hit_1->rpc_id.sector()); + double psi = atan(slope); + double phiB = hasPosRF_rpc(rpc_hit_1->rpc_id.ring(), rpc_hit_1->rpc_id.sector()) ? psi - seg_phi : -psi - seg_phi; + return phiB; +} + +int RPCIntegrator::phiInDTTPFormat(double rpc_global_phi, int rpcSector) { + double rpc_localDT_phi; + rpc_localDT_phi = phi_DT_MP_conv(rpc_global_phi, rpcSector) * m_dt_phi_granularity_; + return (int)round(rpc_localDT_phi); +} + +double RPCIntegrator::phi_DT_MP_conv(double rpc_global_phi, int rpcSector) { + // Adaptation of https://github.com/cms-sw/cmssw/blob/master/L1Trigger/L1TTwinMux/src/RPCtoDTTranslator.cc#L349 + + if (rpcSector == 1) + return rpc_global_phi; + else { + float conversion = 1 / 6.; + if (rpc_global_phi >= 0) + return rpc_global_phi - (rpcSector - 1) * M_PI * conversion; + else + return rpc_global_phi + (13 - rpcSector) * M_PI * conversion; + } +} + +GlobalPoint RPCIntegrator::RPCGlobalPosition(RPCDetId rpcId, const RPCRecHit& rpcIt) const { + RPCDetId rpcid = RPCDetId(rpcId); + const LocalPoint& rpc_lp = rpcIt.localPosition(); + const GlobalPoint& rpc_gp = rpcGeo_->idToDet(rpcid)->surface().toGlobal(rpc_lp); + + return rpc_gp; +} + +bool RPCIntegrator::hasPosRF_rpc(int wh, int sec) const { return (wh > 0 || (wh == 0 && sec % 4 > 1)); } diff --git a/L1Trigger/DTTriggerPhase2/test/primitivesPhase2Prod_over_dTDigis_and_4Dsegments_cfg.py b/L1Trigger/DTTriggerPhase2/test/primitivesPhase2Prod_over_dTDigis_and_4Dsegments_cfg.py new file mode 100644 index 0000000000000..42407da17b768 --- /dev/null +++ b/L1Trigger/DTTriggerPhase2/test/primitivesPhase2Prod_over_dTDigis_and_4Dsegments_cfg.py @@ -0,0 +1,49 @@ +import FWCore.ParameterSet.Config as cms + +process = cms.Process("L1DTTrigPhase2Prod") + +process.load("Geometry.CMSCommonData.cmsIdealGeometryXML_cff") +process.load("Geometry.DTGeometry.dtGeometry_cfi") +process.DTGeometryESModule.applyAlignment = False + +process.load("L1Trigger.DTTriggerPhase2.dtTriggerPhase2PrimitiveDigis_cfi") +process.load("Configuration.StandardSequences.FrontierConditions_GlobalTag_cff") +process.load("Configuration.StandardSequences.MagneticField_AutoFromDBCurrent_cff") +#process.GlobalTag.globaltag = "90X_dataRun2_Express_v2" +process.GlobalTag.globaltag = "80X_dataRun2_2016SeptRepro_v7" + +#Calibrate Digis +process.load("L1Trigger.DTTriggerPhase2.CalibratedDigis_cfi") +#process.CalibratedDigis.flat_calib = 325 #turn to 0 to use the DB , 325 for JM and Jorge benchmark + +#DTTriggerPhase2 +process.load("L1Trigger.DTTriggerPhase2.dtTriggerPhase2PrimitiveDigis_cfi") +#process.dtTriggerPhase2PrimitiveDigis.trigger_with_sl = 3 #4 means SL 1 and 3 +#for the moment the part working in phase2 format is the slice test +#process.dtTriggerPhase2PrimitiveDigis.p2_df = 0 //0 is phase1, 1 is slice test, 2 is phase2(carlo-federica) + +process.dtTriggerPhase2PrimitiveDigis.scenario = 1 #0 is mc, 1 is data, 2 is slice test + + +process.source = cms.Source("PoolSource",fileNames = cms.untracked.vstring( + #'file:/eos/user/c/carrillo/digis_segments_Run2016BSingleMuonRAW-RECO.root' + 'file:/tmp/carrillo/digis_segments_Run2016BSingleMuonRAW-RECO.root' + ) + ) +process.maxEvents = cms.untracked.PSet( + input = cms.untracked.int32(-1) +) + +process.out = cms.OutputModule("PoolOutputModule", + outputCommands = cms.untracked.vstring('keep *'), + fileName = cms.untracked.string('/tmp/carrillo/DTTriggerPhase2Primitives.root') +) + +process.p = cms.Path(process.CalibratedDigis*process.dtTriggerPhase2PrimitiveDigis) +process.this_is_the_end = cms.EndPath(process.out) + + + + + + diff --git a/L1Trigger/DTTriggerPhase2/test/primitivesPhase2Prod_over_dTDigis_and_4Dsegments_cfg_withRPC.py b/L1Trigger/DTTriggerPhase2/test/primitivesPhase2Prod_over_dTDigis_and_4Dsegments_cfg_withRPC.py new file mode 100644 index 0000000000000..312f6a1137152 --- /dev/null +++ b/L1Trigger/DTTriggerPhase2/test/primitivesPhase2Prod_over_dTDigis_and_4Dsegments_cfg_withRPC.py @@ -0,0 +1,62 @@ +import FWCore.ParameterSet.Config as cms + +process = cms.Process("L1DTTrigPhase2Prod") + +process.load("Geometry.CMSCommonData.cmsIdealGeometryXML_cff") +process.load("Geometry.DTGeometry.dtGeometry_cfi") +process.DTGeometryESModule.applyAlignment = False + +process.load("L1Trigger.DTTriggerPhase2.dtTriggerPhase2PrimitiveDigis_cfi") +process.load("Configuration.StandardSequences.FrontierConditions_GlobalTag_cff") +process.load("Configuration.StandardSequences.MagneticField_AutoFromDBCurrent_cff") +process.GlobalTag.globaltag = "106X_upgrade2018_realistic_v4" +#from Configuration.AlCa.GlobalTag import GlobalTag +#process.GlobalTag = GlobalTag(process.GlobalTag, 'auto:phase2_realistic', '') + +#Calibrate Digis +process.load("L1Trigger.DTTriggerPhase2.CalibratedDigis_cfi") +process.CalibratedDigis.dtDigiTag = "simMuonDTDigis" +process.CalibratedDigis.scenario = 0 # 0 for mc, 1 for data, 2 for slice test +#process.CalibratedDigis.flat_calib = 325 #turn to 0 to use the DB , 325 for JM and Jorge benchmark + +#DTTriggerPhase2 +process.load("L1Trigger.DTTriggerPhase2.dtTriggerPhase2PrimitiveDigis_cfi") +#process.dtTriggerPhase2PrimitiveDigis.trigger_with_sl = 3 #4 means SL 1 and 3 +#for the moment the part working in phase2 format is the slice test +#process.dtTriggerPhase2PrimitiveDigis.p2_df = 0 //0 is phase1, 1 is slice test, 2 is phase2(carlo-federica) +#process.dtTriggerPhase2PrimitiveDigis.filter_primos = True +#for debugging +process.dtTriggerPhase2PrimitiveDigis.min_phinhits_match_segment = 4 +#process.dtTriggerPhase2PrimitiveDigis.debug = True + +#Produce RPC clusters from RPCDigi +process.load("RecoLocalMuon.RPCRecHit.rpcRecHits_cfi") +process.rpcRecHits.rpcDigiLabel = cms.InputTag('simMuonRPCDigis') +# Use RPC +process.load('Configuration.Geometry.GeometryExtended2023D38Reco_cff') +process.load('Configuration.Geometry.GeometryExtended2023D38_cff') +process.dtTriggerPhase2PrimitiveDigis.useRPC = True +process.dtTriggerPhase2PrimitiveDigis.scenario = 0 # 0 for mc, 1 for data, 2 for slice test +## Parameters that could be optimized (show here the default values) +#process.dtTriggerPhase2PrimitiveDigis.bx_window = 1 # +#process.dtTriggerPhase2PrimitiveDigis.max_quality_to_overwrite_t0 = 9 # strict inequality +#process.dtTriggerPhase2PrimitiveDigis.phi_window = 50 +#process.dtTriggerPhase2PrimitiveDigis.storeAllRPCHits = False + +process.source = cms.Source("PoolSource",fileNames = cms.untracked.vstring( + 'file:/eos/cms/store/group/dpg_dt/comm_dt/TriggerSimulation/SamplesReco/SingleMu_FlatPt-2to100/Version_10_5_0/SimRECO_1.root' + #'file:/eos/cms/store/group/dpg_rpc/comm_rpc/UpgradePhaseII/RPC_PLUS_DT/SingleMu_FlatPt-2to100_10_5_0_MaryCruz_WithRPCRecHits/SimRECO_1.root' + ) + ) +process.maxEvents = cms.untracked.PSet( + input = cms.untracked.int32(100) +) + +process.out = cms.OutputModule("PoolOutputModule", + outputCommands = cms.untracked.vstring('keep *'), + fileName = cms.untracked.string('DTTriggerPhase2Primitives100_withRPC.root') +) + +process.p = cms.Path(process.rpcRecHits*process.CalibratedDigis*process.dtTriggerPhase2PrimitiveDigis) +process.this_is_the_end = cms.EndPath(process.out) + diff --git a/L1Trigger/DTTriggerPhase2/test/primitivesPhase2Prod_over_hlt_parallel_cfg.py b/L1Trigger/DTTriggerPhase2/test/primitivesPhase2Prod_over_hlt_parallel_cfg.py new file mode 100644 index 0000000000000..dfba5f2a9cffc --- /dev/null +++ b/L1Trigger/DTTriggerPhase2/test/primitivesPhase2Prod_over_hlt_parallel_cfg.py @@ -0,0 +1,52 @@ +import FWCore.ParameterSet.Config as cms + +process = cms.Process("L1DTTrigPhase2Prod") + +process.load("Geometry.CMSCommonData.cmsIdealGeometryXML_cff") +process.load("Geometry.DTGeometry.dtGeometry_cfi") +process.DTGeometryESModule.applyAlignment = False + +process.load("L1Trigger.DTTriggerPhase2.dtTriggerPhase2PrimitiveDigis_cfi") +process.load("Configuration.StandardSequences.FrontierConditions_GlobalTag_cff") +process.load("Configuration.StandardSequences.MagneticField_AutoFromDBCurrent_cff") +#process.GlobalTag.globaltag = "90X_dataRun2_Express_v2" +process.GlobalTag.globaltag = "80X_dataRun2_2016SeptRepro_v7" + +#Calibrate Digis +process.load("L1Trigger.DTTriggerPhase2.CalibratedDigishlt_cfi") +#process.CalibratedDigis.flat_calib = 0 #turn to 0 to use the DB , 325 for JM and Jorge benchmark + +#DTTriggerPhase2 +process.load("L1Trigger.DTTriggerPhase2.dtTriggerPhase2PrimitiveDigishlt_cfi") + + + + + +process.dtTriggerPhase2PrimitiveDigis.pinta = True +process.dtTriggerPhase2PrimitiveDigis.min_phinhits_match_segment = 4 + +process.source = cms.Source("PoolSource", + fileNames = cms.untracked.vstring( + 'file:-input-' + ) + ) + +process.maxEvents = cms.untracked.PSet( + input = cms.untracked.int32(-1) +) + +process.out = cms.OutputModule("PoolOutputModule", + outputCommands = cms.untracked.vstring('keep *'), + fileName = cms.untracked.string('-output-') + ) + + +process.p = cms.Path(process.CalibratedDigis*process.dtTriggerPhase2PrimitiveDigis) +#process.this_is_the_end = cms.EndPath(process.out) + + + + + + diff --git a/L1Trigger/DTTriggerPhase2/test/primitivesPhase2Prod_over_mc_cfg.py b/L1Trigger/DTTriggerPhase2/test/primitivesPhase2Prod_over_mc_cfg.py new file mode 100644 index 0000000000000..c196b642a9f18 --- /dev/null +++ b/L1Trigger/DTTriggerPhase2/test/primitivesPhase2Prod_over_mc_cfg.py @@ -0,0 +1,67 @@ +import FWCore.ParameterSet.Config as cms + +process = cms.Process("L1DTTrigPhase2Prod") + +process.load("Geometry.CMSCommonData.cmsIdealGeometryXML_cff") +process.load("Geometry.DTGeometry.dtGeometry_cfi") +process.DTGeometryESModule.applyAlignment = False + +process.load("L1Trigger.DTTriggerPhase2.dtTriggerPhase2PrimitiveDigis_cfi") +process.load("Configuration.StandardSequences.FrontierConditions_GlobalTag_cff") +process.load("Configuration.StandardSequences.MagneticField_AutoFromDBCurrent_cff") +#process.GlobalTag.globaltag = "90X_dataRun2_Express_v2" +#process.GlobalTag.globaltag = "80X_dataRun2_2016SeptRepro_v7" +process.GlobalTag.globaltag = "100X_upgrade2018_realistic_v10" + +#Calibrate Digis +process.load("L1Trigger.DTTriggerPhase2.CalibratedDigis_cfi") +#process.CalibratedDigis.flat_calib = 325 #turn to 0 to use the DB , 325 for JM and Jorge benchmark +process.CalibratedDigis.dtDigiTag = "simMuonDTDigis" #turn to 0 to use the DB , 325 for JM and Jorge benchmark +process.CalibratedDigis.scenario = 0 # 0 for mc, 1 for data, 2 for slice test + +#DTTriggerPhase2 +process.load("L1Trigger.DTTriggerPhase2.dtTriggerPhase2PrimitiveDigis_cfi") +#process.dtTriggerPhase2PrimitiveDigis.trigger_with_sl = 3 #4 means SL 1 and 3 +#for the moment the part working in phase2 format is the slice test +#process.dtTriggerPhase2PrimitiveDigis.p2_df = True +#process.dtTriggerPhase2PrimitiveDigis.filter_primos = True +#for debugging +#process.dtTriggerPhase2PrimitiveDigis.pinta = True +#process.dtTriggerPhase2PrimitiveDigis.min_phinhits_match_segment = 4 +#process.dtTriggerPhase2PrimitiveDigis.debug = True +process.dtTriggerPhase2PrimitiveDigis.scenario = 0 +process.dtTriggerPhase2PrimitiveDigis.dump = True + +process.source = cms.Source("PoolSource",fileNames = cms.untracked.vstring( + 'file:/eos/cms/store/group/dpg_dt/comm_dt/TriggerSimulation/SamplesReco/SingleMu_FlatPt-2to100/Version_10_5_0/SimRECO_1.root', + 'file:/eos/cms/store/group/dpg_dt/comm_dt/TriggerSimulation/SamplesReco/SingleMu_FlatPt-2to100/Version_10_5_0/SimRECO_2.root', + 'file:/eos/cms/store/group/dpg_dt/comm_dt/TriggerSimulation/SamplesReco/SingleMu_FlatPt-2to100/Version_10_5_0/SimRECO_3.root', + 'file:/eos/cms/store/group/dpg_dt/comm_dt/TriggerSimulation/SamplesReco/SingleMu_FlatPt-2to100/Version_10_5_0/SimRECO_4.root', + 'file:/eos/cms/store/group/dpg_dt/comm_dt/TriggerSimulation/SamplesReco/SingleMu_FlatPt-2to100/Version_10_5_0/SimRECO_5.root', + 'file:/eos/cms/store/group/dpg_dt/comm_dt/TriggerSimulation/SamplesReco/SingleMu_FlatPt-2to100/Version_10_5_0/SimRECO_6.root', + 'file:/eos/cms/store/group/dpg_dt/comm_dt/TriggerSimulation/SamplesReco/SingleMu_FlatPt-2to100/Version_10_5_0/SimRECO_7.root', + 'file:/eos/cms/store/group/dpg_dt/comm_dt/TriggerSimulation/SamplesReco/SingleMu_FlatPt-2to100/Version_10_5_0/SimRECO_8.root', + 'file:/eos/cms/store/group/dpg_dt/comm_dt/TriggerSimulation/SamplesReco/SingleMu_FlatPt-2to100/Version_10_5_0/SimRECO_9.root', + 'file:/eos/cms/store/group/dpg_dt/comm_dt/TriggerSimulation/SamplesReco/SingleMu_FlatPt-2to100/Version_10_5_0/SimRECO_10.root', + 'file:/eos/cms/store/group/dpg_dt/comm_dt/TriggerSimulation/SamplesReco/SingleMu_FlatPt-2to100/Version_10_5_0/SimRECO_11.root', + 'file:/eos/cms/store/group/dpg_dt/comm_dt/TriggerSimulation/SamplesReco/SingleMu_FlatPt-2to100/Version_10_5_0/SimRECO_12.root', + 'file:/eos/cms/store/group/dpg_dt/comm_dt/TriggerSimulation/SamplesReco/SingleMu_FlatPt-2to100/Version_10_5_0/SimRECO_13.root' + ) + ) +process.maxEvents = cms.untracked.PSet( + input = cms.untracked.int32(2) +) + +process.out = cms.OutputModule("PoolOutputModule", + outputCommands = cms.untracked.vstring('keep *'), + fileName = cms.untracked.string('DTTriggerPhase2Primitives_testsmc.root') +) + +process.p = cms.Path(process.CalibratedDigis*process.dtTriggerPhase2PrimitiveDigis) +process.this_is_the_end = cms.EndPath(process.out) + + + + + + diff --git a/L1Trigger/DTTriggerPhase2/test/primitivesPhase2Prod_over_unpacked_cfg.py b/L1Trigger/DTTriggerPhase2/test/primitivesPhase2Prod_over_unpacked_cfg.py new file mode 100644 index 0000000000000..66a588eb7be3e --- /dev/null +++ b/L1Trigger/DTTriggerPhase2/test/primitivesPhase2Prod_over_unpacked_cfg.py @@ -0,0 +1,52 @@ +import FWCore.ParameterSet.Config as cms + +process = cms.Process("L1DTTrigPhase2Prod") + +process.load("Geometry.CMSCommonData.cmsIdealGeometryXML_cff") +process.load("Geometry.DTGeometry.dtGeometry_cfi") +process.DTGeometryESModule.applyAlignment = False + +process.load("L1Trigger.DTTriggerPhase2.dtTriggerPhase2PrimitiveDigis_cfi") +process.load("Configuration.StandardSequences.FrontierConditions_GlobalTag_cff") +process.load("Configuration.StandardSequences.MagneticField_AutoFromDBCurrent_cff") +#process.GlobalTag.globaltag = "90X_dataRun2_Express_v2" +process.GlobalTag.globaltag = "80X_dataRun2_2016SeptRepro_v7" + +#Calibrate Digis +#process.load("L1Trigger.DTTriggerPhase2.CalibratedDigis_cfi") +#process.CalibratedDigis.flat_calib = 325 #turn to 0 to use the DB , 325 for JM and Jorge benchmark + +#DTTriggerPhase2 +process.load("L1Trigger.DTTriggerPhase2.dtTriggerPhase2PrimitiveDigis_cfi") +process.dtTriggerPhase2PrimitiveDigis.trigger_with_sl = 4 #4 means SL 1 and 3 +process.dtTriggerPhase2PrimitiveDigis.digiTag=("ogdtab7unpacker") + +#for the moment the part working in phase2 format is the slice test +process.dtTriggerPhase2PrimitiveDigis.do_correlation = False +process.dtTriggerPhase2PrimitiveDigis.p2_df = True +#for debugging +#process.dtTriggerPhase2PrimitiveDigis.debug = True + +process.source = cms.Source("PoolSource", + fileNames = cms.untracked.vstring(#'file:/eos/user/c/carrillo/digis_segments_Run2016BSingleMuonRAW-RECO.root' + 'file:/tmp/carrillo/unpacker_output.root' + ) + ) +process.maxEvents = cms.untracked.PSet( + input = cms.untracked.int32(-1) +) + +process.out = cms.OutputModule("PoolOutputModule", + outputCommands = cms.untracked.vstring('keep *'), + fileName = cms.untracked.string('/tmp/carrillo/unpacked_and_emulator.root') +) + +#process.p = cms.Path(process.CalibratedDigis*process.dtTriggerPhase2PrimitiveDigis) +process.p = cms.Path(process.dtTriggerPhase2PrimitiveDigis) +process.this_is_the_end = cms.EndPath(process.out) + + + + + + diff --git a/L1Trigger/DTTriggerPhase2/test/prod_Zmu_digis_segments_cfg.py b/L1Trigger/DTTriggerPhase2/test/prod_Zmu_digis_segments_cfg.py new file mode 100644 index 0000000000000..73cfa52aebcec --- /dev/null +++ b/L1Trigger/DTTriggerPhase2/test/prod_Zmu_digis_segments_cfg.py @@ -0,0 +1,134 @@ +import FWCore.ParameterSet.Config as cms + +process = cms.Process("DigisSegments") + +process.load("Geometry.CMSCommonData.cmsIdealGeometryXML_cff") +process.load("Geometry.DTGeometry.dtGeometry_cfi") +process.DTGeometryESModule.applyAlignment = False + +process.load("Configuration.StandardSequences.FrontierConditions_GlobalTag_cff") +process.load("Configuration.StandardSequences.MagneticField_AutoFromDBCurrent_cff") +process.GlobalTag.globaltag = "90X_dataRun2_Express_v2" + +process.load("RecoLocalMuon.Configuration.RecoLocalMuon_cff") + +## DT unpacker +process.load("EventFilter.DTRawToDigi.dtunpacker_cfi") +process.muonDTDigis.inputLabel = 'rawDataCollector' + +process.source = cms.Source("PoolSource", + fileNames = cms.untracked.vstring( +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/90000/A8CD55CA-1F94-E611-8017-0CC47A7C35A8.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/90000/5E3D3C6E-6594-E611-AB43-0CC47A4D7616.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/FEB68681-5A87-E611-9374-FA163EBB015F.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/F8A610D8-6287-E611-845E-FA163E57640C.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/F80380BB-7687-E611-84D6-02163E01653D.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/F4A6C6FD-B089-E611-9227-002590DE6E64.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/F40149E2-7387-E611-B057-0025904CF766.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/F21AA882-6C87-E611-8F39-FA163EA18210.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/F0A05CAE-5387-E611-BACB-FA163E9FDE85.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/F095A793-B389-E611-8A84-00259021A39E.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/EE733CB6-B189-E611-A2A6-B499BAAC054A.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/EA70D05E-4589-E611-BFE3-FA163E3F2846.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/E46AF903-6C87-E611-8658-FA163EDB91EF.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/E4332BCB-D687-E611-A9EA-0025905A6126.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/E09E85A0-EB86-E611-B17D-20CF3019DEEF.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/DEEA9DDD-E187-E611-B13B-FA163E73AE79.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/DA12BA92-B087-E611-B7A3-0242AC130002.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/D615D999-B189-E611-B46C-FA163E8E175A.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/D6055073-6E87-E611-8E91-FA163E8D8332.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/D4FD5F54-658B-E611-BED9-0CC47A4D7646.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/D029A3C8-4B89-E611-9D1F-FA163E631428.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/CE3E1EE9-9789-E611-998C-FA163ED21222.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/CCDC87DF-1A88-E611-9B2A-1CC1DE19274E.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/C8F8C3B2-5387-E611-B9FC-FA163E5669B0.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/C4B49819-F286-E611-B127-549F358EB76F.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/C2B91F86-5A87-E611-B7E7-02163E014C10.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/C09B5970-4B88-E611-9C48-901B0E5427A6.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/BE837F4E-9E87-E611-8DC8-3417EBE7047A.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/BAC10123-7787-E611-A0DE-02163E015FDF.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/B856E93F-E586-E611-BA74-FA163E1909D1.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/B64FD56E-6E87-E611-BD9C-02163E016438.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/B4BC5C81-6987-E611-B97A-F04DA275C2FB.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/B43870D6-1A88-E611-A7C0-0026B9F8CC18.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/AE723C49-B287-E611-ACE5-0CC47A78A42E.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/AC213957-658B-E611-A7AF-0025905B8612.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/AA51B3CF-4B89-E611-A41A-02163E013C40.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/A8FF1F89-E586-E611-BC37-FA163E08C002.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/A28F9FFD-B489-E611-B864-008CFAFBF132.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/A21B22EA-8888-E611-B0C4-0CC47A4DEEBA.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/A0C3ADD4-0E87-E611-892F-02163E014D8C.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/9EE91F3C-1B87-E611-878C-FA163E775232.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/9CAF60BB-4489-E611-A29C-FA163EEF018D.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/9AAB70FE-D587-E611-834C-FA163ECD5C62.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/9A522CDD-6287-E611-BA23-FA163E3DAA96.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/9A345235-E586-E611-9CE6-FA163EFA00C3.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/98CD93AB-3A88-E611-A4C8-B083FED04276.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/961767D1-B189-E611-A1A3-20CF305B05AE.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/90AAF1A6-5387-E611-B9B8-0025905C3DF6.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/90522755-9587-E611-A29C-C45444922BB0.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/901352B9-B189-E611-89EC-0CC47A6C183A.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/8E949801-8288-E611-B9D6-047D7BD6DF22.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/88ADAECF-5789-E611-81B2-FA163EDB91EF.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/8823F019-8587-E611-A162-00259073E3EA.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/80CD4397-2A88-E611-9639-20474791CCC4.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/8095FC8B-B389-E611-ADD9-7CD30AB7F868.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/767A38E6-6287-E611-B225-02163E015D84.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/744FC7C0-5387-E611-BA6F-FA163E06DFEA.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/6CFB58E7-1587-E611-BD35-FA163EC97E57.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/68DE47B4-7E88-E611-A6AE-001E67792422.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/68A0DCD5-BB87-E611-8BF3-008CFA0F5040.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/68171F81-6187-E611-A9DF-001E67504F1D.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/66421E3C-5489-E611-B0BE-001E67505A2D.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/64FB46E3-8887-E611-AAAA-FA163EFA220C.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/64CC5933-4088-E611-B8DD-0025904C641E.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/6448920B-7D87-E611-A5EA-02163E017614.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/6297FABA-5789-E611-A918-0CC47AC08BF8.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/5C7F15A9-9A88-E611-A80B-FA163EC5FCBC.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/5A63963D-B887-E611-88DC-001E6739C801.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/5404AF86-6187-E611-8DB3-44A84225CDA4.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/509458EF-B189-E611-9F85-FA163E17EB18.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/4C3B6518-B189-E611-93B3-0025905A612A.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/48E6AB0F-F286-E611-9792-FA163EDB91EF.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/40E2E2DE-8887-E611-9531-FA163E2AAF83.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/38FF87C2-B189-E611-B665-0CC47A1DF7FA.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/38CE04DC-5788-E611-9240-848F69FD2853.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/32775AB1-6C87-E611-A388-02163E0165D4.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/30A4019E-FE86-E611-B70E-02163E0165B6.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/2C6B53B6-5387-E611-9582-FA163E75F411.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/26D33DC4-3889-E611-B1AF-FA163E743F0B.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/26181B1F-6387-E611-AC9E-02163E01304E.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/24A815DC-0E87-E611-8D96-B083FED13C9E.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/22256107-6887-E611-847F-002590DE6E86.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/20263DED-9B88-E611-9630-001E67F336E0.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/1EF43C44-DE87-E611-BB70-6C3BE5B5B340.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/128426B7-8988-E611-BB9C-008CFA0A5A10.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/1041B010-6F87-E611-BA26-02163E015FDB.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/0E90E9AF-5387-E611-9FFA-FA163EC80D44.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/0C894F1B-5289-E611-8381-0025904C5DE0.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/0C6DFDD5-4D87-E611-9CF3-FA163E0B7F2E.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/0C153439-B187-E611-96D9-002590E1E9B8.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/083DFA38-B189-E611-BD7C-A0369F7FC770.root", +"/store/data/Run2016B/SingleMuon/RAW-RECO/ZMu-23Sep2016-v1/70000/02A6971D-F286-E611-8364-002590DE6E32.root" + ) + ) + +process.maxEvents = cms.untracked.PSet( + input = cms.untracked.int32(-1) +) + +process.out = cms.OutputModule("PoolOutputModule", + outputCommands = cms.untracked.vstring('drop *','keep *_muonDTDigis_*_*','keep *_dt4DSegments_*_*'), + fileName = cms.untracked.string('/store/user/carrillo/digis_segments_Run2016BSingleMuonRAW-RECO.root') +) + + + +process.p = cms.Path(process.muonDTDigis*process.dtlocalreco) +process.this_is_the_end = cms.EndPath(process.out) + + + + + + diff --git a/L1Trigger/DTTriggerPhase2/test/test_primitivesPhase2Prod_over_dTDigis_and_4Dsegments_cfg.py b/L1Trigger/DTTriggerPhase2/test/test_primitivesPhase2Prod_over_dTDigis_and_4Dsegments_cfg.py new file mode 100644 index 0000000000000..3dbafe0e1dec4 --- /dev/null +++ b/L1Trigger/DTTriggerPhase2/test/test_primitivesPhase2Prod_over_dTDigis_and_4Dsegments_cfg.py @@ -0,0 +1,74 @@ +import FWCore.ParameterSet.Config as cms + +process = cms.Process("L1DTTrigPhase2Prod") + +process.load('Configuration.Geometry.GeometryExtended2026D41Reco_cff') +process.load('Configuration.Geometry.GeometryExtended2026D41_cff') + +process.load("L1Trigger.DTTriggerPhase2.dtTriggerPhase2PrimitiveDigis_cfi") +process.load("Configuration.StandardSequences.FrontierConditions_GlobalTag_cff") +process.load("Configuration.StandardSequences.MagneticField_AutoFromDBCurrent_cff") +process.GlobalTag.globaltag = "80X_dataRun2_2016SeptRepro_v7" + +process.load("L1Trigger.DTTriggerPhase2.CalibratedDigis_cfi") +process.load("L1Trigger.DTTriggerPhase2.dtTriggerPhase2PrimitiveDigis_cfi") + +#process.source = cms.Source("PoolSource",fileNames = cms.untracked.vstring('file:/eos/cms/store/user/folguera/P2L1TUpgrade/digis_segments_Run2016BSingleMuonRAW-RECO_camilo.root')) +process.source = cms.Source("PoolSource", + fileNames = cms.untracked.vstring('file:/eos/cms/store/user/folguera/P2L1TUpgrade/digis_segments_Run2016BSingleMuonRAW-RECO_camilo.root')) +process.maxEvents = cms.untracked.PSet(input = cms.untracked.int32(10)) +process.dtTriggerPhase2PrimitiveDigis.dump = True +process.dtTriggerPhase2PrimitiveDigis.debug = False +process.dtTriggerPhase2PrimitiveDigis.chi2Th = cms.untracked.double(0.16) + +#scenario +process.dtTriggerPhase2PrimitiveDigis.scenario = 1 +process.CalibratedDigis.scenario = 1 + +process.load("FWCore.MessageLogger.MessageLogger_cfi") +process.MessageLogger = cms.Service("MessageLogger", + destinations = cms.untracked.vstring("detailedInfo"), + detailedInfo = cms.untracked.PSet(threshold = cms.untracked.string("INFO"), + categories = cms.untracked.vstring("DTTrigPhase2Prod"), + extension = cms.untracked.string(".txt")), + debugModules = cms.untracked.vstring("dtTriggerPhase2PrimitiveDigis"), +) + +####################### SliceTest specials ############################## +#Chi2 -> Changing a lot lately +process.dtTriggerPhase2PrimitiveDigis.chi2Th = cms.untracked.double(0.16) + +#LSB -> Position 0.025 cm instead of 0.004 cm +process.dtTriggerPhase2PrimitiveDigis.use_LSB = True +process.dtTriggerPhase2PrimitiveDigis.x_precision = cms.untracked.double(1./(10.*16.)) +#process.dtTriggerPhase2PrimitiveDigis.x_precision = cms.untracked.double(0.025) +process.dtTriggerPhase2PrimitiveDigis.tanPsi_precision = cms.untracked.double(1./4096.) + +#Correlate with BX +process.dtTriggerPhase2PrimitiveDigis.useBX_correlation = True +process.dtTriggerPhase2PrimitiveDigis.dBX_correlate_TP = 1 + +#Correlate with tanPsi +#process.dtTriggerPhase2PrimitiveDigis.dTanPsi_correlate_TP = cms.untracked.double(9999./4096.) +#process.dtTriggerPhase2PrimitiveDigis.dTanPsi_correlate_TP = cms.untracked.double(900./4096.) + +#Confirmation forbidden +process.dtTriggerPhase2PrimitiveDigis.allow_confirmation = True + +#TanPsi stuff +process.dtTriggerPhase2PrimitiveDigis.tanPhiTh = cms.untracked.double(1.) + + +process.out = cms.OutputModule("PoolOutputModule", + outputCommands = cms.untracked.vstring('keep *'), + fileName = cms.untracked.string('DTTriggerPhase2Primitives.root') +) + +process.p = cms.Path(process.CalibratedDigis*process.dtTriggerPhase2PrimitiveDigis) +process.this_is_the_end = cms.EndPath(process.out) + + + + + +