diff --git a/DataFormats/L1TrackTrigger/interface/TTBV.h b/DataFormats/L1TrackTrigger/interface/TTBV.h index 22cc81410ca86..f18f96cacd900 100644 --- a/DataFormats/L1TrackTrigger/interface/TTBV.h +++ b/DataFormats/L1TrackTrigger/interface/TTBV.h @@ -7,29 +7,31 @@ #include #include #include +#include +#include /*! * \class TTBV * \brief Bit vector used by Track Trigger emulators. Mainly used to convert - * integers into arbitrary (within margin) sized two's complement string. + * integers into arbitrary (within margin) sized two's complement strings. * \author Thomas Schuh * \date 2020, Jan */ class TTBV { public: - static constexpr int S = 64; // Frame width of emp infrastructure f/w, max number of bits a TTBV can handle + static constexpr int S_ = 64; // Frame width of emp infrastructure f/w, max number of bits a TTBV can handle private: - bool twos_; // Two's complement (true) or binary (false) - int size_; // number or bits - std::bitset bs_; // underlying storage + bool twos_; // Two's complement (true) or binary (false) + int size_; // number or bits + std::bitset bs_; // underlying storage public: // constructor: default - TTBV() : twos_(false), size_(S), bs_(std::bitset(0)) {} + TTBV() : twos_(false), size_(0), bs_() {} // constructor: double precision (IEEE 754); from most to least significant bit: 1 bit sign + 11 bit binary exponent + 52 bit binary mantisse - TTBV(const double d) : twos_(false), size_(S) { + TTBV(const double d) : twos_(false), size_(S_) { int index(0); const char* c = reinterpret_cast(&d); for (int iByte = 0; iByte < (int)sizeof(d); iByte++) { @@ -40,45 +42,58 @@ class TTBV { } // constructor: unsigned int value - TTBV(unsigned long long int value, int size) : twos_(false), size_(size), bs_(std::bitset(value)) {} + TTBV(unsigned long long int value, int size) : twos_(false), size_(size), bs_(value) {} // constructor: int value - TTBV(int value, int size, bool Signed = false) - : twos_(Signed), size_(size), bs_(std::bitset((!Signed || value >= 0) ? value : value + iMax())) {} + TTBV(int value, int size, bool twos = false) + : twos_(twos), size_(size), bs_((!twos || value >= 0) ? value : value + iMax()) {} // constructor: double value + precision, biased (floor) representation - TTBV(double value, double base, int size, bool Signed = false) : TTBV((int)std::floor(value / base), size, Signed) {} + TTBV(double value, double base, int size, bool twos = false) : TTBV((int)std::floor(value / base), size, twos) {} // constructor: string - TTBV(const std::string& str, bool Signed = false) : twos_(Signed), size_(str.size()), bs_(std::bitset(str)) {} + TTBV(const std::string& str, bool twos = false) : twos_(twos), size_(str.size()), bs_(str) {} // constructor: bitset - TTBV(const std::bitset& bs, bool Signed = false) : twos_(Signed), size_(S), bs_(std::bitset(bs)) {} + TTBV(const std::bitset& bs, bool twos = false) : twos_(twos), size_(S_), bs_(bs) {} - // access: data members + // constructor: slice reinterpret sign + TTBV(const TTBV& ttBV, int begin, int end = 0, bool twos = false) : twos_(twos), size_(begin - end), bs_(ttBV.bs_) { + bs_ <<= S_ - begin; + bs_ >>= S_ - begin + end; + } + + // Two's complement (true) or binary (false) bool twos() const { return twos_; } + // number or bits int size() const { return size_; } - std::bitset bs() const { return bs_; } + // underlying storage + const std::bitset& bs() const { return bs_; } // access: single bit bool operator[](int pos) const { return bs_[pos]; } - std::bitset::reference operator[](int pos) { return bs_[pos]; } + std::bitset::reference operator[](int pos) { return bs_[pos]; } - // access: most significant bit + // access: most significant bit copy bool msb() const { return bs_[size_ - 1]; } - std::bitset::reference msb() { return bs_[size_ - 1]; } + + // access: most significant bit reference + std::bitset::reference msb() { return bs_[size_ - 1]; } // access: members of underlying bitset + bool all() const { return bs_.all(); } bool any() const { return bs_.any(); } bool none() const { return bs_.none(); } int count() const { return bs_.count(); } - // operator: comparisons + // operator: comparisons equal bool operator==(const TTBV& rhs) const { return bs_ == rhs.bs_; } + + // operator: comparisons not equal bool operator!=(const TTBV& rhs) const { return bs_ != rhs.bs_; } - // operator: boolean and, or, xor, not + // operator: boolean and TTBV& operator&=(const TTBV& rhs) { const int m(std::max(size_, rhs.size())); this->resize(m); @@ -87,6 +102,8 @@ class TTBV { bs_ &= bv.bs_; return *this; } + + // operator: boolean or TTBV& operator|=(const TTBV& rhs) { const int m(std::max(size_, rhs.size())); this->resize(m); @@ -95,6 +112,8 @@ class TTBV { bs_ |= bv.bs_; return *this; } + + // operator: boolean xor TTBV& operator^=(const TTBV& rhs) { const int m(std::max(size_, rhs.size())); this->resize(m); @@ -103,39 +122,49 @@ class TTBV { bs_ ^= bv.bs_; return *this; } + + // operator: not TTBV operator~() const { TTBV bv(*this); return bv.flip(); } - // operator: bit shifts + // reference operator: bit remove right TTBV& operator>>=(int pos) { bs_ >>= pos; size_ -= pos; return *this; } + + // reference operator: bit remove left TTBV& operator<<=(int pos) { - bs_ <<= S - size_ + pos; - bs_ >>= S - size_ + pos; + bs_ <<= S_ - size_ + pos; + bs_ >>= S_ - size_ + pos; size_ -= pos; return *this; } + + // operator: bit remove left copy TTBV operator<<(int pos) const { TTBV bv(*this); - return bv >>= pos; + return bv <<= pos; } + + // operator: bit remove right copy TTBV operator>>(int pos) const { TTBV bv(*this); - return bv <<= pos; + return bv >>= pos; } - // operator: concatenation + // reference operator: concatenation TTBV& operator+=(const TTBV& rhs) { bs_ <<= rhs.size(); bs_ |= rhs.bs_; size_ += rhs.size(); return *this; } + + // operator: concatenation copy TTBV operator+(const TTBV& rhs) const { TTBV lhs(*this); return lhs += rhs; @@ -143,49 +172,62 @@ class TTBV { // operator: value increment, overflow protected TTBV& operator++() { - bs_ = std::bitset(bs_.to_ullong() + 1); + bs_ = std::bitset(bs_.to_ullong() + 1); this->resize(size_); return *this; } - // manipulation: all bits + // manipulation: all bits set to 0 TTBV& reset() { bs_.reset(); return *this; } + + // manipulation: all bits set to 1 TTBV& set() { for (int n = 0; n < size_; n++) bs_.set(n); return *this; } + + // manipulation: all bits flip 1 to 0 and vice versa TTBV& flip() { for (int n = 0; n < size_; n++) bs_.flip(n); return *this; } - // manipulation: single bit + // manipulation: single bit set to 0 TTBV& reset(int pos) { bs_.reset(pos); return *this; } + + // manipulation: single bit set to 1 TTBV& set(int pos) { bs_.set(pos); return *this; } + + // manipulation: multiple bit set to 1 + TTBV& set(std::vector vpos) { + for (int pos : vpos) + bs_.set(pos); + return *this; + } + + // manipulation: single bit flip 1 to 0 and vice versa TTBV& flip(int pos) { bs_.flip(pos); return *this; } - // manipulation: biased absolute value + // manipulation: absolute value of biased twos' complement. Converts twos' complenet into binary. TTBV& abs() { if (twos_) { twos_ = false; - if (this->msb()) { + if (this->msb()) this->flip(); - this->operator++(); - } size_--; } return *this; @@ -208,7 +250,7 @@ class TTBV { } // conversion: to string - std::string str() const { return bs_.to_string().substr(S - size_, S); } + std::string str() const { return bs_.to_string().substr(S_ - size_, S_); } // conversion: range based to string std::string str(int start, int end = 0) const { return this->str().substr(size_ - start, size_ - end); } @@ -217,14 +259,40 @@ class TTBV { int val() const { return (twos_ && this->msb()) ? (int)bs_.to_ullong() - iMax() : bs_.to_ullong(); } // conversion: to int, reinterpret sign - int val(bool Signed) const { return (Signed && this->msb()) ? (int)bs_.to_ullong() - iMax() : bs_.to_ullong(); } + int val(bool twos) const { return (twos && this->msb()) ? (int)bs_.to_ullong() - iMax() : bs_.to_ullong(); } // conversion: range based to int, reinterpret sign - int val(int start, int end = 0, bool Signed = false) const { return TTBV(this->str(start, end), Signed).val(); } + int val(int start, int end = 0, bool twos = false) const { return TTBV(*this, start, end).val(twos); } // conversion: to double for given precision assuming biased (floor) representation double val(double base) const { return (this->val() + .5) * base; } + // conversion: range based to double for given precision assuming biased (floor) representation, reinterpret sign + double val(double base, int start, int end = 0, bool twos = false) const { + return (this->val(start, end, twos) + .5) * base; + } + + // maniplulation and conversion: extracts range based to double reinterpret sign and removes these bits + double extract(double base, int size, bool twos = false) { + double val = this->val(base, size, 0, twos); + this->operator>>=(size); + return val; + } + + // maniplulation and conversion: extracts range based to int reinterpret sign and removes these bits + int extract(int size, bool twos = false) { + double val = this->val(size, 0, twos); + this->operator>>=(size); + return val; + } + + // manipulation: extracts slice and removes these bits + TTBV slice(int size, bool twos = false) { + TTBV ttBV(*this, size, 0, twos); + this->operator>>=(size); + return ttBV; + } + // range based count of '1's or '0's int count(int begin, int end, bool b = true) const { int c(0); @@ -250,18 +318,42 @@ class TTBV { return size_; } + // position for n'th '1' or '0' counted from least to most significant bit + int encode(int n, bool b = true) const { + int sum(0); + for (int e = 0; e < size_; e++) { + if (bs_[e] == b) { + sum++; + if (sum == n) + return e; + } + } + return size_; + } + + std::vector ids(bool b = true, bool singed = false) const { + std::vector v; + v.reserve(bs_.count()); + for (int i = 0; i < size_; i++) + if (bs_[i] == b) + v.push_back(singed ? i + size_ / 2 : i); + return v; + } + + friend std::ostream& operator<<(std::ostream& os, const TTBV& ttBV) { return os << ttBV.str(); } + private: // look up table initializer for powers of 2 - constexpr std::array powersOfTwo() const { - std::array lut = {}; - for (int i = 0; i < S; i++) + constexpr std::array powersOfTwo() const { + std::array lut = {}; + for (int i = 0; i < S_; i++) lut[i] = std::pow(2, i); return lut; } // returns 2 ** size_ unsigned long long int iMax() const { - static const std::array lut = powersOfTwo(); + static const std::array lut = powersOfTwo(); return lut[size_]; } }; diff --git a/DataFormats/L1TrackTrigger/interface/TTDTC.h b/DataFormats/L1TrackTrigger/interface/TTDTC.h index 586301dd714c4..1eb786910f5b5 100644 --- a/DataFormats/L1TrackTrigger/interface/TTDTC.h +++ b/DataFormats/L1TrackTrigger/interface/TTDTC.h @@ -16,15 +16,6 @@ */ class TTDTC { public: - // bit accurate Stub - typedef std::bitset BV; - // TTStub with bit accurate Stub - typedef std::pair Frame; - // stub collection transported over an optical link between DTC and TFP - typedef std::vector Stream; - // collection of optical links - typedef std::vector Streams; - TTDTC() {} TTDTC(int numRegions, int numOverlappingRegions, int numDTCsPerRegion); ~TTDTC() {} @@ -35,10 +26,10 @@ class TTDTC { const std::vector& tfpChannels() const { return channels_; } // write one specific stream of TTStubRefs using DTC identifier (region[0-8], board[0-23], channel[0-1]) // dtcRegions aka detector regions are defined by tk layout - void setStream(int dtcRegion, int dtcBoard, int dtcChannel, const Stream& stream); + void setStream(int dtcRegion, int dtcBoard, int dtcChannel, const tt::StreamStub& stream); // read one specific stream of TTStubRefs using TFP identifier (region[0-8], channel[0-47]) // tfpRegions aka processing regions are rotated by -0.5 region width w.r.t detector regions - const Stream& stream(int tfpRegion, int tfpChannel) const; + const tt::StreamStub& stream(int tfpRegion, int tfpChannel) const; // total number of frames int size() const; // total number of stubs @@ -64,7 +55,7 @@ class TTDTC { // all TFP channel [default 0..47] std::vector channels_; // collection of all optical links between DTC and TFP [default 432 links] - Streams streams_; + tt::StreamsStub streams_; }; #endif \ No newline at end of file diff --git a/DataFormats/L1TrackTrigger/interface/TTTypes.h b/DataFormats/L1TrackTrigger/interface/TTTypes.h index cf739f7161253..cd39890561977 100644 --- a/DataFormats/L1TrackTrigger/interface/TTTypes.h +++ b/DataFormats/L1TrackTrigger/interface/TTTypes.h @@ -18,32 +18,56 @@ #include "DataFormats/L1TrackTrigger/interface/TTStub.h" #include "DataFormats/L1TrackTrigger/interface/TTTrack.h" #include "DataFormats/L1TrackTrigger/interface/TTTrack_TrackWord.h" +#include "DataFormats/L1TrackTrigger/interface/TTBV.h" + +#include /// Templated aliases template -using TTClusterDetSetVecT = edmNew::DetSetVector >; +using TTClusterDetSetVecT = edmNew::DetSetVector>; template -using TTStubDetSetVecT = edmNew::DetSetVector >; +using TTStubDetSetVecT = edmNew::DetSetVector>; template -using TTClusterRefT = edm::Ref, TTCluster >; +using TTClusterRefT = edm::Ref, TTCluster>; template -using TTStubRefT = edm::Ref, TTStub >; +using TTStubRefT = edm::Ref, TTStub>; template -using TTTrackPtrT = edm::Ptr >; +using TTTrackPtrT = edm::Ptr>; /// Specialized aliases typedef edm::Ref, Phase2TrackerDigi> Ref_Phase2TrackerDigi_; -typedef edmNew::DetSet > TTStubDetSet; - typedef TTClusterDetSetVecT TTClusterDetSetVec; typedef TTStubDetSetVecT TTStubDetSetVec; typedef TTClusterRefT TTClusterRef; typedef TTStubRefT TTStubRef; +typedef edmNew::DetSet> TTStubDetSet; +typedef edmNew::DetSet> TTClusterDetSet; + +typedef edm::Ref>, TTTrack> TTTrackRef; typedef TTTrackPtrT TTTrackPtr; +namespace tt { + // types including digitized info on an optical link + + // emp framework firmware frame (64 bit word) + typedef std::bitset Frame; + // reference to TTStub with bit accurate f/w word + typedef std::pair FrameStub; + // reference to TTTrack with bit accurate f/w word, only used before TFP output since TFP output uses more then one frame per TTTrack + typedef std::pair FrameTrack; + typedef std::vector StreamStub; + typedef std::vector StreamTrack; + typedef std::vector Stream; + typedef std::vector StreamsStub; + typedef std::vector StreamsTrack; + typedef std::vector Streams; + typedef std::map TTTrackRefMap; + typedef std::vector> TTTracks; +} // namespace tt + #endif diff --git a/DataFormats/L1TrackTrigger/src/TTDTC.cc b/DataFormats/L1TrackTrigger/src/TTDTC.cc index 60fff29d2efe0..7a54d81da358d 100644 --- a/DataFormats/L1TrackTrigger/src/TTDTC.cc +++ b/DataFormats/L1TrackTrigger/src/TTDTC.cc @@ -5,6 +5,7 @@ using namespace std; using namespace edm; +using namespace tt; TTDTC::TTDTC(int numRegions, int numOverlappingRegions, int numDTCsPerRegion) : numRegions_(numRegions), @@ -20,7 +21,7 @@ TTDTC::TTDTC(int numRegions, int numOverlappingRegions, int numDTCsPerRegion) // write one specific stream of TTStubRefs using DTC identifier (region[0-8], board[0-23], channel[0-1]) // dtcRegions aka detector regions are defined by tk layout -void TTDTC::setStream(int dtcRegion, int dtcBoard, int dtcChannel, const Stream& stream) { +void TTDTC::setStream(int dtcRegion, int dtcBoard, int dtcChannel, const StreamStub& stream) { // check arguments const bool oorRegion = dtcRegion >= numRegions_ || dtcRegion < 0; const bool oorBoard = dtcBoard >= numDTCsPerRegion_ || dtcBoard < 0; @@ -44,7 +45,7 @@ void TTDTC::setStream(int dtcRegion, int dtcBoard, int dtcChannel, const Stream& // read one specific stream of TTStubRefs using TFP identifier (region[0-8], channel[0-47]) // tfpRegions aka processing regions are rotated by -0.5 region width w.r.t detector regions -const TTDTC::Stream& TTDTC::stream(int tfpRegion, int tfpChannel) const { +const StreamStub& TTDTC::stream(int tfpRegion, int tfpChannel) const { // check arguments const bool oorRegion = tfpRegion >= numRegions_ || tfpRegion < 0; const bool oorChannel = tfpChannel >= numDTCsPerTFP_ || tfpChannel < 0; @@ -64,24 +65,24 @@ const TTDTC::Stream& TTDTC::stream(int tfpRegion, int tfpChannel) const { // total number of frames int TTDTC::size() const { - auto all = [](int& sum, const Stream& stream) { return sum += stream.size(); }; + auto all = [](int& sum, const StreamStub& stream) { return sum += stream.size(); }; return accumulate(streams_.begin(), streams_.end(), 0, all); } // total number of stubs int TTDTC::nStubs() const { - auto stubs = [](int& sum, const Frame& frame) { return sum += frame.first.isNonnull(); }; + auto stubs = [](int& sum, const FrameStub& frame) { return sum += frame.first.isNonnull(); }; int n(0); - for (const Stream& stream : streams_) + for (const StreamStub& stream : streams_) n += accumulate(stream.begin(), stream.end(), 0, stubs); return n; } // total number of gaps int TTDTC::nGaps() const { - auto gaps = [](int& sum, const Frame& frame) { return sum += frame.first.isNull(); }; + auto gaps = [](int& sum, const FrameStub& frame) { return sum += frame.first.isNull(); }; int n(0); - for (const Stream& stream : streams_) + for (const StreamStub& stream : streams_) n += accumulate(stream.begin(), stream.end(), 0, gaps); return n; } diff --git a/DataFormats/L1TrackTrigger/src/classes_def.xml b/DataFormats/L1TrackTrigger/src/classes_def.xml index 9d5ce0be50192..800cf2528af7f 100644 --- a/DataFormats/L1TrackTrigger/src/classes_def.xml +++ b/DataFormats/L1TrackTrigger/src/classes_def.xml @@ -37,9 +37,19 @@ - + + + + + + + + + + + + - diff --git a/DataFormats/L1TrackTrigger/test/TestDataFormatsTTTrackTrackWord.cc b/DataFormats/L1TrackTrigger/test/TestDataFormatsTTTrackTrackWord.cc index 3eb6c49b54d15..a92c28f9728a5 100644 --- a/DataFormats/L1TrackTrigger/test/TestDataFormatsTTTrackTrackWord.cc +++ b/DataFormats/L1TrackTrigger/test/TestDataFormatsTTTrackTrackWord.cc @@ -12,7 +12,7 @@ namespace trackwordtest { class TTTrackTrackWordDummyOneAnalyzer : public edm::one::EDAnalyzer<> { public: explicit TTTrackTrackWordDummyOneAnalyzer(const edm::ParameterSet&) {} - ~TTTrackTrackWordDummyOneAnalyzer() {} + ~TTTrackTrackWordDummyOneAnalyzer() override {} void analyze(edm::Event const& iEvent, edm::EventSetup const& iSetup) override { TTTrack_TrackWord tw; diff --git a/L1Trigger/TrackFindingTMTT/interface/KFParamsComb.h b/L1Trigger/TrackFindingTMTT/interface/KFParamsComb.h index a87d9c2548e6d..48f25fdfa1516 100644 --- a/L1Trigger/TrackFindingTMTT/interface/KFParamsComb.h +++ b/L1Trigger/TrackFindingTMTT/interface/KFParamsComb.h @@ -5,8 +5,30 @@ #include "L1Trigger/TrackFindingTMTT/interface/L1track3D.h" ///=== This is the Kalman Combinatorial Filter for 4 & 5 helix parameters track fit algorithm. +///=== ///=== All variable names & equations come from Fruhwirth KF paper ///=== http://dx.doi.org/10.1016/0168-9002%2887%2990887-4 +///=== +///=== Summary of variables: +///=== m = hit position (phi,z) +///=== V = hit position 2x2 covariance matrix in (phi,z). +///=== x = helix params +///=== C = helix params 4x4 covariance matrix +///=== r = residuals +///=== H = 2x4 derivative matrix (expected stub position w.r.t. helix params) +///=== K = KF gain 2x2 matrix +///=== x' & C': Updated values of x & C after KF iteration +///=== Boring: F = unit matrix; pxcov = C +///=== +///=== Summary of equations: +///=== S = H*C (2x4 matrix); St = Transpose S +///=== R = V + H*C*Ht (KF paper) = V + H*St (used here at simpler): 2x2 matrix +///=== Rinv = Inverse R +///=== K = St * Rinv : 2x2 Kalman gain matrix * det(R) +///=== r = m - H*x +///=== x' = x + K*r +///=== C' = C - K*H*C (KF paper) = C - K*S (used here as simpler) +///=== delta(chi2) = r(transpose) * Rinv * r : Increase in chi2 from new stub added during iteration. namespace tmtt { diff --git a/L1Trigger/TrackFindingTMTT/interface/KFbase.h b/L1Trigger/TrackFindingTMTT/interface/KFbase.h index 36ff3642d6764..1a6e3ecaff2a3 100644 --- a/L1Trigger/TrackFindingTMTT/interface/KFbase.h +++ b/L1Trigger/TrackFindingTMTT/interface/KFbase.h @@ -48,6 +48,27 @@ namespace tmtt { // Do KF fit L1fittedTrack fit(const L1track3D &l1track3D) override; + static const unsigned int nKFlayer_ = 7; + static const unsigned int nEta_ = 16; + static const unsigned int nGPlayer_ = 7; + static constexpr unsigned int invalidKFlayer_ = nKFlayer_; + + // index across is GP encoded layer ID (where barrel layers=1,2,7,5,4,3 & endcap wheels=3,4,5,6,7 & 0 never occurs) + // index down is eta reg + // element.first is kalman layer when stub is from barrel, 7 is invalid + // element.second is kalman layer when stub is from endcap, 7 is invalid + + static constexpr std::pair layerMap_[nEta_ / 2][nGPlayer_ + 1] = { + {{7, 7}, {0, 7}, {1, 7}, {5, 7}, {4, 7}, {3, 7}, {7, 7}, {2, 7}}, // B1 B2 B3 B4 B5 B6 + {{7, 7}, {0, 7}, {1, 7}, {5, 7}, {4, 7}, {3, 7}, {7, 7}, {2, 7}}, // B1 B2 B3 B4 B5 B6 + {{7, 7}, {0, 7}, {1, 7}, {5, 7}, {4, 7}, {3, 7}, {7, 7}, {2, 7}}, // B1 B2 B3 B4 B5 B6 + {{7, 7}, {0, 7}, {1, 7}, {5, 7}, {4, 7}, {3, 7}, {7, 7}, {2, 7}}, // B1 B2 B3 B4 B5 B6 + {{7, 7}, {0, 7}, {1, 7}, {5, 4}, {4, 5}, {3, 6}, {7, 7}, {2, 7}}, // B1 B2 B3 B4(/D3) B5(/D2) B6(/D1) + {{7, 7}, {0, 7}, {1, 7}, {7, 3}, {7, 4}, {2, 5}, {7, 6}, {2, 6}}, // B1 B2 B3(/D5)+B4(/D3) D1 D2 X D4 + {{7, 7}, {0, 7}, {1, 7}, {7, 2}, {7, 3}, {7, 4}, {7, 5}, {7, 6}}, // B1 B2 D1 D2 D3 D4 D5 + {{7, 7}, {0, 7}, {7, 7}, {7, 1}, {7, 2}, {7, 3}, {7, 4}, {7, 5}}, // B1 D1 D2 D3 D4 D5 + }; + protected: // Do KF fit (internal) const KalmanState *doKF(const L1track3D &l1track3D, const std::vector &stubs, const TP *tpa); diff --git a/L1Trigger/TrackFindingTMTT/interface/TrackerModule.h b/L1Trigger/TrackFindingTMTT/interface/TrackerModule.h index e29f665c2496d..14dde3f51c528 100644 --- a/L1Trigger/TrackFindingTMTT/interface/TrackerModule.h +++ b/L1Trigger/TrackFindingTMTT/interface/TrackerModule.h @@ -97,7 +97,28 @@ namespace tmtt { //--- Utilties // Calculate reduced layer ID (in range 1-7), for packing into 3 bits to simplify the firmware. - static unsigned int calcLayerIdReduced(unsigned int layerId); + static unsigned int calcLayerIdReduced(unsigned int layerId) { + // Don't bother distinguishing two endcaps, as no track can have stubs in both. + unsigned int lay = (layerId < 20) ? layerId : layerId - 10; + + // No genuine track can have stubs in both barrel layer 6 and endcap disk 11 etc., so merge their layer IDs. + if (lay == 6) + lay = 11; + if (lay == 5) + lay = 12; + if (lay == 4) + lay = 13; + if (lay == 3) + lay = 15; + // At this point, the reduced layer ID can have values of 1, 2, 11, 12, 13, 14, 15. So correct to put in range 1-7. + if (lay > 10) + lay -= 8; + + if (lay < 1 || lay > 7) + throw cms::Exception("LogicError") << "TrackerModule: Reduced layer ID out of expected range"; + + return lay; + } // Get module type ID defined by firmware. unsigned int calcModuleType(float pitch, float space, bool barrel, bool tiltedBarrel, bool psModule) const; diff --git a/L1Trigger/TrackFindingTMTT/src/KFbase.cc b/L1Trigger/TrackFindingTMTT/src/KFbase.cc index 53e7fcbe943c6..286701d638af0 100644 --- a/L1Trigger/TrackFindingTMTT/src/KFbase.cc +++ b/L1Trigger/TrackFindingTMTT/src/KFbase.cc @@ -202,8 +202,7 @@ namespace tmtt { // Get Kalman encoded layer ID for this stub. int kalmanLay = this->kalmanLayer(etaReg, stub->layerIdReduced(), stub->barrel(), stub->r(), stub->z()); - constexpr unsigned int invalidKFlayer = 7; - if (kalmanLay != invalidKFlayer) { + if (kalmanLay != invalidKFlayer_) { if (layerStubs[kalmanLay].size() < settings_->kalmanMaxStubsPerLayer()) { layerStubs[kalmanLay].push_back(stub); } else { @@ -267,7 +266,7 @@ namespace tmtt { if (kfDeadLayers.find(layer + 1) != kfDeadLayers.end() && layerStubs[layer + 1].empty()) { nextlay_stubs = layerStubs[layer + 2]; nSkippedDeadLayers_nextStubs++; - } else if (this->kalmanAmbiguousLayer(etaReg, layer) && layerStubs[layer + 1].empty()) { + } else if (this->kalmanAmbiguousLayer(etaReg, layer + 1) && layerStubs[layer + 1].empty()) { nextlay_stubs = layerStubs[layer + 2]; nSkippedAmbiguousLayers_nextStubs++; } else { @@ -343,19 +342,6 @@ namespace tmtt { new_states.insert(new_states.end(), next_states.begin(), next_states.end()); new_states.insert(new_states.end(), next_states_skipped.begin(), next_states_skipped.end()); - /* - i = 0; - for (auto state : next_states) { - new_states.push_back(state); - i++; - } - - i = 0; - for (auto state : next_states_skipped) { - new_states.push_back(state); - i++; - } -*/ } //end of state loop // copy new_states into prev_states for next iteration or end if we are on @@ -375,7 +361,7 @@ namespace tmtt { // We're done. prev_states.clear(); new_states.clear(); - + break; } else { // Continue iterating. prev_states = new_states; @@ -600,6 +586,8 @@ namespace tmtt { TVectorD delta = vd - hx; // Calculate higher order corrections to residuals. + // TO DO: Check if these could be determined using Tracklet/HT input track helix params, + // so only need applying at input to KF, instead of very iteration? if (not settings_->kalmanHOfw()) { TVectorD correction(2); @@ -618,6 +606,11 @@ namespace tmtt { deltaS = (1. / 6.) * (stub->r()) * pow(corr, 2); correction[1] -= deltaS * tanL; + + if (nHelixPar_ == 5) { + float d0 = vecX[D0]; + correction[0] += (1. / 6.) * pow(d0 / stub->r(), 3); // Division by r hard in FPGA? + } } if ((not stub->barrel()) && not(stub->psModule())) { @@ -689,33 +682,9 @@ namespace tmtt { unsigned int KFbase::kalmanLayer( unsigned int iEtaReg, unsigned int layerIDreduced, bool barrel, float r, float z) const { - // index across is GP encoded layer ID (where barrel layers=1,2,7,5,4,3 & endcap wheels=3,4,5,6,7 & 0 never occurs) - // index down is eta reg - // element is kalman layer, where 7 is invalid - - // If stub with given GP encoded layer ID can have different KF layer ID depending on whether it - // is barrel or endcap, then in layerMap, the the barrel case is assumed. - // The endcap case is fixed by hand later in this function. - - const unsigned int nEta = 16; - const unsigned int nGPlayID = 7; - - if (nEta != numEtaRegions_) + if (nEta_ != numEtaRegions_) throw cms::Exception("LogicError") - << "ERROR KFbase::getKalmanLayer hardwired value of nEta differs from NumEtaRegions cfg param"; - - // In cases where identical GP encoded layer ID present in this sector from both barrel & endcap, this array filled considering barrel. The endcap is fixed by subsequent code. - - constexpr unsigned layerMap[nEta / 2][nGPlayID + 1] = { - {7, 0, 1, 5, 4, 3, 7, 2}, // B1 B2 B3 B4 B5 B6 -- current FW - {7, 0, 1, 5, 4, 3, 7, 2}, // B1 B2 B3 B4 B5 B6 - {7, 0, 1, 5, 4, 3, 7, 2}, // B1 B2 B3 B4 B5 B6 - {7, 0, 1, 5, 4, 3, 7, 2}, // B1 B2 B3 B4 B5 B6 - {7, 0, 1, 5, 4, 3, 7, 2}, // B1 B2 B3 B4(/D3) B5(/D2) B6(/D1) - {7, 0, 1, 3, 4, 2, 6, 2}, // B1 B2 B3(/D5)+B4(/D3) D1 D2 X D4 - {7, 0, 1, 1, 2, 3, 4, 5}, // B1 B2+D1 D2 D3 D5 D6 - {7, 0, 7, 1, 2, 3, 4, 5}, // B1 D1 D2 D3 D4 D5 - }; + << "ERROR KFbase::getKalmanLayer hardwired value of nEta_ differs from NumEtaRegions cfg param"; unsigned int kfEtaReg; // KF VHDL eta sector def: small in barrel & large in endcap. if (iEtaReg < numEtaRegions_ / 2) { @@ -724,45 +693,15 @@ namespace tmtt { kfEtaReg = iEtaReg - numEtaRegions_ / 2; } - unsigned int kalmanLay = layerMap[kfEtaReg][layerIDreduced]; + unsigned int kalmanLay = + barrel ? layerMap_[kfEtaReg][layerIDreduced].first : layerMap_[kfEtaReg][layerIDreduced].second; - // Fixes to layermap when "maybe layer" used - if (settings_->kfUseMaybeLayers()) { + // Switch back to the layermap that is consistent with current FW when "maybe layer" is not used + if (not settings_->kfUseMaybeLayers()) { switch (kfEtaReg) { - case 5: //case 5: B1 B2 (B3+B4)* D1 D2 D3+D4 D5+D6 -- B3 is combined with B4 and is flagged as "maybe layer" - if (layerIDreduced == 6) { - kalmanLay = 5; - } - break; - case 6: //case 6: B1* B2* D1 D2 D3 D4 D5 -- B1 and B2 are flagged as "maybe layer" + case 6: //case 6: B1 B2+D1 D2 D3 D4 D5 if (layerIDreduced > 2) { - kalmanLay++; - } - break; - default: - break; - } - } - - // Fixes to endcap stubs, for cases where identical GP encoded layer ID present in this sector from both barrel & endcap. - - if (not barrel) { - switch (kfEtaReg) { - case 4: // B1 B2 B3 B4 B5/D1 B6/D2 D3 - if (layerIDreduced == 3) { - kalmanLay = 4; - } else if (layerIDreduced == 4) { - kalmanLay = 5; - } else if (layerIDreduced == 5) { - kalmanLay = 6; - } - break; - //case 5: // B1 B2 B3+B4 D1 D2 D3 D4/D5 - case 5: // B1 B2 B3 D1+B4 D2 D3 D4/D5 - if (layerIDreduced == 5) { - kalmanLay = 5; - } else if (layerIDreduced == 7) { - kalmanLay = 6; + kalmanLay--; } break; default: @@ -812,9 +751,7 @@ namespace tmtt { // Only helps in extreme forward sector, and there not significantly. // UNDERSTAND IF CAN BE USED ELSEWHERE. - const unsigned int nEta = 16; - const unsigned int nKFlayer = 7; - constexpr bool ambiguityMap[nEta / 2][nKFlayer] = { + constexpr bool ambiguityMap[nEta_ / 2][nKFlayer_] = { {false, false, false, false, false, false, false}, {false, false, false, false, false, false, false}, {false, false, false, false, false, false, false}, @@ -833,7 +770,7 @@ namespace tmtt { } bool ambiguous = false; - if (settings_->kfUseMaybeLayers() and kfLayer < nKFlayer) + if (settings_->kfUseMaybeLayers() && kfLayer < nKFlayer_) ambiguous = ambiguityMap[kfEtaReg][kfLayer]; return ambiguous; diff --git a/L1Trigger/TrackFindingTMTT/src/TrackerModule.cc b/L1Trigger/TrackFindingTMTT/src/TrackerModule.cc index 0c3650d8fc8b2..8f942e824a7d1 100644 --- a/L1Trigger/TrackFindingTMTT/src/TrackerModule.cc +++ b/L1Trigger/TrackFindingTMTT/src/TrackerModule.cc @@ -99,31 +99,6 @@ namespace tmtt { moduleTypeID_ = TrackerModule::calcModuleType(stripPitch_, sensorSpacing_, barrel_, tiltedBarrel_, psModule_); } - //=== Calculate reduced layer ID (in range 1-7), for packing into 3 bits to simplify the firmware. - - unsigned int TrackerModule::calcLayerIdReduced(unsigned int layerId) { - // Don't bother distinguishing two endcaps, as no track can have stubs in both. - unsigned int lay = (layerId < 20) ? layerId : layerId - 10; - - // No genuine track can have stubs in both barrel layer 6 and endcap disk 11 etc., so merge their layer IDs. - if (lay == 6) - lay = 11; - if (lay == 5) - lay = 12; - if (lay == 4) - lay = 13; - if (lay == 3) - lay = 15; - // At this point, the reduced layer ID can have values of 1, 2, 11, 12, 13, 14, 15. So correct to put in range 1-7. - if (lay > 10) - lay -= 8; - - if (lay < 1 || lay > 7) - throw cms::Exception("LogicError") << "TrackerModule: Reduced layer ID out of expected range"; - - return lay; - } - //=== Get module type ID defined by firmware. unsigned int TrackerModule::calcModuleType( diff --git a/L1Trigger/TrackFindingTMTT/test/tmtt_tf_analysis_cfg.py b/L1Trigger/TrackFindingTMTT/test/tmtt_tf_analysis_cfg.py index 706b9b5c3ff5f..628ce03bf8116 100644 --- a/L1Trigger/TrackFindingTMTT/test/tmtt_tf_analysis_cfg.py +++ b/L1Trigger/TrackFindingTMTT/test/tmtt_tf_analysis_cfg.py @@ -11,14 +11,18 @@ process = cms.Process("Demo") -GEOMETRY = "D49" - -if GEOMETRY == "D49": - process.load('Configuration.Geometry.GeometryExtended2026D49Reco_cff') - process.load('Configuration.Geometry.GeometryExtended2026D49_cff') +GEOMETRY = "D76" + +if GEOMETRY == "D49": + print("using geometry " + GEOMETRY + " (tilted)") + process.load('Configuration.Geometry.GeometryExtended2026D49Reco_cff') + process.load('Configuration.Geometry.GeometryExtended2026D49_cff') +elif GEOMETRY == "D76": + print("using geometry " + GEOMETRY + " (tilted)") + process.load('Configuration.Geometry.GeometryExtended2026D76Reco_cff') + process.load('Configuration.Geometry.GeometryExtended2026D76_cff') else: - print "this is not a valid geometry!!!" - exit + print("this is not a valid geometry!!!") process.load('Configuration.StandardSequences.MagneticField_cff') process.load('Configuration.StandardSequences.FrontierConditions_GlobalTag_cff') @@ -32,15 +36,18 @@ #--- Specify input MC -#--- To use MCsamples scripts, defining functions get*data*(), -#--- follow instructions https://cernbox.cern.ch/index.php/s/enCnnfUZ4cpK7mT +#--- To use MCsamples scripts, defining functions get*data*() for easy MC access, +#--- follow instructions in https://github.com/cms-L1TK/MCsamples #from MCsamples.Scripts.getCMSdata_cfi import * #from MCsamples.Scripts.getCMSlocaldata_cfi import * if GEOMETRY == "D49": + inputMC = ["/store/relval/CMSSW_11_3_0_pre3/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v3_2026D49PU200_rsb-v1/00000/00260a30-734a-4a3a-a4b0-f836ce5502c6.root"] + +elif GEOMETRY == "D76": # Read data from card files (defines getCMSdataFromCards()): - #from MCsamples.RelVal_1120.PU200_TTbar_14TeV_cfi import * + #from MCsamples.RelVal_1130_D76.PU200_TTbar_14TeV_cfi import * #inputMC = getCMSdataFromCards() # Or read .root files from directory on local computer: @@ -48,11 +55,15 @@ #inputMC=getCMSlocaldata(dirName) # Or read specified dataset (accesses CMS DB, so use this method only occasionally): - #dataName="/RelValTTbar_14TeV/CMSSW_11_2_0_pre5-PU25ns_110X_mcRun4_realistic_v3_2026D49PU200-v1/GEN-SIM-DIGI-RAW" + #dataName="/RelValTTbar_14TeV/CMSSW_11_3_0_pre6-PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/GEN-SIM-DIGI-RAW" #inputMC=getCMSdata(dataName) # Or read specified .root file: - inputMC = ["/store/relval/CMSSW_11_2_0_pre5/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU25ns_110X_mcRun4_realistic_v3_2026D49PU200-v1/20000/FDFA00CE-FA93-0142-B187-99CBD4A43944.root"] + inputMC = ["/store/relval/CMSSW_11_3_0_pre6/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/00000/00026541-6200-4eed-b6f8-d3a1fd720e9c.root"] + +else: + print("this is not a valid geometry!!!") + #--- Specify number of events to process. options.register('Events',100,VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.int,"Number of Events to analyze") @@ -108,9 +119,9 @@ # Optionally (re)make the stubs on the fly if options.makeStubs == 1: - process.load('L1Trigger.TrackTrigger.TrackTrigger_cff') - process.load('SimTracker.TrackTriggerAssociation.TrackTriggerAssociator_cff') - process.TTClusterAssociatorFromPixelDigis.digiSimLinks = cms.InputTag("simSiPixelDigis","Tracker") + process.load('L1Trigger.TrackTrigger.TrackTrigger_cff') + process.load('SimTracker.TrackTriggerAssociation.TrackTriggerAssociator_cff') + process.TTClusterAssociatorFromPixelDigis.digiSimLinks = cms.InputTag("simSiPixelDigis","Tracker") LOOSE_STUBS = False @@ -168,7 +179,7 @@ ) ) - process.p = cms.Path(process.TrackTriggerClustersStubs * process.TrackTriggerAssociatorClustersStubs * process.TMTrackProducer) + process.p = cms.Path(process.TrackTriggerClustersStubs * process.TrackTriggerAssociatorClustersStubs * process.TMTrackProducer) # Optionally create output GEN-SIM-DIGI-RAW dataset containing TMTT L1 tracks & associators. if options.outputDataset == 1: diff --git a/L1Trigger/TrackFindingTracklet/BuildFile.xml b/L1Trigger/TrackFindingTracklet/BuildFile.xml index 9ca0665e2be06..f5666d006fdf3 100644 --- a/L1Trigger/TrackFindingTracklet/BuildFile.xml +++ b/L1Trigger/TrackFindingTracklet/BuildFile.xml @@ -7,6 +7,7 @@ + diff --git a/L1Trigger/TrackFindingTracklet/interface/ChannelAssignment.h b/L1Trigger/TrackFindingTracklet/interface/ChannelAssignment.h new file mode 100644 index 0000000000000..6e36345a07550 --- /dev/null +++ b/L1Trigger/TrackFindingTracklet/interface/ChannelAssignment.h @@ -0,0 +1,89 @@ +#ifndef L1Trigger_TrackFindingTracklet_ChannelAssignment_h +#define L1Trigger_TrackFindingTracklet_ChannelAssignment_h + +#include "FWCore/Framework/interface/data_default_record_trait.h" +#include "L1Trigger/TrackFindingTracklet/interface/ChannelAssignmentRcd.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "DataFormats/L1TrackTrigger/interface/TTTypes.h" +#include "L1Trigger/TrackTrigger/interface/Setup.h" + +#include + +namespace trklet { + + /*! \class trklet::ChannelAssignment + * \brief Class to assign tracklet tracks and stubs to output channel + * based on their Pt or seed type as well as DTC stubs to input channel + * \author Thomas Schuh + * \date 2020, Nov; updated 2021 Oct + */ + class ChannelAssignment { + public: + ChannelAssignment() {} + ChannelAssignment(const edm::ParameterSet& iConfig, const tt::Setup* setup); + ~ChannelAssignment() {} + // sets channelId of given TTTrackRef from TrackBuilder or PurgeDuplicate (if enabled), return false if track outside pt range + bool channelId(const TTTrackRef& ttTrackRef, int& channelId); + // number of used channels for tracks + int numChannelsTrack() const { return numChannelsTrack_; } + // number of used channels for stubs + int numChannelsStub() const { return numChannelsStub_; } + // number of used seed types in tracklet algorithm + int numSeedTypes() const { return numSeedTypes_; } + // sets layerId (0-7 in sequence the seed type projects to) of given TTStubRef and seedType, returns false if seeed stub + bool layerId(int seedType, const TTStubRef& ttStubRef, int& layerId) const; + // return tracklet layerId (barrel: [0-5], endcap: [6-10]) for given TTStubRef + int trackletLayerId(const TTStubRef& ttStubRef) const; + // number layers a given seed type projects to + int numProjectionLayers(int seedType) const { return (int)seedTypesProjectionLayers_.at(seedType).size(); } + // max. no. layers that any seed type projects to + int maxNumProjectionLayers() const { return maxNumProjectionLayers_; } + // map of used DTC tfp channels in InputRouter + const std::vector& channelEncoding() const { return channelEncoding_; } + // index of first stub channel belonging to given track channel + int offsetStub(int channelTrack) const; + // seed layers for given seed type id + const std::vector& seedingLayers(int seedType) const { return seedTypesSeedLayers_.at(seedType); } + // + tt::SensorModule::Type type(const TTStubRef& ttStubRef) const { return setup_->type(ttStubRef); } + // + int layerId(int seedType, int channel) const { return seedTypesProjectionLayers_.at(seedType).at(channel); } + // + int channelId(int seedType, int layerId) const; + // max number of seeding layers + int numSeedingLayers() const { return numSeedingLayers_; } + + private: + // helper class to store configurations + const tt::Setup* setup_; + // use tracklet seed type as channel id if False, binned track pt used if True + bool useDuplicateRemoval_; + // pt Boundaries in GeV, last boundary is infinity + std::vector boundaries_; + // seed type names + std::vector seedTypeNames_; + // number of used seed types in tracklet algorithm + int numSeedTypes_; + // number of used channels for tracks + int numChannelsTrack_; + // number of used channels for stubs + int numChannelsStub_; + // seeding layers of seed types using default layer id [barrel: 1-6, discs: 11-15] + std::vector> seedTypesSeedLayers_; + // layers a seed types can project to using default layer id [barrel: 1-6, discs: 11-15] + std::vector> seedTypesProjectionLayers_; + // max. number of layers to which any seed type projects + int maxNumProjectionLayers_; + // map of used DTC tfp channels in InputRouter + std::vector channelEncoding_; + // accumulated number of projections layer from seed 0 to vector index + std::vector offsetsStubs_; + // max number of seeding layers + int numSeedingLayers_; + }; + +} // namespace trklet + +EVENTSETUP_DATA_DEFAULT_RECORD(trklet::ChannelAssignment, trklet::ChannelAssignmentRcd); + +#endif diff --git a/L1Trigger/TrackFindingTracklet/interface/ChannelAssignmentRcd.h b/L1Trigger/TrackFindingTracklet/interface/ChannelAssignmentRcd.h new file mode 100644 index 0000000000000..576ef813ac105 --- /dev/null +++ b/L1Trigger/TrackFindingTracklet/interface/ChannelAssignmentRcd.h @@ -0,0 +1,17 @@ +#ifndef L1Trigger_TrackFindingTracklet_ChannelAssignmentRcd_h +#define L1Trigger_TrackFindingTracklet_ChannelAssignmentRcd_h + +#include "FWCore/Framework/interface/DependentRecordImplementation.h" +#include "FWCore/Utilities/interface/mplVector.h" +#include "L1Trigger/TrackTrigger/interface/SetupRcd.h" + +namespace trklet { + + typedef edm::mpl::Vector RcdsChannelAssignment; + + class ChannelAssignmentRcd + : public edm::eventsetup::DependentRecordImplementation {}; + +} // namespace trklet + +#endif \ No newline at end of file diff --git a/L1Trigger/TrackFindingTracklet/interface/FitTrack.h b/L1Trigger/TrackFindingTracklet/interface/FitTrack.h index e72c4cf664132..50b4584d0d853 100644 --- a/L1Trigger/TrackFindingTracklet/interface/FitTrack.h +++ b/L1Trigger/TrackFindingTracklet/interface/FitTrack.h @@ -5,15 +5,16 @@ #include "L1Trigger/TrackFindingTracklet/interface/TrackletParametersMemory.h" #include "L1Trigger/TrackFindingTracklet/interface/FullMatchMemory.h" #include "L1Trigger/TrackFindingTracklet/interface/TrackFitMemory.h" +#include "L1Trigger/TrackFindingTracklet/interface/StubStreamData.h" #include +#include namespace trklet { class Settings; class Globals; class Stub; - class L1TStub; class FitTrack : public ProcessBase { public: @@ -38,7 +39,9 @@ namespace trklet { std::vector orderedMatches(std::vector& fullmatch); - void execute(unsigned int iSector); + void execute(std::deque& streamTrackRaw, + std::vector>& stubStream, + unsigned int iSector); private: std::vector seedtracklet_; diff --git a/L1Trigger/TrackFindingTracklet/interface/HybridFit.h b/L1Trigger/TrackFindingTracklet/interface/HybridFit.h index 5ca9437e8189e..2a07ce6cdf134 100644 --- a/L1Trigger/TrackFindingTracklet/interface/HybridFit.h +++ b/L1Trigger/TrackFindingTracklet/interface/HybridFit.h @@ -7,8 +7,6 @@ #ifdef USEHYBRID #include "DataFormats/L1TrackTrigger/interface/TTStub.h" #include "DataFormats/L1TrackTrigger/interface/TTCluster.h" -#include "SimTracker/TrackTriggerAssociation/interface/TTStubAssociationMap.h" -#include "SimTracker/TrackTriggerAssociation/interface/TTClusterAssociationMap.h" #include "L1Trigger/TrackFindingTMTT/interface/L1track3D.h" #include "L1Trigger/TrackFindingTMTT/interface/Stub.h" #include "L1Trigger/TrackFindingTMTT/interface/KFParamsComb.h" diff --git a/L1Trigger/TrackFindingTracklet/interface/KFin.h b/L1Trigger/TrackFindingTracklet/interface/KFin.h new file mode 100644 index 0000000000000..63d9a05a216d1 --- /dev/null +++ b/L1Trigger/TrackFindingTracklet/interface/KFin.h @@ -0,0 +1,143 @@ +#ifndef L1Trigger_TrackFindingTracklet_KFin_h +#define L1Trigger_TrackFindingTracklet_KFin_h + +#include "L1Trigger/TrackTrigger/interface/Setup.h" +#include "L1Trigger/TrackerTFP/interface/DataFormats.h" +#include "L1Trigger/TrackerTFP/interface/LayerEncoding.h" +#include "L1Trigger/TrackFindingTracklet/interface/ChannelAssignment.h" +#include "L1Trigger/TrackFindingTracklet/interface/Settings.h" + +#include + +namespace trklet { + + /*! \class trklet::KFin + * \brief Class to emulate transformation of tracklet tracks and stubs into TMTT format + * \author Thomas Schuh + * \date 2021, Dec + */ + class KFin { + public: + KFin(const edm::ParameterSet& iConfig, + const tt::Setup* setup_, + const trackerTFP::DataFormats* dataFormats, + const trackerTFP::LayerEncoding* layerEncoding, + const ChannelAssignment* channelAssignment, + const Settings* settings, + int region); + ~KFin() {} + + // read in and organize input tracks and stubs + void consume(const tt::StreamsTrack& streamsTrack, const tt::StreamsStub& streamsStub); + // fill output products + void produce(tt::StreamsStub& accpetedStubs, + tt::StreamsTrack& acceptedTracks, + tt::StreamsStub& lostStubs, + tt::StreamsTrack& lostTracks); + + private: + // truncates double precision of val into base precision, +1.e-12 restores robustness of addition of 2 digitised values + double digi(double val, double base) const { return (floor(val / base + 1.e-12) + .5) * base; } + // basetransformation of val from baseLow into baseHigh using widthMultiplier bit multiplication + double redigi(double val, double baseLow, double baseHigh, int widthMultiplier) const; + struct Stub { + Stub(const TTStubRef& ttStubRef, int layer, double r, double phi, double z, bool psTilt) + : valid_(true), ttStubRef_(ttStubRef), layer_(layer), r_(r), phi_(phi), z_(z), psTilt_(psTilt) {} + bool valid_; + TTStubRef ttStubRef_; + int layer_; + // radius w.r.t. chosenRofPhi in cm + double r_; + // phi residual in rad + double phi_; + // z residual in cm + double z_; + // phi uncertainty * sqrt(12) + additional terms in rad + double dPhi_; + // z uncertainty * sqrt(12) + additional terms in cm + double dZ_; + // true if barrel tilted module or encap PS module + bool psTilt_; + }; + struct Track { + static constexpr int max_ = 8; + Track() { stubs_.reserve(max_); } + Track(const TTTrackRef& ttTrackRef, + bool valid, + double inv2R, + double phiT, + double cot, + double zT, + const std::vector& stubs) + : ttTrackRef_(ttTrackRef), + valid_(valid), + sector_(-1), + inv2R_(inv2R), + phiT_(phiT), + cot_(cot), + zT_(zT), + stubs_(stubs) {} + TTTrackRef ttTrackRef_; + bool valid_; + TTBV maybe_; + int sector_; + double inv2R_; + double phiT_; + double cot_; + double zT_; + std::vector stubs_; + }; + + // true if truncation is enbaled + bool enableTruncation_; + // stub residuals are recalculated from seed parameter and TTStub position + bool useTTStubResiduals_; + // provides run-time constants + const tt::Setup* setup_; + // provides dataformats + const trackerTFP::DataFormats* dataFormats_; + // helper class to encode layer + const trackerTFP::LayerEncoding* layerEncoding_; + // helper class to assign tracks to channel + const ChannelAssignment* channelAssignment_; + // provides tracklet constants + const Settings* settings_; + // processing region (0 - 8) aka processing phi nonant + const int region_; + // storage of input tracks + std::vector tracks_; + // storage of input stubs + std::vector stubs_; + // h/w liked organized pointer to input tracks + std::vector> input_; + // unified tracklet digitisation granularity + double baseUinv2R_; + double baseUphiT_; + double baseUcot_; + double baseUzT_; + double baseUr_; + double baseUphi_; + double baseUz_; + // KF input format digitisation granularity (identical to TMTT) + double baseLinv2R_; + double baseLphiT_; + double baseLcot_; + double baseLzT_; + double baseLr_; + double baseLphi_; + double baseLz_; + // Finer granularity (by powers of 2) than the TMTT one. Used to transform from Tracklet to TMTT base. + double baseHinv2R_; + double baseHphiT_; + double baseHcot_; + double baseHzT_; + double baseHr_; + double baseHphi_; + double baseHz_; + // digitisation granularity used for inverted cot(theta) + double baseInvCot_; + }; + +} // namespace trklet + +#endif diff --git a/L1Trigger/TrackFindingTracklet/interface/L1TStub.h b/L1Trigger/TrackFindingTracklet/interface/L1TStub.h index 95a85bdaf4f1a..2a5f0e01732ee 100644 --- a/L1Trigger/TrackFindingTracklet/interface/L1TStub.h +++ b/L1Trigger/TrackFindingTracklet/interface/L1TStub.h @@ -21,6 +21,10 @@ namespace trklet { std::string stubword, int isPSmodule, int isFlipped, + bool tiltedBarrel, + unsigned int tiltedRingId, + unsigned int endcapRingId, + unsigned int detId, double x, double y, double z, @@ -49,8 +53,6 @@ namespace trklet { } return disk; } - unsigned int ladder() const { return ladder_; } - unsigned int module() const { return module_; } double x() const { return x_; } double y() const { return y_; } @@ -94,7 +96,13 @@ namespace trklet { unsigned int isPSmodule() const { return isPSmodule_; } unsigned int isFlipped() const { return isFlipped_; } - bool isTilted() const; + bool isTilted() const { return tiltedBarrel_; } // Tilted barrel + + // Tilted module ring no. (Increasing 1 to 12 as |z| increases). + unsigned int tiltedRingId() const { return tiltedRingId_; } + // Endcap disk module ring number (1-15 as r increases). + unsigned int endcapRingId() const { return endcapRingId_; } + unsigned int detId() const { return detId_; } // Of lower sensor in module bool tpmatch(int tp) const; bool tpmatch2(int tp) const; @@ -117,8 +125,6 @@ namespace trklet { unsigned int iphi_; unsigned int iz_; unsigned int layer_; - unsigned int ladder_; - unsigned int module_; unsigned int strip_; double x_; double y_; @@ -128,9 +134,12 @@ namespace trklet { double pt_; double bend_; unsigned int allstubindex_; - unsigned int isPSmodule_; unsigned int isFlipped_; + bool tiltedBarrel_; + unsigned int tiltedRingId_; + unsigned int endcapRingId_; + unsigned int detId_; }; }; // namespace trklet #endif diff --git a/L1Trigger/TrackFindingTracklet/interface/MatchCalculator.h b/L1Trigger/TrackFindingTracklet/interface/MatchCalculator.h index 3c8a0a6bd0165..82459b8c3925f 100644 --- a/L1Trigger/TrackFindingTracklet/interface/MatchCalculator.h +++ b/L1Trigger/TrackFindingTracklet/interface/MatchCalculator.h @@ -28,7 +28,7 @@ namespace trklet { void addOutput(MemoryBase* memory, std::string output) override; void addInput(MemoryBase* memory, std::string input) override; - void execute(double phioffset); + void execute(unsigned int iSector, double phioffset); std::vector, const Stub*> > mergeMatches( std::vector& candmatch); diff --git a/L1Trigger/TrackFindingTracklet/interface/MatchEngine.h b/L1Trigger/TrackFindingTracklet/interface/MatchEngine.h index 58d667de2f310..10b76d002169b 100644 --- a/L1Trigger/TrackFindingTracklet/interface/MatchEngine.h +++ b/L1Trigger/TrackFindingTracklet/interface/MatchEngine.h @@ -23,7 +23,7 @@ namespace trklet { void addOutput(MemoryBase* memory, std::string output) override; void addInput(MemoryBase* memory, std::string input) override; - void execute(); + void execute(unsigned int iSector); private: VMStubsMEMemory* vmstubs_; diff --git a/L1Trigger/TrackFindingTracklet/interface/MatchEngineUnit.h b/L1Trigger/TrackFindingTracklet/interface/MatchEngineUnit.h index f4d448f4d9026..6aad8567e0a0f 100644 --- a/L1Trigger/TrackFindingTracklet/interface/MatchEngineUnit.h +++ b/L1Trigger/TrackFindingTracklet/interface/MatchEngineUnit.h @@ -1,3 +1,12 @@ +/**************************************************************** + * MatchEngineUnit (MEU) is a single instance of the MatchEngine + * section of the MatchProcessor (MP) + * + * Manual pipelining is implemented to properly emulate the HLS + * implementation (required to meet II=1) + * + * A total of `nMatchEngines_` MEUs are used in the MP + ****************************************************************/ #ifndef L1Trigger_TrackFindingTracklet_interface_MatchEngineUnit_h #define L1Trigger_TrackFindingTracklet_interface_MatchEngineUnit_h @@ -18,7 +27,7 @@ namespace trklet { class MatchEngineUnit { public: - MatchEngineUnit(bool barrel, unsigned int layerdisk, const TrackletLUT& luttable); + MatchEngineUnit(const Settings& settings, bool barrel, unsigned int layerdisk, const TrackletLUT& luttable); ~MatchEngineUnit() = default; @@ -35,8 +44,7 @@ namespace trklet { bool usesecondMinus, bool usesecondPlus, bool isPSseed, - Tracklet* proj, - bool print); + Tracklet* proj); bool empty() const { return candmatches_.empty(); } @@ -46,24 +54,29 @@ namespace trklet { std::pair peek() const { return candmatches_.peek(); } - Tracklet* currentProj() const { return proj_; } - bool idle() const { return idle_; } - bool active() const { return !idle_ || goodpair_ || goodpair__ || !empty(); } + bool active() const { return !idle_ || good__ || good___ || !empty(); } + + void setAlmostFull(); - //needed for consistency with HLS FW version ("_" vs "__" indicating different pipelining stages) - bool have_() const { return havepair_; } - bool have__() const { return havepair__; } + void setimeu(int imeu) { imeu_ = imeu; } + + void setprint(bool print) { print_ = print; } void reset(); unsigned int rptr() const { return candmatches_.rptr(); } unsigned int wptr() const { return candmatches_.wptr(); } - void step(bool print); + void step(); + + void processPipeline(); private: + //Provide access to constants + const Settings& settings_; + VMStubsMEMemory* vmstubsmemory_; unsigned int nrzbins_; @@ -86,16 +99,29 @@ namespace trklet { unsigned int layerdisk_; + //Save state at the start of istep + bool almostfullsave_; + //LUT for bend consistency with rinv const TrackletLUT& luttable_; - //Pipeline variables - std::pair tmppair_, tmppair__; - bool goodpair_, goodpair__; - bool havepair_, havepair__; + //Various manually pipelined variables + //Each _ represents a layer of pipelining + //e.g., good__ is set and one iteration later good___ is updated + VMStubME vmstub__, vmstub___; + bool isPSseed__, isPSseed___; + bool good__, good___; + int projfinerz__, projfinerz___; + int projfinephi__, projfinephi___; + int projrinv__, projrinv___; + Tracklet *proj__, *proj___; //save the candidate matches CircularBuffer> candmatches_; + + //debugging help + int imeu_; + bool print_; }; }; // namespace trklet diff --git a/L1Trigger/TrackFindingTracklet/interface/MemoryBase.h b/L1Trigger/TrackFindingTracklet/interface/MemoryBase.h index ca0280bff8911..9c806137f85ef 100644 --- a/L1Trigger/TrackFindingTracklet/interface/MemoryBase.h +++ b/L1Trigger/TrackFindingTracklet/interface/MemoryBase.h @@ -32,13 +32,16 @@ namespace trklet { // extended is the seeding for displaced tracks void initSpecialSeeding(unsigned int pos, bool& overlap, bool& extra, bool& extended); - //Used for a hack below due to MAC OS case sensitiviy problem for files + //Used for a hack below due to MAC OS case insensitiviy problem for files void findAndReplaceAll(std::string& data, std::string toSearch, std::string replaceStr); void openFile(bool first, std::string dirName, std::string filebase); static size_t find_nth(const std::string& haystack, size_t pos, const std::string& needle, size_t nth); + //Format index position in hex + static std::string hexstr(unsigned int index); + protected: std::string name_; unsigned int iSector_; diff --git a/L1Trigger/TrackFindingTracklet/interface/PurgeDuplicate.h b/L1Trigger/TrackFindingTracklet/interface/PurgeDuplicate.h index 6600a3de15d98..7909efdbeb72d 100644 --- a/L1Trigger/TrackFindingTracklet/interface/PurgeDuplicate.h +++ b/L1Trigger/TrackFindingTracklet/interface/PurgeDuplicate.h @@ -7,6 +7,13 @@ #include +// Run algorithm to remove duplicate tracks. +// Returns Track object that represent output at end of L1 track chain, +// (and are later converted to TTTrack). Duplicate Track objects are flagged, +// but only deleted if using the Hybrid algo. +// Also writes to memory the same tracks in more detailed Tracklet format, +// where duplicates are all deleted. + namespace trklet { class Settings; diff --git a/L1Trigger/TrackFindingTracklet/interface/SLHCEvent.h b/L1Trigger/TrackFindingTracklet/interface/SLHCEvent.h index 74dfc0d22d3fd..444767154ffc6 100644 --- a/L1Trigger/TrackFindingTracklet/interface/SLHCEvent.h +++ b/L1Trigger/TrackFindingTracklet/interface/SLHCEvent.h @@ -1,4 +1,7 @@ -// This holds two classes: L1SimTrack (truth level simulated track), and SLHCEvent (support for maintaining standalone running) +// This class stores all the L1SimTracks (truth-level simulated track) +// & reconstructed stubs using CMSSW independent containers, +// to support standalone running. + #ifndef L1Trigger_TrackFindingTracklet_interface_SLHCEvent_h #define L1Trigger_TrackFindingTracklet_interface_SLHCEvent_h @@ -34,12 +37,16 @@ namespace trklet { std::string stubword, int isPSmodule, int isFlipped, + bool tiltedBarrel, + unsigned int tiltedRingId, + unsigned int endcapRingId, + unsigned int detId, double x, double y, double z, double bend, double strip, - std::vector tps); + std::vector tpstt); const L1TStub& lastStub() const { return stubs_.back(); } diff --git a/L1Trigger/TrackFindingTracklet/interface/Sector.h b/L1Trigger/TrackFindingTracklet/interface/Sector.h index ab3d67bdb39e7..eb724e2d003c7 100644 --- a/L1Trigger/TrackFindingTracklet/interface/Sector.h +++ b/L1Trigger/TrackFindingTracklet/interface/Sector.h @@ -4,6 +4,7 @@ #include "L1Trigger/TrackFindingTracklet/interface/L1TStub.h" #include "L1Trigger/TrackFindingTracklet/interface/SLHCEvent.h" +#include "L1Trigger/TrackFindingTracklet/interface/StubStreamData.h" #include #include @@ -50,6 +51,7 @@ namespace trklet { class TripletEngine; class TrackletCalculator; class TrackletProcessor; + class TrackletProcessorDisplaced; class TrackletCalculatorDisplaced; class ProjectionRouter; class MatchEngine; @@ -108,13 +110,15 @@ namespace trklet { void executeTED(); void executeTRE(); void executeTP(); + void executeTPD(); void executeTC(); void executeTCD(); void executePR(); void executeME(); void executeMC(); void executeMP(); - void executeFT(); + void executeFT(std::vector>& streamsTrackRaw, + std::vector>& streamsStubRaw); void executePD(std::vector& tracks); std::vector getAllTracklets() const; @@ -126,14 +130,14 @@ namespace trklet { double phimax() const { return phimax_; } template - void addMemToVec(std::vector >& memvec, const std::string& memName, Args&... args) { + void addMemToVec(std::vector>& memvec, const std::string& memName, Args&... args) { memvec.push_back(std::make_unique(memName, std::forward(args)...)); Memories_[memName] = memvec.back().get(); MemoriesV_.push_back(memvec.back().get()); } template - void addProcToVec(std::vector >& procvec, const std::string& procName, Args&... args) { + void addProcToVec(std::vector>& procvec, const std::string& procName, Args&... args) { procvec.push_back(std::make_unique(procName, std::forward(args)...)); Processes_[procName] = procvec.back().get(); } @@ -147,39 +151,40 @@ namespace trklet { std::map Memories_; std::vector MemoriesV_; - std::vector > DL_; - std::vector > IL_; - std::vector > AS_; - std::vector > AIS_; - std::vector > VMSTE_; - std::vector > VMSME_; - std::vector > SP_; - std::vector > ST_; - std::vector > TPAR_; - std::vector > TPROJ_; - std::vector > AP_; - std::vector > VMPROJ_; - std::vector > CM_; - std::vector > FM_; - std::vector > TF_; - std::vector > CT_; + std::vector> DL_; + std::vector> IL_; + std::vector> AS_; + std::vector> AIS_; + std::vector> VMSTE_; + std::vector> VMSME_; + std::vector> SP_; + std::vector> ST_; + std::vector> TPAR_; + std::vector> TPROJ_; + std::vector> AP_; + std::vector> VMPROJ_; + std::vector> CM_; + std::vector> FM_; + std::vector> TF_; + std::vector> CT_; std::map Processes_; - std::vector > IR_; - std::vector > VMR_; - std::vector > VMRCM_; - std::vector > TE_; - std::vector > TED_; - std::vector > TRE_; - std::vector > TP_; - std::vector > TC_; - std::vector > TCD_; - std::vector > PR_; - std::vector > ME_; - std::vector > MC_; - std::vector > MP_; - std::vector > FT_; - std::vector > PD_; + std::vector> IR_; + std::vector> VMR_; + std::vector> VMRCM_; + std::vector> TE_; + std::vector> TED_; + std::vector> TRE_; + std::vector> TP_; + std::vector> TPD_; + std::vector> TC_; + std::vector> TCD_; + std::vector> PR_; + std::vector> ME_; + std::vector> MC_; + std::vector> MP_; + std::vector> FT_; + std::vector> PD_; }; }; // namespace trklet #endif diff --git a/L1Trigger/TrackFindingTracklet/interface/Settings.h b/L1Trigger/TrackFindingTracklet/interface/Settings.h index e46e94b109386..41fe380fac2c8 100644 --- a/L1Trigger/TrackFindingTracklet/interface/Settings.h +++ b/L1Trigger/TrackFindingTracklet/interface/Settings.h @@ -118,7 +118,7 @@ namespace trklet { throw cms::Exception("BadConfig") << __FILE__ << " " << __LINE__ << " maxStep module = " << module << " not known"; } - return maxstep_.at(module) + maxstepoffset_; + return extended_ ? (maxstep_.at(module) + maxstepoffset_extended_) : (maxstep_.at(module) + maxstepoffset_); } double zlength() const { return zlength_; } @@ -224,9 +224,10 @@ namespace trklet { unsigned int maxStubsPerBin() const { return maxStubsPerBin_; } std::string geomext() const { + std::string geo = extended_ ? "hourglassExtended" : "hourglass"; if (combined_) - return "hourglassCombined"; - return extended_ ? "hourglassExtended" : "hourglass"; + geo += "Combined"; + return geo; } bool exactderivatives() const { return exactderivatives_; } @@ -240,6 +241,13 @@ namespace trklet { bool doKF() const { return doKF_; } bool doMultipleMatches() const { return doMultipleMatches_; } bool fakefit() const { return fakefit_; } + void setFakefit(bool fakefit) { fakefit_ = fakefit; } + bool storeTrackBuilderOutput() const { return storeTrackBuilderOutput_; } + void setStoreTrackBuilderOutput(bool storeTrackBuilderOutput) { + storeTrackBuilderOutput_ = storeTrackBuilderOutput; + } + void setRemovalType(std::string removalType) { removalType_ = removalType; } + void setDoMultipleMatches(bool doMultipleMatches) { doMultipleMatches_ = doMultipleMatches; } // configurable unsigned int nHelixPar() const { return nHelixPar_; } @@ -249,6 +257,8 @@ namespace trklet { void setExtended(bool extended) { extended_ = extended; } bool combined() const { return combined_; } void setCombined(bool combined) { combined_ = combined; } + bool reduced() const { return reduced_; } + void setReduced(bool reduced) { reduced_ = reduced; } double bfield() const { return bfield_; } void setBfield(double bfield) { bfield_ = bfield; } @@ -278,6 +288,7 @@ namespace trklet { void setNbitsseed(unsigned int nbitsseed) { nbitsseed_ = nbitsseed; } void setNbitsseedextended(unsigned int nbitsseed) { nbitsseedextended_ = nbitsseed; } + // Phi width of nonant including overlaps (at widest point). double dphisectorHG() const { //These values are used in the DTC emulation code. double rsectmin = 21.8; @@ -295,6 +306,7 @@ namespace trklet { double phicritminmc() const { return phicritmin() - dphicritmc_; } double phicritmaxmc() const { return phicritmax() + dphicritmc_; } + // Stub digitization granularities double kphi() const { return dphisectorHG() / (1 << nphibitsstub(0)); } double kphi1() const { return dphisectorHG() / (1 << nphibitsstub(N_LAYER - 1)); } double kphi(unsigned int layerdisk) const { return dphisectorHG() / (1 << nphibitsstub(layerdisk)); } @@ -380,6 +392,7 @@ namespace trklet { int chisqphifactbits() const { return chisqphifactbits_; } int chisqzfactbits() const { return chisqzfactbits_; } + // Helix param digisation granularities //0.02 here is the maximum range in rinv values that can be represented double krinvpars() const { int shift = ceil(-log2(0.02 * rmaxdisk_ / ((1 << nbitsrinv_) * dphisectorHG()))); @@ -409,7 +422,7 @@ namespace trklet { double bendcut(int ibend, int layerdisk, bool isPSmodule) const { if (layerdisk >= N_LAYER && (!isPSmodule)) - layerdisk += (N_LAYER - 1); + layerdisk += N_DISK; double bendcut = bendcut_[layerdisk][ibend]; if (bendcut <= 0.0) std::cout << "bendcut : " << layerdisk << " " << ibend << " " << isPSmodule << std::endl; @@ -417,6 +430,10 @@ namespace trklet { return bendcut; } + // DTC in given ATCA crate slot. + std::string slotToDTCname(unsigned int slot) const { return slotToDTCname_.at(slot); } + + // Tracker layers read by given DTC. const std::vector& dtcLayers(const std::string& dtcName) const { auto iter = dtclayers_.find(dtcName); assert(iter != dtclayers_.end()); @@ -426,11 +443,20 @@ namespace trklet { double bendcutte(int ibend, int layerdisk, bool isPSmodule) const { return bendcut(ibend, layerdisk, isPSmodule); } double bendcutme(int ibend, int layerdisk, bool isPSmodule) const { - //FIXME temporary fix until phiprojderdisk bits adjusted. But requires coordinatin with HLS + //Should understand why larger cut needed in disks double fact = (layerdisk < N_LAYER) ? 1.0 : 1.8; return fact * bendcut(ibend, layerdisk, isPSmodule); } + //layers/disks used by each seed + std::array, N_SEED> seedlayers() const { return seedlayers_; } + + //projection layers by seed index. For each seeding index (row) the list of layers that we consider projections to + std::array, N_SEED> projlayers() const { return projlayers_; } + + //projection disks by seed index. For each seeding index (row) the list of diks that we consider projections to + std::array, N_SEED> projdisks() const { return projdisks_; } + private: std::string fitPatternFile_; std::string processingModulesFile_; @@ -477,6 +503,11 @@ namespace trklet { {{3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2}}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1}}}}; + // FIX: There should be 3 PS10G slots & 3 PS (5G) ones. + // (Will change output files used by HLS). + std::vector slotToDTCname_{ + "PS10G_1", "PS10G_2", "PS10G_3", "PS10G_4", "PS_1", "PS_2", "2S_1", "2S_2", "2S_3", "2S_4", "2S_5", "2S_6"}; + std::map > dtclayers_{{"PS10G_1", {0, 6, 8, 10}}, {"PS10G_2", {0, 7, 9}}, {"PS10G_3", {1, 7}}, @@ -520,6 +551,7 @@ namespace trklet { double ptcutte_{1.8}; //Minimum pt in TE + // VALUE AUTOMATICALLY INCREASED FOR EXTENDED TRACKING BY PYTHON CFG unsigned int nbitstrackletindex_{7}; //Bits used to store the tracklet index unsigned int nbitsitc_{4}; //Bits used to store the iTC, a unique @@ -603,14 +635,23 @@ namespace trklet { {{5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4}}, //outer {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4}}}}; //outermost (triplets only) + // These are the number of bits to represent lutval for VM memories in TE std::array, 3> lutwidthtab_{{{{10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 11, 0}}, {{6, 6, 6, 6, 10, 10, 10, 10, 0, 0, 6, 0}}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 6}}}}; + // These are the number of bits to represent lutval for VM memories in TED + // TO DO: tune lutwidthtabextended_ values + + /* std::array, 3> lutwidthtabextended_{ */ + /* {{{11, 11, 21, 21, 21, 21, 11, 11, 0, 0, 21, 0}}, */ + /* {{6, 6, 6, 6, 10, 10, 10, 10, 0, 0, 6, 0}}, */ + /* {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6}}}}; */ + std::array, 3> lutwidthtabextended_{ - {{{11, 11, 21, 21, 21, 21, 11, 11, 0, 0, 21, 0}}, - {{6, 6, 6, 6, 10, 10, 10, 10, 0, 0, 6, 0}}, - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6}}}}; + {{{21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21}}, + {{21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21}}, + {{21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21}}}}; //layers/disks used by each seed std::array, N_SEED> seedlayers_{{{{0, 1, -1}}, //L1L2 @@ -749,36 +790,62 @@ namespace trklet { // Set to 0 (default) means standard truncation // Set to large value, e.g. 10000, to disable truncation unsigned int maxstepoffset_{0}; + // turn off truncation for displaced tracking (not implemented properly for displaced seeding) + unsigned int maxstepoffset_extended_{10000}; //Number of processing steps for one event (108=18TM*240MHz/40MHz) + + //IR should be set to 108 to match the FW for the summer chain, but ultimately should be at 156 std::unordered_map maxstep_{{"IR", 156}, //IR will run at a higher clock speed to handle //input links running at 25 Gbits/s - {"VMR", 108}, - {"TE", 108}, + //Set to 108 to match firmware project 240 MHz clock + + {"VMR", 107}, + {"TE", 107}, {"TC", 108}, {"PR", 108}, {"ME", 108}, - {"MC", 105}, + //NOTE: The MC is set to 108, but `mergedepth` + //removes 3 iterations to emulate the delay + //due to the HLS priority encoder + {"MC", 108}, + {"TB", 108}, {"MP", 108}, {"TP", 108}, {"TRE", 108}}; // If set to true this will generate debub printout in text files - std::unordered_map writeMonitorData_{{"IL", false}, {"TE", false}, - {"CT", false}, {"HitPattern", false}, - {"ChiSq", false}, {"Seeds", false}, - {"FT", false}, {"Residuals", false}, - {"StubBend", false}, {"MC", false}, - {"MP", false}, {"ME", false}, - {"AP", false}, {"VMP", false}, - {"TrackProjOcc", false}, {"TC", false}, - {"Pars", false}, {"TPars", false}, - {"TPD", false}, {"TrackletPars", false}, - {"TED", false}, {"TP", false}, - {"TRE", false}, {"VMR", false}, - {"StubsLayer", false}, {"StubsLayerSector", false}, - {"HitEff", false}, {"MatchEff", false}, - {"IFit", false}, {"AS", false}}; + std::unordered_map writeMonitorData_{{"IL", false}, + {"TE", false}, + {"CT", false}, + {"HitPattern", false}, + {"ChiSq", false}, + {"Seeds", false}, + {"FT", false}, + {"Residuals", false}, + {"StubBend", false}, + {"MC", false}, + {"MP", false}, + {"ME", false}, + {"AP", false}, + {"VMP", false}, + {"TrackProjOcc", false}, + {"TC", false}, + {"Pars", false}, + {"TPars", false}, + {"TPD", false}, + {"TrackletPars", false}, + {"TED", false}, + {"TP", false}, + {"TRE", false}, + {"VMR", false}, + {"StubsLayer", false}, + {"StubsLayerSector", false}, + {"HitEff", false}, + {"MatchEff", false}, + {"IFit", false}, + {"AS", false}, + {"WriteEmptyProj", false}}; std::array rDSSinner_mod_{{68.9391, 78.7750, 85.4550, 96.3150, 102.3160}}; std::array rDSSouter_mod_{{66.4903, 76.7750, 84.4562, 94.9920, 102.3160}}; @@ -832,8 +899,8 @@ namespace trklet { int nrinvBitsTable_{3}; //number of bits for tabulating rinv dependence unsigned int MEBinsBits_{3}; - unsigned int MEBinsDisks_{8}; //on each side - unsigned int maxStubsPerBin_{16}; + unsigned int MEBinsDisks_{8}; //on each side + unsigned int maxStubsPerBin_{15}; //16 causes overflow! // Options for chisq fit bool exactderivatives_{false}; @@ -848,32 +915,42 @@ namespace trklet { unsigned int minIndStubs_{3}; // not used with merge removal #ifdef USEHYBRID + // Duplicate track removal algo. VALUE HERE OVERRIDDEN BY PYTHON CFG std::string removalType_{"merge"}; // "CompareBest" (recommended) Compares only the best stub in each track for each region (best = smallest phi residual) // and will merge the two tracks if stubs are shared in three or more regions // "CompareAll" Compares all stubs in a region, looking for matches, and will merge the two tracks if stubs are shared in three or more regions std::string mergeComparison_{"CompareBest"}; bool doKF_{true}; -#endif - -#ifndef USEHYBRID - bool doKF_{false}; +#else std::string removalType_{"ichi"}; std::string mergeComparison_{""}; + bool doKF_{false}; #endif + // VALUE OVERRIDDEN BY PYTHON CFG // When false, match calculator does not save multiple matches, even when doKF=true. // This is a temporary fix for compatibilty with HLS. We will need to implement multiple match // printing in emulator eventually, possibly after CMSSW-integration inspired rewrites // Use false when generating HLS files, use true when doing full hybrid tracking bool doMultipleMatches_{true}; + // NEXT 2 VALUES OVERRIDDEN BY PYTHON CFG // if true, run a dummy fit, producing TTracks directly from output of tracklet pattern reco stage bool fakefit_{false}; + // if true, EDProducer fills additional bit & clock accurate TrackBuilder EDProduct + bool storeTrackBuilderOutput_{false}; + // NEXT 3 VALUES OVERRIDDEN BY PYTHON CFG unsigned int nHelixPar_{4}; // 4 or 5 param helix fit bool extended_{false}; // turn on displaced tracking - bool combined_{false}; // use combined TP (TE+TC) and MP (PR+ME+MC) configuration + bool reduced_{false}; // use reduced (Summer Chain) config + + // Use combined TP (TE+TC) and MP (PR+ME+MC) configuration (with prompt tracking) + bool combined_{false}; + // N.B. To use combined modules with extended tracking, edit + // Tracklet_cfi.py to refer to *_hourglassExtendedCombined.dat, + // but leave combined_=false. std::string skimfile_{""}; //if not empty events will be written out in ascii format to this file @@ -891,7 +968,7 @@ namespace trklet { }; constexpr unsigned int N_TILTED_RINGS = 12; // # of tilted rings per half-layer in TBPS layers - constexpr std::array N_MOD_PLANK = {{7, 11, 15}}; // # of modules/plank in TBPS + constexpr std::array N_MOD_PLANK = {{7, 11, 15}}; // # of flat barrel modules/plank in TBPS constexpr unsigned int N_TRKLSEED = 7; // # of tracklet seeds constexpr unsigned int N_PROJ = 4; // # of projections (beyond stubs from tracklet seed) diff --git a/L1Trigger/TrackFindingTracklet/interface/StubStreamData.h b/L1Trigger/TrackFindingTracklet/interface/StubStreamData.h new file mode 100644 index 0000000000000..5bf2c488da1a6 --- /dev/null +++ b/L1Trigger/TrackFindingTracklet/interface/StubStreamData.h @@ -0,0 +1,36 @@ +#ifndef L1Trigger_TrackFindingTracklet_interface_StubStreamData_h +#define L1Trigger_TrackFindingTracklet_interface_StubStreamData_h + +#include "L1Trigger/TrackFindingTracklet/interface/L1TStub.h" + +#include + +// Represents an element of the bit-accurate stub stream from TrackBuilder output +// (This class only needed to support stand-alone running of this code). + +namespace trklet { + + class L1TStub; + + class StubStreamData { + public: + StubStreamData() {} + + StubStreamData(int iSeed, const L1TStub& stub, const std::string& dataBits) + : iSeed_(iSeed), stub_(stub), dataBits_(dataBits) {} + + ~StubStreamData() = default; + + int iSeed() const { return iSeed_; } // Seed type + bool valid() const { return (iSeed_ >= 0); } // Valid stub + const L1TStub& stub() const { return stub_; } + // String with bits of valid bit + r coordinate + phi residual + r or z residual. + const std::string& dataBits() const { return dataBits_; } + + private: + int iSeed_{-1}; + L1TStub stub_; + std::string dataBits_{""}; + }; +}; // namespace trklet +#endif diff --git a/L1Trigger/TrackFindingTracklet/interface/Track.h b/L1Trigger/TrackFindingTracklet/interface/Track.h index 0e014083b70fc..6553c6fc0fa82 100644 --- a/L1Trigger/TrackFindingTracklet/interface/Track.h +++ b/L1Trigger/TrackFindingTracklet/interface/Track.h @@ -17,8 +17,9 @@ namespace trklet { class Track { public: - Track(TrackPars ipars, - int ichisqrphi, + // Create track from digitized helix params & stubs + Track(TrackPars ipars, // digi helix + int ichisqrphi, // digi chi2 int ichisqrz, double chisqrphi, double chisqrz, @@ -54,13 +55,15 @@ namespace trklet { return (settings.c() * settings.bfield() * 0.01) / (ipars_.rinv() * settings.krinvpars()); } + // Get floating point helix params by undigitized digi helix params double phi0(Settings const& settings) const; - double eta(Settings const& settings) const { return asinh(ipars_.t() * settings.ktpars()); } - double tanL(Settings const& settings) const { return ipars_.t() * settings.ktpars(); } - double z0(Settings const& settings) const { return ipars_.z0() * settings.kz0pars(); } - double rinv(Settings const& settings) const { return ipars_.rinv() * settings.krinvpars(); } - double d0(Settings const& settings) const { return ipars_.d0() * settings.kd0pars(); } + //The following return the floating point track parameters by undigitizing the digitized parameters + double eta(Settings const& settings) const { return (asinh(ipars_.t() + 0.5) * settings.ktpars()); } + double tanL(Settings const& settings) const { return (ipars_.t() + 0.5) * settings.ktpars(); } + double z0(Settings const& settings) const { return (ipars_.z0() + 0.5) * settings.kz0pars(); } + double rinv(Settings const& settings) const { return (ipars_.rinv() + 0.5) * settings.krinvpars(); } + double d0(Settings const& settings) const { return (ipars_.d0() + 0.5) * settings.kd0pars(); } double chisq() const { return chisqrphi_ + chisqrz_; } double chisqrphi() const { return chisqrphi_; } @@ -76,7 +79,7 @@ namespace trklet { } private: - TrackPars ipars_; + TrackPars ipars_; //digitized track parameters int ichisqrphi_; int ichisqrz_; diff --git a/L1Trigger/TrackFindingTracklet/interface/Tracklet.h b/L1Trigger/TrackFindingTracklet/interface/Tracklet.h index 30e1ae3900ec3..2e31286e775fe 100644 --- a/L1Trigger/TrackFindingTracklet/interface/Tracklet.h +++ b/L1Trigger/TrackFindingTracklet/interface/Tracklet.h @@ -157,6 +157,7 @@ namespace trklet { return FPGAWord(ichisqrphifit_.value() + ichisqrzfit_.value(), ichisqrphifit_.nbits()); } + // Note floating & digitized helix params after track fit. void setFitPars(double rinvfit, double phi0fit, double d0fit, @@ -185,6 +186,7 @@ namespace trklet { const std::string diskstubstr(const unsigned disk) const; std::string trackfitstr() const; + // Create a Track object from stubs & digitized track helix params Track makeTrack(const std::vector& l1stubs); Track* getTrack() { diff --git a/L1Trigger/TrackFindingTracklet/interface/TrackletCalculatorDisplaced.h b/L1Trigger/TrackFindingTracklet/interface/TrackletCalculatorDisplaced.h index 9bc51a81d34c8..e0199f5ae030c 100644 --- a/L1Trigger/TrackFindingTracklet/interface/TrackletCalculatorDisplaced.h +++ b/L1Trigger/TrackFindingTracklet/interface/TrackletCalculatorDisplaced.h @@ -155,7 +155,7 @@ namespace trklet { double phiderdisk[5], double rderdisk[5]); - private: + protected: int TCIndex_; int layer_; int disk_; diff --git a/L1Trigger/TrackFindingTracklet/interface/TrackletConfigBuilder.h b/L1Trigger/TrackFindingTracklet/interface/TrackletConfigBuilder.h index 64cc428205da8..49403db972260 100644 --- a/L1Trigger/TrackFindingTracklet/interface/TrackletConfigBuilder.h +++ b/L1Trigger/TrackFindingTracklet/interface/TrackletConfigBuilder.h @@ -9,18 +9,23 @@ #include "L1Trigger/TrackFindingTracklet/interface/Settings.h" #include +#include #include #include #include #include #include +namespace tt { + class Setup; +} + namespace trklet { class TrackletConfigBuilder { public: //Builds the configuration for the tracklet based track finding - TrackletConfigBuilder(const Settings& settings); + TrackletConfigBuilder(const Settings& settings, const tt::Setup* setup = nullptr); //This method writes out the configuration as files void writeAll(std::ostream& wires, std::ostream& memories, std::ostream& modules); @@ -31,28 +36,28 @@ namespace trklet { // //Seed string, eg. L1L2 - std::string iSeedStr(unsigned int iSeed); + std::string iSeedStr(unsigned int iSeed) const; //Return unsigned as string static std::string numStr(unsigned int i); - //Retunr iTC as string - ie A, B, C, etc - std::string iTCStr(unsigned int iTC); + //Return iTC as string - ie A, B, C, etc + std::string iTCStr(unsigned int iTC) const; //The region string A, B, C etc for layers and disks; X, Y, Z etc for overlap - std::string iRegStr(unsigned int iReg, unsigned int iSeed); + std::string iRegStr(unsigned int iReg, unsigned int iSeed) const; //TC Name - std::string TCName(unsigned int iSeed, unsigned int iTC); + std::string TCName(unsigned int iSeed, unsigned int iTC) const; //Name of layer or disk, e.g. L1 or D1 static std::string LayerName(unsigned int ilayer); //Tracklet projection name - std::string TPROJName(unsigned int iSeed, unsigned int iTC, unsigned int ilayer, unsigned int ireg); + std::string TPROJName(unsigned int iSeed, unsigned int iTC, unsigned int ilayer, unsigned int ireg) const; //Projection router name - std::string PRName(unsigned int ilayer, unsigned int ireg); + std::string PRName(unsigned int ilayer, unsigned int ireg) const; private: // @@ -75,6 +80,17 @@ namespace trklet { // void buildProjections(); +#ifdef CMSSW_GIT_HASH + // Calculate phi range of modules read by each DTC. + void setDTCphirange(const tt::Setup* setup); + + // Write DTC phi ranges to dtcphirange.txt for stand-alone emulation. + void writeDTCphirange() const; +#else + // Set phi ranges after reading them from dtcphirange.txt (stand-alone emulation) + void setDTCphirange(const tt::Setup* setup = nullptr); +#endif + // // Helper function to determine if a pair of VM memories form valid TE // @@ -113,9 +129,9 @@ namespace trklet { unsigned int l2, unsigned int ireg2, unsigned int ivm2, - unsigned int iseed); + unsigned int iseed) const; - //StubPaur displaced name + //StubPair displaced name std::string SPDName(unsigned int l1, unsigned int ireg1, unsigned int ivm1, @@ -125,7 +141,7 @@ namespace trklet { unsigned int l3, unsigned int ireg3, unsigned int ivm3, - unsigned int iseed); + unsigned int iseed) const; //Stub Triplet name std::string STName(unsigned int l1, @@ -135,7 +151,7 @@ namespace trklet { unsigned int l3, unsigned int ireg3, unsigned int iseed, - unsigned int count); + unsigned int count) const; //TrackletEngine name std::string TEName(unsigned int l1, @@ -144,7 +160,7 @@ namespace trklet { unsigned int l2, unsigned int ireg2, unsigned int ivm2, - unsigned int iseed); + unsigned int iseed) const; //Triplet engine name std::string TREName(unsigned int l1, @@ -152,7 +168,7 @@ namespace trklet { unsigned int l2, unsigned int ireg2, unsigned int iseed, - unsigned int count); + unsigned int count) const; //TrackletEngine displaced name std::string TEDName(unsigned int l1, @@ -161,13 +177,13 @@ namespace trklet { unsigned int l2, unsigned int ireg2, unsigned int ivm2, - unsigned int iseed); + unsigned int iseed) const; //Tracklet parameter memory name - std::string TParName(unsigned int l1, unsigned int l2, unsigned int l3, unsigned int itc); + std::string TParName(unsigned int l1, unsigned int l2, unsigned int l3, unsigned int itc) const; //TrackletCalculator displaced name - std::string TCDName(unsigned int l1, unsigned int l2, unsigned int l3, unsigned int itc); + std::string TCDName(unsigned int l1, unsigned int l2, unsigned int l3, unsigned int itc) const; //TrackletProjection name std::string TPROJName(unsigned int l1, @@ -175,13 +191,10 @@ namespace trklet { unsigned int l3, unsigned int itc, unsigned int projlay, - unsigned int projreg); + unsigned int projreg) const; //FitTrack module name - std::string FTName(unsigned int l1, unsigned int l2, unsigned int l3); - - //TrackletCalculator name - std::string TCNAme(unsigned int iseed, unsigned int iTC); + std::string FTName(unsigned int l1, unsigned int l2, unsigned int l3) const; // // This group of methods are used to print out the configuration as a file @@ -213,8 +226,9 @@ namespace trklet { void writeILMemories(std::ostream& os, std::ostream& memories, std::ostream& modules); // - // Store constants extracted from Settings + //--- Store constants extracted from Settings // + unsigned int NSector_; //Number of sectors double rcrit_; //critical radius that defines the sector @@ -246,10 +260,10 @@ namespace trklet { std::pair >, std::vector > > VMStubsTE_[N_SEED_PROMPT]; - //List of the TEs and the VM bins for each TE + // VM bin in inner/outer seeding layer of each TE. std::vector > TE_[N_SEED_PROMPT]; - //The TCs for each seeding combination + //The ID of all TE that send data to TCs for each seeding combination std::vector > TC_[N_SEED_PROMPT]; //The projections to each layer/disk from a seed and TC @@ -266,6 +280,14 @@ namespace trklet { {-1, -1, -1, -1, -1, -1, -1, 1, 2, 3, 4}, //L1D1 {1, -1, -1, -1, -1, -1, -1, 2, 3, 4, -1}}; //L2D1 + struct DTCinfo { + std::string name; + int layer; + float phimin; + float phimax; + }; + std::list vecDTCinfo_; + //Settings const Settings& settings_; }; diff --git a/L1Trigger/TrackFindingTracklet/interface/TrackletEventProcessor.h b/L1Trigger/TrackFindingTracklet/interface/TrackletEventProcessor.h index 114b2f0e32dc5..e617ef173e6ea 100644 --- a/L1Trigger/TrackFindingTracklet/interface/TrackletEventProcessor.h +++ b/L1Trigger/TrackFindingTracklet/interface/TrackletEventProcessor.h @@ -7,8 +7,13 @@ #include #include #include +#include #include +namespace tt { + class Setup; +} + namespace trklet { class Settings; @@ -17,6 +22,7 @@ namespace trklet { class Sector; class HistBase; class Track; + class StubStreamData; class TrackletEventProcessor { public: @@ -24,9 +30,11 @@ namespace trklet { ~TrackletEventProcessor(); - void init(Settings const& theSettings); + void init(Settings const& theSettings, const tt::Setup* setup = nullptr); - void event(SLHCEvent& ev); + void event(SLHCEvent& ev, + std::vector>& streamsTrackRaw, + std::vector>& streamsStubRaw); void printSummary(); @@ -53,6 +61,7 @@ namespace trklet { Timer TEDTimer_; Timer TRETimer_; Timer TPTimer_; + Timer TPDTimer_; Timer TCTimer_; Timer TCDTimer_; Timer PRTimer_; diff --git a/L1Trigger/TrackFindingTracklet/interface/TrackletProcessorDisplaced.h b/L1Trigger/TrackFindingTracklet/interface/TrackletProcessorDisplaced.h new file mode 100644 index 0000000000000..9313f030b1b5b --- /dev/null +++ b/L1Trigger/TrackFindingTracklet/interface/TrackletProcessorDisplaced.h @@ -0,0 +1,79 @@ +// TrackletProcessorDisplaced: This class performs the tasks of the TrackletEngineDisplaced+TripletEngine+TrackletCalculatorDisplaced. +#ifndef L1Trigger_TrackFindingTracklet_interface_TrackletProcessorDisplaced_h +#define L1Trigger_TrackFindingTracklet_interface_TrackletProcessorDisplaced_h + +#include "L1Trigger/TrackFindingTracklet/interface/TrackletCalculatorBase.h" +#include "L1Trigger/TrackFindingTracklet/interface/TrackletCalculatorDisplaced.h" +#include "L1Trigger/TrackFindingTracklet/interface/TrackletLUT.h" +#include "L1Trigger/TrackFindingTracklet/interface/CircularBuffer.h" +#include "L1Trigger/TrackFindingTracklet/interface/TrackletEngineUnit.h" +#include "L1Trigger/TrackFindingTracklet/interface/TrackletParametersMemory.h" +#include "L1Trigger/TrackFindingTracklet/interface/TrackletProjectionsMemory.h" + +#include +#include +#include + +namespace trklet { + + class Settings; + class Globals; + class MemoryBase; + class AllStubsMemory; + class AllInnerStubsMemory; + class VMStubsTEMemory; + class StubPairsMemory; + + class TrackletProcessorDisplaced : public TrackletCalculatorDisplaced { + public: + TrackletProcessorDisplaced(std::string name, Settings const& settings, Globals* globals); + + ~TrackletProcessorDisplaced() override = default; + + void addOutputProjection(TrackletProjectionsMemory*& outputProj, MemoryBase* memory); + + void addOutput(MemoryBase* memory, std::string output) override; + + void addInput(MemoryBase* memory, std::string input) override; + + void execute(unsigned int iSector, double phimin, double phimax); + + private: + int iTC_; + int iAllStub_; + unsigned int maxStep_; + int count_; + unsigned int layerdisk_; + + int layer1_; + int layer2_; + int layer3_; + int disk1_; + int disk2_; + int disk3_; + + int firstphibits_; + int secondphibits_; + int thirdphibits_; + + int nbitszfinebintable_; + int nbitsrfinebintable_; + + TrackletLUT innerTable_; //projection to next layer/disk + TrackletLUT innerOverlapTable_; //projection to disk from layer + TrackletLUT innerThirdTable_; //projection to disk1 for extended - iseed=10 + + std::vector stubpairs_; + /* std::vector stubtriplets_; */ + std::vector innervmstubs_; + std::vector outervmstubs_; + + StubTripletsMemory* stubtriplets_; + + std::map > > tmpSPTable_; + std::map > > spTable_; + std::vector table_; + }; + +}; // namespace trklet +#endif diff --git a/L1Trigger/TrackFindingTracklet/interface/TrackletProjectionsMemory.h b/L1Trigger/TrackFindingTracklet/interface/TrackletProjectionsMemory.h index 4a936c7c4f950..038306d981a63 100644 --- a/L1Trigger/TrackFindingTracklet/interface/TrackletProjectionsMemory.h +++ b/L1Trigger/TrackFindingTracklet/interface/TrackletProjectionsMemory.h @@ -16,7 +16,11 @@ namespace trklet { public: TrackletProjectionsMemory(std::string name, Settings const& settings); - ~TrackletProjectionsMemory() override = default; + ~TrackletProjectionsMemory() override { + if (settings_.writeMonitorData("WriteEmptyProj") && (!hasProj_)) { + edm::LogPrint("Tracklet") << "Empty Projection Memory : " << getName() << std::endl; + } + }; void addProj(Tracklet* tracklet); @@ -34,6 +38,7 @@ namespace trklet { private: std::vector tracklets_; + bool hasProj_; int layer_; int disk_; }; diff --git a/L1Trigger/TrackFindingTracklet/interface/Util.h b/L1Trigger/TrackFindingTracklet/interface/Util.h index 37fe0ba503141..deaf18936d052 100644 --- a/L1Trigger/TrackFindingTracklet/interface/Util.h +++ b/L1Trigger/TrackFindingTracklet/interface/Util.h @@ -47,9 +47,7 @@ namespace trklet { } inline double rinv(double phi1, double phi2, double r1, double r2) { - if (r2 <= r1) { //FIXME can not form tracklet should not call function with r2<=r1 - return 20.0; - } + assert(r1 < r2); //Can not form tracklet should not call function with r2<=r1 double dphi = phi2 - phi1; double dr = r2 - r1; diff --git a/L1Trigger/TrackFindingTracklet/interface/VMRouterCM.h b/L1Trigger/TrackFindingTracklet/interface/VMRouterCM.h index 2f6a468576361..d6250cc138246 100644 --- a/L1Trigger/TrackFindingTracklet/interface/VMRouterCM.h +++ b/L1Trigger/TrackFindingTracklet/interface/VMRouterCM.h @@ -38,7 +38,7 @@ namespace trklet { void addOutput(MemoryBase* memory, std::string output) override; void addInput(MemoryBase* memory, std::string input) override; - void execute(); + void execute(unsigned int iSector); private: //0-5 are the layers and 6-10 are the disks diff --git a/L1Trigger/TrackFindingTracklet/interface/imath.h b/L1Trigger/TrackFindingTracklet/interface/imath.h index 6d74daddc81cc..a3e5ad3f597d2 100644 --- a/L1Trigger/TrackFindingTracklet/interface/imath.h +++ b/L1Trigger/TrackFindingTracklet/interface/imath.h @@ -226,7 +226,7 @@ namespace trklet { const std::map > *const previous_cut_strings = nullptr) const; void add_cut(VarCut *cut, const bool call_set_cut_var = true); VarBase *cut_var(); - + // observed range of fval_ (only filled if debug_level > 0) double minval() const { return minval_; } double maxval() const { return maxval_; } void analyze(); @@ -251,9 +251,9 @@ namespace trklet { int step() const { return step_; } int latency() const { return latency_; } void add_latency(unsigned int l) { latency_ += l; } //only call before using the variable in calculation! - bool calculate(int debug_level); - bool calculate() { return calculate(0); } + bool calculate(int debug_level = 0); virtual void local_calculate() {} + void calcDebug(int debug_level, long int ival_prev, bool &all_ok); virtual void print(std::ofstream &fs, Verilog, int l1 = 0, int l2 = 0, int l3 = 0) { fs << "// VarBase here. Soemthing is wrong!! " << l1 << ", " << l2 << ", " << l3 << "\n"; } diff --git a/L1Trigger/TrackFindingTracklet/plugins/L1FPGATrackProducer.cc b/L1Trigger/TrackFindingTracklet/plugins/L1FPGATrackProducer.cc index d389a7159c8d8..13fdc79169296 100644 --- a/L1Trigger/TrackFindingTracklet/plugins/L1FPGATrackProducer.cc +++ b/L1Trigger/TrackFindingTracklet/plugins/L1FPGATrackProducer.cc @@ -29,6 +29,7 @@ #include "DataFormats/SiPixelDetId/interface/PXBDetId.h" #include "DataFormats/SiPixelDetId/interface/PXFDetId.h" #include "DataFormats/Common/interface/DetSetVector.h" +#include "DataFormats/L1TrackTrigger/interface/TTBV.h" // #include "L1Trigger/TrackFindingTracklet/interface/SLHCEvent.h" #include "L1Trigger/TrackFindingTracklet/interface/L1TStub.h" @@ -40,7 +41,6 @@ #include "SimDataFormats/Vertex/interface/SimVertex.h" #include "SimDataFormats/Vertex/interface/SimVertexContainer.h" #include "SimDataFormats/TrackingAnalysis/interface/TrackingParticle.h" -#include "SimTracker/TrackTriggerAssociation/interface/TTStubAssociationMap.h" #include "SimTracker/TrackTriggerAssociation/interface/TTClusterAssociationMap.h" // #include "DataFormats/Math/interface/LorentzVector.h" @@ -52,7 +52,7 @@ #include "DataFormats/L1TrackTrigger/interface/TTTrack_TrackWord.h" #include "DataFormats/L1TrackTrigger/interface/TTTypes.h" #include "DataFormats/L1TrackTrigger/interface/TTDTC.h" -#include "L1Trigger/TrackerDTC/interface/Setup.h" +#include "L1Trigger/TrackTrigger/interface/Setup.h" // #include "DataFormats/HepMCCandidate/interface/GenParticle.h" #include "DataFormats/Candidate/interface/Candidate.h" @@ -83,6 +83,11 @@ #include "L1Trigger/TrackFindingTracklet/interface/Sector.h" #include "L1Trigger/TrackFindingTracklet/interface/Track.h" #include "L1Trigger/TrackFindingTracklet/interface/TrackletEventProcessor.h" +#include "L1Trigger/TrackFindingTracklet/interface/ChannelAssignment.h" +#include "L1Trigger/TrackFindingTracklet/interface/Tracklet.h" +#include "L1Trigger/TrackFindingTracklet/interface/Residual.h" +#include "L1Trigger/TrackFindingTracklet/interface/Stub.h" +#include "L1Trigger/TrackFindingTracklet/interface/StubStreamData.h" //////////////// // PHYSICS TOOLS @@ -94,6 +99,7 @@ #include "L1Trigger/TrackTrigger/interface/StubPtConsistency.h" #include "L1Trigger/TrackTrigger/interface/L1TrackQuality.h" +#include "L1Trigger/TrackTrigger/interface/HitPatternHelper.h" ////////////// // STD HEADERS @@ -106,6 +112,8 @@ // NAMESPACES using namespace edm; using namespace std; +using namespace tt; +using namespace trklet; ////////////////////////////// // // @@ -157,13 +165,14 @@ class L1FPGATrackProducer : public edm::one::EDProducer { std::ofstream asciiEventOut_; // settings containing various constants for the tracklet processing - trklet::Settings settings; + trklet::Settings settings_; // event processor for the tracklet track finding trklet::TrackletEventProcessor eventProcessor; unsigned int nHelixPar_; bool extended_; + bool reduced_; bool trackQuality_; std::unique_ptr trackQualityModel_; @@ -174,21 +183,31 @@ class L1FPGATrackProducer : public edm::one::EDProducer { edm::InputTag MCTruthStubInputTag; edm::InputTag TrackingParticleInputTag; - const edm::EDGetTokenT bsToken_; + const edm::EDGetTokenT getTokenBS_; + const edm::EDGetTokenT getTokenDTC_; + edm::EDGetTokenT> getTokenTTClusterMCTruth_; + edm::EDGetTokenT> getTokenTrackingParticle_; - edm::EDGetTokenT> ttClusterMCTruthToken_; - edm::EDGetTokenT> TrackingParticleToken_; - edm::EDGetTokenT tokenDTC_; + // ED output token for clock and bit accurate tracks + const edm::EDPutTokenT putTokenTracks_; + // ED output token for clock and bit accurate stubs + const edm::EDPutTokenT putTokenStubs_; + // ChannelAssignment token + const ESGetToken esGetTokenChannelAssignment_; + // helper class to assign tracks to channel + const ChannelAssignment* channelAssignment_; // helper class to store DTC configuration - trackerDTC::Setup setup_; + const Setup* setup_; + // helper class to store configuration needed by HitPatternHelper + const hph::Setup* setupHPH_; // Setup token - edm::ESGetToken esGetToken_; - const edm::ESGetToken magneticFieldToken_; - - const edm::ESGetToken tGeomToken_; - const edm::ESGetToken tTopoToken_; + const edm::ESGetToken esGetTokenBfield_; + const edm::ESGetToken esGetTokenTGeom_; + const edm::ESGetToken esGetTokenTTopo_; + const edm::ESGetToken esGetToken_; + const edm::ESGetToken esGetTokenHPH_; /// ///////////////// /// /// MANDATORY METHODS /// @@ -208,14 +227,23 @@ L1FPGATrackProducer::L1FPGATrackProducer(edm::ParameterSet const& iConfig) : edm::InputTag()), TrackingParticleInputTag(readMoreMcTruth_ ? iConfig.getParameter("TrackingParticleInputTag") : edm::InputTag()), - bsToken_(consumes(config.getParameter("BeamSpotSource"))), - tokenDTC_(consumes(edm::InputTag(iConfig.getParameter("InputTagTTDTC")))), - magneticFieldToken_(esConsumes()), - tGeomToken_(esConsumes()), - tTopoToken_(esConsumes()) { + // book ED products + getTokenBS_(consumes(config.getParameter("BeamSpotSource"))), + getTokenDTC_(consumes(edm::InputTag(iConfig.getParameter("InputTagTTDTC")))), + // book ED output token for clock and bit accurate tracks + putTokenTracks_(produces("Level1TTTracks")), + // book ED output token for clock and bit accurate stubs + putTokenStubs_(produces("Level1TTTracks")), + // book ES products + esGetTokenChannelAssignment_(esConsumes()), + esGetTokenBfield_(esConsumes()), + esGetTokenTGeom_(esConsumes()), + esGetTokenTTopo_(esConsumes()), + esGetToken_(esConsumes()), + esGetTokenHPH_(esConsumes()) { if (readMoreMcTruth_) { - ttClusterMCTruthToken_ = consumes>(MCTruthClusterInputTag); - TrackingParticleToken_ = consumes>(TrackingParticleInputTag); + getTokenTTClusterMCTruth_ = consumes>(MCTruthClusterInputTag); + getTokenTrackingParticle_ = consumes>(TrackingParticleInputTag); } produces>>("Level1TTTracks").setBranchAlias("Level1TTTracks"); @@ -228,6 +256,7 @@ L1FPGATrackProducer::L1FPGATrackProducer(edm::ParameterSet const& iConfig) wiresFile = iConfig.getParameter("wiresFile"); extended_ = iConfig.getParameter("Extended"); + reduced_ = iConfig.getParameter("Reduced"); nHelixPar_ = iConfig.getParameter("Hnpar"); if (extended_) { @@ -235,29 +264,36 @@ L1FPGATrackProducer::L1FPGATrackProducer(edm::ParameterSet const& iConfig) tableTREFile = iConfig.getParameter("tableTREFile"); } - // book ES product - esGetToken_ = esConsumes(); + // initial ES products + channelAssignment_ = nullptr; + setup_ = nullptr; // -------------------------------------------------------------------------------- // set options in Settings based on inputs from configuration files // -------------------------------------------------------------------------------- - settings.setExtended(extended_); - settings.setNHelixPar(nHelixPar_); + settings_.setExtended(extended_); + settings_.setReduced(reduced_); + settings_.setNHelixPar(nHelixPar_); + + settings_.setFitPatternFile(fitPatternFile.fullPath()); + settings_.setProcessingModulesFile(processingModulesFile.fullPath()); + settings_.setMemoryModulesFile(memoryModulesFile.fullPath()); + settings_.setWiresFile(wiresFile.fullPath()); - settings.setFitPatternFile(fitPatternFile.fullPath()); - settings.setProcessingModulesFile(processingModulesFile.fullPath()); - settings.setMemoryModulesFile(memoryModulesFile.fullPath()); - settings.setWiresFile(wiresFile.fullPath()); + settings_.setFakefit(iConfig.getParameter("Fakefit")); + settings_.setStoreTrackBuilderOutput(iConfig.getParameter("StoreTrackBuilderOutput")); + settings_.setRemovalType(iConfig.getParameter("RemovalType")); + settings_.setDoMultipleMatches(iConfig.getParameter("DoMultipleMatches")); if (extended_) { - settings.setTableTEDFile(tableTEDFile.fullPath()); - settings.setTableTREFile(tableTREFile.fullPath()); + settings_.setTableTEDFile(tableTEDFile.fullPath()); + settings_.setTableTREFile(tableTREFile.fullPath()); //FIXME: The TED and TRE tables are currently disabled by default, so we //need to allow for the additional tracklets that will eventually be //removed by these tables, once they are finalized - settings.setNbitstrackletindex(10); + settings_.setNbitstrackletindex(15); } eventnum = 0; @@ -265,7 +301,7 @@ L1FPGATrackProducer::L1FPGATrackProducer(edm::ParameterSet const& iConfig) asciiEventOut_.open(asciiEventOutName_.c_str()); } - if (settings.debugTracklet()) { + if (settings_.debugTracklet()) { edm::LogVerbatim("Tracklet") << "fit pattern : " << fitPatternFile.fullPath() << "\n process modules : " << processingModulesFile.fullPath() << "\n memory modules : " << memoryModulesFile.fullPath() @@ -280,6 +316,15 @@ L1FPGATrackProducer::L1FPGATrackProducer(edm::ParameterSet const& iConfig) if (trackQuality_) { trackQualityModel_ = std::make_unique(iConfig.getParameter("TrackQualityPSet")); } + if (settings_.storeTrackBuilderOutput() && (settings_.doMultipleMatches() || !settings_.removalType().empty())) { + cms::Exception exception("ConfigurationNotSupported."); + exception.addContext("L1FPGATrackProducer::produce"); + if (settings_.doMultipleMatches()) + exception << "Storing of TrackBuilder output does not support doMultipleMatches."; + if (!settings_.removalType().empty()) + exception << "Storing of TrackBuilder output does not support duplicate removal."; + throw exception; + } } ///////////// @@ -299,14 +344,19 @@ void L1FPGATrackProducer::endRun(const edm::Run& run, const edm::EventSetup& iSe void L1FPGATrackProducer::beginRun(const edm::Run& run, const edm::EventSetup& iSetup) { //////////////////////// // GET MAGNETIC FIELD // - const MagneticField* theMagneticField = &iSetup.getData(magneticFieldToken_); + const MagneticField* theMagneticField = &iSetup.getData(esGetTokenBfield_); double mMagneticFieldStrength = theMagneticField->inTesla(GlobalPoint(0, 0, 0)).z(); - settings.setBfield(mMagneticFieldStrength); - - setup_ = iSetup.getData(esGetToken_); + settings_.setBfield(mMagneticFieldStrength); + setup_ = &iSetup.getData(esGetToken_); + setupHPH_ = &iSetup.getData(esGetTokenHPH_); + if (trackQuality_) { + trackQualityModel_->beginRun(setupHPH_); + } + // Tracklet pattern reco output channel info. + channelAssignment_ = &iSetup.getData(esGetTokenChannelAssignment_); // initialize the tracklet event processing (this sets all the processing & memory modules, wiring, etc) - eventProcessor.init(settings); + eventProcessor.init(settings_, setup_); } ////////// @@ -327,7 +377,7 @@ void L1FPGATrackProducer::produce(edm::Event& iEvent, const edm::EventSetup& iSe //////////// // GET BS // edm::Handle beamSpotHandle; - iEvent.getByToken(bsToken_, beamSpotHandle); + iEvent.getByToken(getTokenBS_, beamSpotHandle); math::XYZPoint bsPosition = beamSpotHandle->position(); eventnum++; @@ -338,16 +388,16 @@ void L1FPGATrackProducer::produce(edm::Event& iEvent, const edm::EventSetup& iSe // tracking particles edm::Handle> TrackingParticleHandle; if (readMoreMcTruth_) - iEvent.getByToken(TrackingParticleToken_, TrackingParticleHandle); + iEvent.getByToken(getTokenTrackingParticle_, TrackingParticleHandle); // tracker topology - const TrackerTopology* const tTopo = &iSetup.getData(tTopoToken_); - const TrackerGeometry* const theTrackerGeom = &iSetup.getData(tGeomToken_); + const TrackerTopology* const tTopo = &iSetup.getData(esGetTokenTTopo_); + const TrackerGeometry* const theTrackerGeom = &iSetup.getData(esGetTokenTGeom_); //////////////////////// // GET THE PRIMITIVES // edm::Handle handleDTC; - iEvent.getByToken(tokenDTC_, handleDTC); + iEvent.getByToken(getTokenDTC_, handleDTC); // must be defined for code to compile, even if it's not used unless readMoreMcTruth_ is true map, int> translateTP; @@ -355,7 +405,7 @@ void L1FPGATrackProducer::produce(edm::Event& iEvent, const edm::EventSetup& iSe // MC truth association maps edm::Handle> MCTruthTTClusterHandle; if (readMoreMcTruth_) { - iEvent.getByToken(ttClusterMCTruthToken_, MCTruthTTClusterHandle); + iEvent.getByToken(getTokenTTClusterMCTruth_, MCTruthTTClusterHandle); //////////////////////////////////////////////// /// LOOP OVER TRACKING PARTICLES & GET SIMTRACKS @@ -363,37 +413,39 @@ void L1FPGATrackProducer::produce(edm::Event& iEvent, const edm::EventSetup& iSe int ntps = 1; //count from 1 ; 0 will mean invalid int this_tp = 0; - for (const auto& iterTP : *TrackingParticleHandle) { - edm::Ptr tp_ptr(TrackingParticleHandle, this_tp); - this_tp++; + if (readMoreMcTruth_) { + for (const auto& iterTP : *TrackingParticleHandle) { + edm::Ptr tp_ptr(TrackingParticleHandle, this_tp); + this_tp++; - // only keep TPs producing a cluster - if (MCTruthTTClusterHandle->findTTClusterRefs(tp_ptr).empty()) - continue; + // only keep TPs producing a cluster + if (MCTruthTTClusterHandle->findTTClusterRefs(tp_ptr).empty()) + continue; - if (iterTP.g4Tracks().empty()) { - continue; - } + if (iterTP.g4Tracks().empty()) { + continue; + } - int sim_eventid = iterTP.g4Tracks().at(0).eventId().event(); - int sim_type = iterTP.pdgId(); - float sim_pt = iterTP.pt(); - float sim_eta = iterTP.eta(); - float sim_phi = iterTP.phi(); + int sim_eventid = iterTP.g4Tracks().at(0).eventId().event(); + int sim_type = iterTP.pdgId(); + float sim_pt = iterTP.pt(); + float sim_eta = iterTP.eta(); + float sim_phi = iterTP.phi(); - float vx = iterTP.vertex().x(); - float vy = iterTP.vertex().y(); - float vz = iterTP.vertex().z(); + float vx = iterTP.vertex().x(); + float vy = iterTP.vertex().y(); + float vz = iterTP.vertex().z(); - if (sim_pt < 1.0 || std::abs(vz) > 100.0 || hypot(vx, vy) > 50.0) - continue; + if (sim_pt < 1.0 || std::abs(vz) > 100.0 || hypot(vx, vy) > 50.0) + continue; - ev.addL1SimTrack(sim_eventid, ntps, sim_type, sim_pt, sim_eta, sim_phi, vx, vy, vz); + ev.addL1SimTrack(sim_eventid, ntps, sim_type, sim_pt, sim_eta, sim_phi, vx, vy, vz); - translateTP[tp_ptr] = ntps; - ntps++; + translateTP[tp_ptr] = ntps; + ntps++; - } //end loop over TPs + } //end loop over TPs + } } // end if (readMoreMcTruth_) @@ -401,33 +453,29 @@ void L1FPGATrackProducer::produce(edm::Event& iEvent, const edm::EventSetup& iSe /// READ DTC STUB INFORMATION /// ///////////////////////////////// - // Process stubs in each region and channel within that region + // Process stubs in each region and channel within that tracking region for (const int& region : handleDTC->tfpRegions()) { for (const int& channel : handleDTC->tfpChannels()) { - // Get the DTC name form the channel - - static string dtcbasenames[12] = { - "PS10G_1", "PS10G_2", "PS10G_3", "PS10G_4", "PS_1", "PS_2", "2S_1", "2S_2", "2S_3", "2S_4", "2S_5", "2S_6"}; - - string dtcname = dtcbasenames[channel % 12]; - + // Get the DTC name & ID from the channel + unsigned int atcaSlot = channel % 12; + string dtcname = settings_.slotToDTCname(atcaSlot); if (channel % 24 >= 12) dtcname = "neg" + dtcname; - - dtcname += (channel < 24) ? "_A" : "_B"; + dtcname += (channel < 24) ? "_A" : "_B"; // which detector region + int dtcId = setup_->dtcId(region, channel); // Get the stubs from the DTC - const TTDTC::Stream& streamFromDTC{handleDTC->stream(region, channel)}; + const tt::StreamStub& streamFromDTC{handleDTC->stream(region, channel)}; // Prepare the DTC stubs for the IR for (size_t stubIndex = 0; stubIndex < streamFromDTC.size(); ++stubIndex) { - const TTDTC::Frame& stub{streamFromDTC[stubIndex]}; + const tt::FrameStub& stub{streamFromDTC[stubIndex]}; + const TTStubRef& stubRef = stub.first; - if (stub.first.isNull()) { + if (stubRef.isNull()) continue; - } - const GlobalPoint& ttPos = setup_.stubPos(stub.first); + const GlobalPoint& ttPos = setup_->stubPos(stubRef); //Get the 2 bits for the layercode string layerword = stub.second.to_string().substr(61, 2); @@ -436,18 +484,19 @@ void L1FPGATrackProducer::produce(edm::Event& iEvent, const edm::EventSetup& iSe //translation from the two bit layercode to the layer/disk number of each of the //12 channels (dtcs) - static int layerdisktab[12][4] = {{0, 6, 8, 10}, - {0, 7, 9, -1}, - {1, 7, -1, -1}, - {6, 8, 10, -1}, - {2, 7, -1, -1}, - {2, 9, -1, -1}, - {3, 4, -1, -1}, - {4, -1, -1, -1}, - {5, -1, -1, -1}, - {5, 8, -1, -1}, - {6, 9, -1, -1}, - {7, 10, -1, -1}}; + // FIX: take this from DTC cabling map. + static const int layerdisktab[12][4] = {{0, 6, 8, 10}, + {0, 7, 9, -1}, + {1, 7, -1, -1}, + {6, 8, 10, -1}, + {2, 7, -1, -1}, + {2, 9, -1, -1}, + {3, 4, -1, -1}, + {4, -1, -1, -1}, + {5, -1, -1, -1}, + {5, 8, -1, -1}, + {6, 9, -1, -1}, + {7, 10, -1, -1}}; int layerdisk = layerdisktab[channel % 12][layercode]; assert(layerdisk != -1); @@ -501,45 +550,72 @@ void L1FPGATrackProducer::produce(edm::Event& iEvent, const edm::EventSetup& iSe for (unsigned int iClus = 0; iClus <= 1; iClus++) { // Loop over both clusters that make up stub. - const TTClusterRef& ttClusterRef = stub.first->clusterRef(iClus); + const TTClusterRef& ttClusterRef = stubRef->clusterRef(iClus); // Now identify all TP's contributing to either cluster in stub. - vector> vecTpPtr = MCTruthTTClusterHandle->findTrackingParticlePtrs(ttClusterRef); - - for (const edm::Ptr& tpPtr : vecTpPtr) { - if (translateTP.find(tpPtr) != translateTP.end()) { - if (iClus == 0) { - assocTPs.push_back(translateTP.at(tpPtr)); + if (readMoreMcTruth_) { + vector> vecTpPtr = + MCTruthTTClusterHandle->findTrackingParticlePtrs(ttClusterRef); + + for (const edm::Ptr& tpPtr : vecTpPtr) { + if (translateTP.find(tpPtr) != translateTP.end()) { + if (iClus == 0) { + assocTPs.push_back(translateTP.at(tpPtr)); + } else { + assocTPs.push_back(-translateTP.at(tpPtr)); + } + // N.B. Since not all tracking particles are stored in InputData::vTPs_, sometimes no match will be found. } else { - assocTPs.push_back(-translateTP.at(tpPtr)); + assocTPs.push_back(0); } - // N.B. Since not all tracking particles are stored in InputData::vTPs_, sometimes no match will be found. - } else { - assocTPs.push_back(0); } } } - double stubbend = stub.first->bendFE(); //stub.first->rawBend() + double stubbend = stubRef->bendFE(); //stubRef->rawBend() if (ttPos.z() < -120) { stubbend = -stubbend; } + bool barrel = (layerdisk < N_LAYER); + // See https://github.com/cms-sw/cmssw/tree/master/Geometry/TrackerNumberingBuilder + enum TypeBarrel { nonBarrel = 0, tiltedMinus = 1, tiltedPlus = 2, flat = 3 }; + const TypeBarrel type = static_cast(tTopo->tobSide(innerDetId)); + bool tiltedBarrel = barrel && (type == tiltedMinus || type == tiltedPlus); + unsigned int tiltedRingId = 0; + // Tilted module ring no. (Increasing 1 to 12 as |z| increases). + if (tiltedBarrel) { + tiltedRingId = tTopo->tobRod(innerDetId); + if (type == tiltedMinus) { + unsigned int layp1 = 1 + layerdisk; // Setup counts from 1 + unsigned int nTilted = setup_->numTiltedLayerRing(layp1); + tiltedRingId = 1 + nTilted - tiltedRingId; + } + } + // Endcap module ring number (1-15) in endcap disks. + unsigned int endcapRingId = barrel ? 0 : tTopo->tidRing(innerDetId); + + const unsigned int intDetId = innerDetId.rawId(); + ev.addStub(dtcname, region, layerdisk, stubwordhex, - setup_.psModule(setup_.dtcId(region, channel)), + setup_->psModule(dtcId), isFlipped, + tiltedBarrel, + tiltedRingId, + endcapRingId, + intDetId, ttPos.x(), ttPos.y(), ttPos.z(), stubbend, - stub.first->innerClusterPosition(), + stubRef->innerClusterPosition(), assocTPs); const trklet::L1TStub& lastStub = ev.lastStub(); - stubMap[lastStub] = stub.first; + stubMap[lastStub] = stubRef; } } } @@ -553,8 +629,20 @@ void L1FPGATrackProducer::produce(edm::Event& iEvent, const edm::EventSetup& iSe const std::vector& tracks = eventProcessor.tracks(); + const unsigned int maxNumProjectionLayers = channelAssignment_->maxNumProjectionLayers(); + // number of track channels + const unsigned int numStreamsTrack = N_SECTOR * channelAssignment_->numChannelsTrack(); + // number of stub channels + const unsigned int numStreamsStub = N_SECTOR * channelAssignment_->numChannelsStub(); + // number of stub channels if all seed types streams padded to have same number of stub channels (for coding simplicity) + const unsigned int numStreamsStubRaw = numStreamsTrack * maxNumProjectionLayers; + + // Streams formatted to allow this code to run outside CMSSW. + vector> streamsTrackRaw(numStreamsTrack); + vector> streamsStubRaw(numStreamsStubRaw); + // this performs the actual tracklet event processing - eventProcessor.event(ev); + eventProcessor.event(ev, streamsTrackRaw, streamsStubRaw); int ntracks = 0; @@ -565,11 +653,11 @@ void L1FPGATrackProducer::produce(edm::Event& iEvent, const edm::EventSetup& iSe ntracks++; // this is where we create the TTTrack object - double tmp_rinv = track.rinv(settings); - double tmp_phi = track.phi0(settings); - double tmp_tanL = track.tanL(settings); - double tmp_z0 = track.z0(settings); - double tmp_d0 = track.d0(settings); + double tmp_rinv = track.rinv(settings_); + double tmp_phi = track.phi0(settings_); + double tmp_tanL = track.tanL(settings_); + double tmp_z0 = track.z0(settings_); + double tmp_d0 = track.d0(settings_); double tmp_chi2rphi = track.chisqrphi(); double tmp_chi2rz = track.chisqrz(); unsigned int tmp_hit = track.hitpattern(); @@ -585,8 +673,8 @@ void L1FPGATrackProducer::produce(edm::Event& iEvent, const edm::EventSetup& iSe 0, 0, tmp_hit, - settings.nHelixPar(), - settings.bfield()); + settings_.nHelixPar(), + settings_.bfield()); unsigned int trksector = track.sector(); unsigned int trkseed = (unsigned int)abs(track.seed()); @@ -614,7 +702,7 @@ void L1FPGATrackProducer::produce(edm::Event& iEvent, const edm::EventSetup& iSe // pt consistency aTrack.setStubPtConsistency( - StubPtConsistency::getConsistency(aTrack, theTrackerGeom, tTopo, settings.bfield(), settings.nHelixPar())); + StubPtConsistency::getConsistency(aTrack, theTrackerGeom, tTopo, settings_.bfield(), settings_.nHelixPar())); // set TTTrack word aTrack.setTrackWordBits(); @@ -631,6 +719,46 @@ void L1FPGATrackProducer::produce(edm::Event& iEvent, const edm::EventSetup& iSe iEvent.put(std::move(L1TkTracksForOutput), "Level1TTTracks"); + // produce clock and bit accurate stream output tracks and stubs. + // from end of tracklet pattern recognition. + // Convertion here is from stream format that allows this code to run + // outside CMSSW to the EDProduct one. + Streams streamsTrack(numStreamsTrack); + StreamsStub streamsStub(numStreamsStub); + + for (unsigned int chanTrk = 0; chanTrk < numStreamsTrack; chanTrk++) { + for (unsigned int itk = 0; itk < streamsTrackRaw[chanTrk].size(); itk++) { + std::string bitsTrk = streamsTrackRaw[chanTrk][itk]; + int iSeed = chanTrk % channelAssignment_->numChannelsTrack(); // seed type + streamsTrack[chanTrk].emplace_back(bitsTrk); + + const unsigned int chanStubOffsetIn = chanTrk * maxNumProjectionLayers; + const unsigned int chanStubOffsetOut = channelAssignment_->offsetStub(chanTrk); + const unsigned int numProjLayers = channelAssignment_->numProjectionLayers(iSeed); + TTBV hitMap(0, numProjLayers); + // remove padding from stub stream + for (unsigned int iproj = 0; iproj < maxNumProjectionLayers; iproj++) { + // FW current has one (perhaps invalid) stub per layer per track. + const StubStreamData& stubdata = streamsStubRaw[chanStubOffsetIn + iproj][itk]; + const L1TStub& stub = stubdata.stub(); + if (stubdata.valid()) { + const TTStubRef ttStubRef = stubMap[stub]; + int layerId(-1); + if (!channelAssignment_->layerId(stubdata.iSeed(), ttStubRef, layerId)) + continue; + hitMap.set(layerId); + streamsStub[chanStubOffsetOut + layerId].emplace_back(ttStubRef, stubdata.dataBits()); + } + } + for (int layerId : hitMap.ids(false)) { // invalid stubs + streamsStub[chanStubOffsetOut + layerId].emplace_back(tt::FrameStub()); + } + } + } + + iEvent.emplace(putTokenTracks_, move(streamsTrack)); + iEvent.emplace(putTokenStubs_, move(streamsStub)); + } /// End of produce() // /////////////////////////// diff --git a/L1Trigger/TrackFindingTracklet/plugins/ProducerAS.cc b/L1Trigger/TrackFindingTracklet/plugins/ProducerAS.cc new file mode 100644 index 0000000000000..2f45cdee83143 --- /dev/null +++ b/L1Trigger/TrackFindingTracklet/plugins/ProducerAS.cc @@ -0,0 +1,99 @@ +#include "FWCore/Framework/interface/stream/EDProducer.h" +#include "FWCore/Framework/interface/Run.h" +#include "FWCore/Framework/interface/EventSetup.h" +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/MakerMacros.h" +#include "FWCore/Utilities/interface/EDGetToken.h" +#include "FWCore/Utilities/interface/EDPutToken.h" +#include "FWCore/Utilities/interface/ESGetToken.h" +#include "FWCore/Utilities/interface/InputTag.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "DataFormats/Common/interface/Handle.h" + +#include "DataFormats/L1TrackTrigger/interface/TTTypes.h" +#include "L1Trigger/TrackTrigger/interface/Setup.h" + +#include + +using namespace std; +using namespace edm; +using namespace tt; + +namespace trklet { + + /*! \class trklet::ProducerAS + * \brief Associate the TTTracks output by KF fitter with the tracks input to KF fitter. + * \author Thomas Schuh + * \date 2020, Oct + */ + class ProducerAS : public stream::EDProducer<> { + public: + explicit ProducerAS(const ParameterSet&); + ~ProducerAS() override {} + + private: + void beginRun(const Run&, const EventSetup&) override; + void produce(Event&, const EventSetup&) override; + void endJob() {} + + // ED input token of kf tracks + EDGetTokenT edGetTokenKF_; + // ED input token of kf TTtracks + EDGetTokenT edGetTokenTT_; + // ED output token for TTTrackRefMap + EDPutTokenT edPutToken_; + // Setup token + ESGetToken esGetTokenSetup_; + // configuration + ParameterSet iConfig_; + // helper class to store configurations + const Setup* setup_; + }; + + ProducerAS::ProducerAS(const ParameterSet& iConfig) : iConfig_(iConfig) { + const string& labelKF = iConfig.getParameter("LabelKF"); + const string& labelTT = iConfig.getParameter("LabelTT"); + const string& branch = iConfig.getParameter("BranchAcceptedTracks"); + // book in- and output ED products + edGetTokenKF_ = consumes(InputTag(labelKF, branch)); + edGetTokenTT_ = consumes(InputTag(labelTT, branch)); + edPutToken_ = produces(branch); + // book ES products + esGetTokenSetup_ = esConsumes(); + // initial ES products + setup_ = nullptr; + } + + void ProducerAS::beginRun(const Run& iRun, const EventSetup& iSetup) { + // helper class to store configurations + setup_ = &iSetup.getData(esGetTokenSetup_); + if (!setup_->configurationSupported()) + return; + // check process history if desired + if (iConfig_.getParameter("CheckHistory")) + setup_->checkHistory(iRun.processHistory()); + } + + void ProducerAS::produce(Event& iEvent, const EventSetup& iSetup) { + // empty KFTTTrack product + TTTrackRefMap ttTrackMap; + // read in KF Product and produce AssociatorKF product + if (setup_->configurationSupported()) { + Handle handleKF; + iEvent.getByToken(edGetTokenKF_, handleKF); + const StreamsTrack& streams = *handleKF.product(); + Handle handleTT; + iEvent.getByToken(edGetTokenTT_, handleTT); + int i(0); + for (const StreamTrack& stream : streams) + for (const FrameTrack& frame : stream) + if (frame.first.isNonnull()) + ttTrackMap.emplace(TTTrackRef(handleTT, i++), frame.first); + } + // store products + iEvent.emplace(edPutToken_, move(ttTrackMap)); + } + +} // namespace trklet + +DEFINE_FWK_MODULE(trklet::ProducerAS); \ No newline at end of file diff --git a/L1Trigger/TrackFindingTracklet/plugins/ProducerChannelAssignment.cc b/L1Trigger/TrackFindingTracklet/plugins/ProducerChannelAssignment.cc new file mode 100644 index 0000000000000..4671dfaefb3ef --- /dev/null +++ b/L1Trigger/TrackFindingTracklet/plugins/ProducerChannelAssignment.cc @@ -0,0 +1,45 @@ +#include "FWCore/Framework/interface/ESProducer.h" +#include "FWCore/Framework/interface/ModuleFactory.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/Utilities/interface/ESGetToken.h" +#include "L1Trigger/TrackFindingTracklet/interface/ChannelAssignment.h" +#include "L1Trigger/TrackTrigger/interface/Setup.h" + +#include + +using namespace std; +using namespace edm; +using namespace tt; + +namespace trklet { + + /*! \class trklet::ProducerChannelAssignment + * \brief Creates ChannelAssignment class that assigns tracklet tracks and stubs + * to output channel as well as DTC stubs to input channel + * \author Thomas Schuh + * \date 2020, Nov + */ + class ProducerChannelAssignment : public ESProducer { + public: + ProducerChannelAssignment(const ParameterSet& iConfig); + ~ProducerChannelAssignment() override {} + unique_ptr produce(const ChannelAssignmentRcd& rcd); + + private: + const ParameterSet* iConfig_; + ESGetToken esGetToken_; + }; + + ProducerChannelAssignment::ProducerChannelAssignment(const ParameterSet& iConfig) : iConfig_(&iConfig) { + auto cc = setWhatProduced(this); + esGetToken_ = cc.consumes(); + } + + unique_ptr ProducerChannelAssignment::produce(const ChannelAssignmentRcd& rcd) { + const Setup* setup = &rcd.get(esGetToken_); + return make_unique(*iConfig_, setup); + } + +} // namespace trklet + +DEFINE_FWK_EVENTSETUP_MODULE(trklet::ProducerChannelAssignment); diff --git a/L1Trigger/TrackFindingTracklet/plugins/ProducerKFin.cc b/L1Trigger/TrackFindingTracklet/plugins/ProducerKFin.cc new file mode 100644 index 0000000000000..eec2af036e659 --- /dev/null +++ b/L1Trigger/TrackFindingTracklet/plugins/ProducerKFin.cc @@ -0,0 +1,156 @@ +#include "FWCore/Framework/interface/stream/EDProducer.h" +#include "FWCore/Framework/interface/Run.h" +#include "FWCore/Framework/interface/EventSetup.h" +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/MakerMacros.h" +#include "FWCore/Utilities/interface/EDGetToken.h" +#include "FWCore/Utilities/interface/EDPutToken.h" +#include "FWCore/Utilities/interface/ESGetToken.h" +#include "FWCore/Utilities/interface/InputTag.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "DataFormats/Common/interface/Handle.h" + +#include "L1Trigger/TrackTrigger/interface/Setup.h" +#include "L1Trigger/TrackerTFP/interface/DataFormats.h" +#include "L1Trigger/TrackerTFP/interface/LayerEncoding.h" +#include "L1Trigger/TrackFindingTracklet/interface/ChannelAssignment.h" +#include "L1Trigger/TrackFindingTracklet/interface/Settings.h" +#include "L1Trigger/TrackFindingTracklet/interface/KFin.h" +#include "SimTracker/TrackTriggerAssociation/interface/TTTypes.h" + +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace edm; +using namespace trackerTFP; +using namespace tt; + +namespace trklet { + + /*! \class trklet::ProducerKFin + * \brief Transforms format of TBout into that expected by KF input. + * \author Thomas Schuh + * \date 2020, Oct; updated 2021, Dec + */ + class ProducerKFin : public stream::EDProducer<> { + public: + explicit ProducerKFin(const ParameterSet&); + ~ProducerKFin() override {} + + private: + void beginRun(const Run&, const EventSetup&) override; + void produce(Event&, const EventSetup&) override; + virtual void endJob() {} + + // ED input token of Tracks + EDGetTokenT edGetTokenTracks_; + // ED input token of Stubs + EDGetTokenT edGetTokenStubs_; + // ED output token for stubs + EDPutTokenT edPutTokenAcceptedStubs_; + EDPutTokenT edPutTokenLostStubs_; + // ED output token for tracks + EDPutTokenT edPutTokenAcceptedTracks_; + EDPutTokenT edPutTokenLostTracks_; + // Setup token + ESGetToken esGetTokenSetup_; + // DataFormats token + ESGetToken esGetTokenDataFormats_; + // LayerEncoding token + ESGetToken esGetTokenLayerEncoding_; + // ChannelAssignment token + ESGetToken esGetTokenChannelAssignment_; + // configuration + ParameterSet iConfig_; + // helper class to store configurations + const Setup* setup_; + // helper class to extract structured data from tt::Frames + const DataFormats* dataFormats_; + // helper class to encode layer + const LayerEncoding* layerEncoding_; + // helper class to assign tracks to channel + const ChannelAssignment* channelAssignment_; + // helper class to store tracklet configurations + Settings settings_; + }; + + ProducerKFin::ProducerKFin(const ParameterSet& iConfig) : iConfig_(iConfig) { + const string& label = iConfig.getParameter("LabelTBout"); + const string& branchAcceptedStubs = iConfig.getParameter("BranchAcceptedStubs"); + const string& branchAcceptedTracks = iConfig.getParameter("BranchAcceptedTracks"); + const string& branchLostStubs = iConfig.getParameter("BranchLostStubs"); + const string& branchLostTracks = iConfig.getParameter("BranchLostTracks"); + // book in- and output ED products + edGetTokenTracks_ = consumes(InputTag(label, branchAcceptedTracks)); + edGetTokenStubs_ = consumes(InputTag(label, branchAcceptedStubs)); + edPutTokenAcceptedStubs_ = produces(branchAcceptedStubs); + edPutTokenAcceptedTracks_ = produces(branchAcceptedTracks); + edPutTokenLostStubs_ = produces(branchLostStubs); + edPutTokenLostTracks_ = produces(branchLostTracks); + // book ES products + esGetTokenSetup_ = esConsumes(); + esGetTokenDataFormats_ = esConsumes(); + esGetTokenLayerEncoding_ = esConsumes(); + esGetTokenChannelAssignment_ = esConsumes(); + // initial ES products + setup_ = nullptr; + dataFormats_ = nullptr; + layerEncoding_ = nullptr; + channelAssignment_ = nullptr; + settings_ = Settings(); + } + + void ProducerKFin::beginRun(const Run& iRun, const EventSetup& iSetup) { + // helper class to store configurations + setup_ = &iSetup.getData(esGetTokenSetup_); + if (!setup_->configurationSupported()) + return; + // check process history if desired + if (iConfig_.getParameter("CheckHistory")) + setup_->checkHistory(iRun.processHistory()); + // helper class to extract structured data from tt::Frames + dataFormats_ = &iSetup.getData(esGetTokenDataFormats_); + // helper class to encode layer + layerEncoding_ = &iSetup.getData(esGetTokenLayerEncoding_); + // helper class to assign tracks to channel + channelAssignment_ = &iSetup.getData(esGetTokenChannelAssignment_); + } + + void ProducerKFin::produce(Event& iEvent, const EventSetup& iSetup) { + // empty KFin products + StreamsStub acceptedStubs(dataFormats_->numStreamsStubs(Process::kfin)); + StreamsTrack acceptedTracks(dataFormats_->numStreamsTracks(Process::kfin)); + StreamsStub lostStubs(dataFormats_->numStreamsStubs(Process::kfin)); + StreamsTrack lostTracks(dataFormats_->numStreamsTracks(Process::kfin)); + // read in TBout Product and produce KFin product + if (setup_->configurationSupported()) { + Handle handleStubs; + iEvent.getByToken(edGetTokenStubs_, handleStubs); + const StreamsStub& stubs = *handleStubs; + Handle handleTracks; + iEvent.getByToken(edGetTokenTracks_, handleTracks); + const StreamsTrack& tracks = *handleTracks; + for (int region = 0; region < setup_->numRegions(); region++) { + // object to reformat tracks from tracklet fromat to TMTT format in a processing region + KFin kfin(iConfig_, setup_, dataFormats_, layerEncoding_, channelAssignment_, &settings_, region); + // read in and organize input tracks and stubs + kfin.consume(tracks, stubs); + // fill output products + kfin.produce(acceptedStubs, acceptedTracks, lostStubs, lostTracks); + } + } + // store products + iEvent.emplace(edPutTokenAcceptedStubs_, move(acceptedStubs)); + iEvent.emplace(edPutTokenAcceptedTracks_, move(acceptedTracks)); + iEvent.emplace(edPutTokenLostStubs_, move(lostStubs)); + iEvent.emplace(edPutTokenLostTracks_, move(lostTracks)); + } + +} // namespace trklet + +DEFINE_FWK_MODULE(trklet::ProducerKFin); \ No newline at end of file diff --git a/L1Trigger/TrackFindingTracklet/plugins/ProducerKFout.cc b/L1Trigger/TrackFindingTracklet/plugins/ProducerKFout.cc new file mode 100644 index 0000000000000..f1db53d8a0f77 --- /dev/null +++ b/L1Trigger/TrackFindingTracklet/plugins/ProducerKFout.cc @@ -0,0 +1,334 @@ +#include "FWCore/Framework/interface/stream/EDProducer.h" +#include "FWCore/Framework/interface/Run.h" +#include "FWCore/Framework/interface/EventSetup.h" +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/MakerMacros.h" +#include "FWCore/Utilities/interface/EDGetToken.h" +#include "FWCore/Utilities/interface/EDPutToken.h" +#include "FWCore/Utilities/interface/ESGetToken.h" +#include "FWCore/Utilities/interface/InputTag.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "DataFormats/Common/interface/Handle.h" + +#include "L1Trigger/TrackTrigger/interface/Setup.h" +#include "L1Trigger/TrackerTFP/interface/DataFormats.h" +#include "L1Trigger/TrackerTFP/interface/DistServer.h" + +#include +#include + +using namespace std; +using namespace edm; +using namespace trackerTFP; +using namespace tt; + +namespace trklet { + + /*! \class trklet::ProducerKFout + * \brief Converts KF output into TFP output + * \author Christopher Brown + * \date 2021, Aug + */ + class ProducerKFout : public stream::EDProducer<> { + public: + explicit ProducerKFout(const ParameterSet&); + ~ProducerKFout() override {} + template + int digitise(const vector Bins, T Value, T factor = 1); + + private: + void beginRun(const Run&, const EventSetup&) override; + void produce(Event&, const EventSetup&) override; + void endJob() {} + + // ED input token of kf stubs + EDGetTokenT edGetTokenStubs_; + // ED input token of kf tracks + EDGetTokenT edGetTokenTracks_; + // ED input token of kf input to kf output TTTrack map + EDGetTokenT edGetTokenTTTrackRefMap_; + // ED output token for accepted kfout tracks + EDPutTokenT edPutTokenAccepted_; + // ED output token for truncated kfout tracks + EDPutTokenT edPutTokenLost_; + // Setup token + ESGetToken esGetTokenSetup_; + // DataFormats token + ESGetToken esGetTokenDataFormats_; + // configuration + ParameterSet iConfig_; + // helper class to store configurations + const Setup* setup_; + // helper class to extract structured data from tt::Frames + const DataFormats* dataFormats_; + // Bins for dPhi/dZ use to create weight LUT + vector dPhiBins_; + vector dZBins_; + + // Constant used throughout for partial ttrack words + int partialTrackWordBits_; + + // For convenience and keeping readable code, accessed many times + int numWorkers_; + }; + + ProducerKFout::ProducerKFout(const ParameterSet& iConfig) : iConfig_(iConfig) { + const string& labelKF = iConfig.getParameter("LabelKF"); + const string& labelAS = iConfig.getParameter("LabelAS"); + const string& branchStubs = iConfig.getParameter("BranchAcceptedStubs"); + const string& branchTracks = iConfig.getParameter("BranchAcceptedTracks"); + const string& branchLost = iConfig.getParameter("BranchLostTracks"); + // book in- and output ED products + edGetTokenStubs_ = consumes(InputTag(labelKF, branchStubs)); + edGetTokenTracks_ = consumes(InputTag(labelKF, branchTracks)); + edGetTokenTTTrackRefMap_ = consumes(InputTag(labelAS, branchTracks)); + edPutTokenAccepted_ = produces(branchTracks); + edPutTokenLost_ = produces(branchLost); + // book ES products + esGetTokenSetup_ = esConsumes(); + esGetTokenDataFormats_ = esConsumes(); + // initial ES products + setup_ = nullptr; + dataFormats_ = nullptr; + } + + void ProducerKFout::beginRun(const Run& iRun, const EventSetup& iSetup) { + // helper class to store configurations + setup_ = &iSetup.getData(esGetTokenSetup_); + if (!setup_->configurationSupported()) + return; + // check process history if desired + if (iConfig_.getParameter("CheckHistory")) + setup_->checkHistory(iRun.processHistory()); + // helper class to extract structured data from tt::Frames + dataFormats_ = &iSetup.getData(esGetTokenDataFormats_); + + // Calculate 1/dz**2 and 1/dphi**2 bins for v0 and v1 weightings + for (int i = 0; + i < pow(2, dataFormats_->width(Variable::dPhi, Process::kfin)) / pow(2, setup_->weightBinFraction()); + i++) + dPhiBins_.push_back( + pow(dataFormats_->base(Variable::dPhi, Process::kfin) * (i + 1) * pow(2, setup_->weightBinFraction()), -2)); + + for (int i = 0; i < pow(2, dataFormats_->width(Variable::dZ, Process::kfin)) / pow(2, setup_->weightBinFraction()); + i++) + dZBins_.push_back( + pow(dataFormats_->base(Variable::dZ, Process::kfin) * (i + 1) * pow(2, setup_->weightBinFraction()), -2)); + + partialTrackWordBits_ = TTBV::S_ / 2; + numWorkers_ = setup_->kfNumWorker(); + } + + // Helper function to convert floating chi2 to chi2 bin + template + int ProducerKFout::digitise(const vector Bins, T Value, T factor) { + for (int i = 0; i < (int)Bins.size(); i++) { + if (Value * factor > Bins[i] && Value * factor <= Bins[i + 1]) { + return i; + } + } + return -1; + } + + void ProducerKFout::produce(Event& iEvent, const EventSetup& iSetup) { + // empty KFout product + StreamsTrack accepted(setup_->numRegions() * setup_->tfpNumChannel()); + StreamsTrack lost(setup_->numRegions() * setup_->tfpNumChannel()); + // read in KF Product and produce KFout product + if (setup_->configurationSupported()) { + Handle handleStubs; + iEvent.getByToken(edGetTokenStubs_, handleStubs); + const StreamsStub& streamsStubs = *handleStubs.product(); + Handle handleTracks; + iEvent.getByToken(edGetTokenTracks_, handleTracks); + const StreamsTrack& streamsTracks = *handleTracks.product(); + Handle handleTTTrackRefMap; + iEvent.getByToken(edGetTokenTTTrackRefMap_, handleTTTrackRefMap); + const TTTrackRefMap& ttTrackRefMap = *handleTTTrackRefMap.product(); + // 18 Output Links (First Vector) each has a vector of tracks per event (second vector) each track is 3 32 bit TTBV partial tracks + vector> SortedPartialTracks(setup_->numRegions() * setup_->tfpNumChannel(), vector(0)); + + TrackKFOutSAPtrCollectionss InTrackStreams; + TrackKFOutSAPtrCollectionss OutTrackStreams; + + // Setup empty collections for input tracks to distribution server + for (int iRegion = 0; iRegion < setup_->numRegions(); iRegion++) { + TrackKFOutSAPtrCollections temp_collection; + for (int iLink = 0; iLink < setup_->tfpNumChannel(); iLink++) { + TrackKFOutSAPtrCollection temp; + for (int iTrack = 0; iTrack < setup_->numFramesIO(); iTrack++) + temp.emplace_back(std::make_shared()); + temp_collection.push_back(temp); + } + OutTrackStreams.push_back(temp_collection); + } + + // Setup empty collections for oiutpu tracks from distribution server + for (int iRegion = 0; iRegion < setup_->numRegions(); iRegion++) { + TrackKFOutSAPtrCollections temp_collection; + for (int iLink = 0; iLink < numWorkers_; iLink++) { + TrackKFOutSAPtrCollection temp; + for (int iTrack = 0; iTrack < setup_->numFramesIO(); iTrack++) + temp.emplace_back(std::make_shared()); + temp_collection.push_back(temp); + } + InTrackStreams.push_back(temp_collection); + } + + StreamsTrack OutputStreamsTracks(setup_->numRegions() * setup_->tfpNumChannel()); + + for (int iLink = 0; iLink < (int)streamsTracks.size(); iLink++) { + for (int iTrack = 0; iTrack < (int)streamsTracks[iLink].size(); iTrack++) { + const auto& track = streamsTracks[iLink].at(iTrack); + TrackKF InTrack(track, dataFormats_); + + double temp_z0 = InTrack.zT() - ((InTrack.cot() * setup_->chosenRofZ())); + + // Correction to Phi calcuation depending if +ve/-ve phi sector + const double baseSectorCorr = InTrack.sectorPhi() ? -setup_->baseSector() : setup_->baseSector(); + + double temp_phi0 = InTrack.phiT() - ((InTrack.inv2R()) * setup_->hybridChosenRofPhi()) + baseSectorCorr; + + double temp_tanL = InTrack.cotGlobal(); + + TTBV HitPattern(0, setup_->numLayers()); + + double tempchi2rphi = 0; + double tempchi2rz = 0; + + for (int iStub = 0; iStub < setup_->numLayers() - 1; iStub++) { + const auto& stub = streamsStubs[setup_->numLayers() * iLink + iStub].at(iTrack); + StubKF InStub(stub, dataFormats_, iStub); + + if (!stub.first.isNonnull()) + continue; + + HitPattern.set(iStub); + double phiSquared = pow(InStub.phi(), 2); + double zSquared = pow(InStub.z(), 2); + + double tempv0 = dPhiBins_[(InStub.dPhi() / (dataFormats_->base(Variable::dPhi, Process::kfin) * + pow(2, setup_->weightBinFraction())))]; + double tempv1 = dZBins_[( + InStub.dZ() / (dataFormats_->base(Variable::dZ, Process::kfin) * pow(2, setup_->weightBinFraction())))]; + + double tempRphi = phiSquared * tempv0; + double tempRz = zSquared * tempv1; + + tempchi2rphi += tempRphi; + tempchi2rz += tempRz; + } // Iterate over track stubs + + // TODO extract TTTrack bit widths from TTTrack word pending update to the TTTrack_word class + TTBV TrackValid(1, 1, false); + TTBV extraMVA(0, 6, false); + TTBV TQMVA(0, 3, false); + TTBV BendChi2(0, 3, false); + TTBV Chi2rphi( + digitise(setup_->kfoutchi2rphiBins(), tempchi2rphi, (double)setup_->kfoutchi2rphiConv()), 4, false); + TTBV Chi2rz(digitise(setup_->kfoutchi2rzBins(), tempchi2rz, (double)setup_->kfoutchi2rzConv()), 4, false); + TTBV D0(0, 13, false); + TTBV z0(temp_z0, dataFormats_->base(Variable::zT, Process::kf), 12, true); + TTBV TanL(temp_tanL, dataFormats_->base(Variable::cot, Process::kf), 16, true); + TTBV phi0(temp_phi0, dataFormats_->base(Variable::phiT, Process::kf), 12, true); + TTBV InvR(-InTrack.inv2R(), dataFormats_->base(Variable::inv2R, Process::kf), 16, true); + InvR.resize(15); + // 13 + 3 + 7 + 3 + 3 + TTBV PartialTrack3((D0 + BendChi2 + HitPattern + TQMVA + extraMVA), partialTrackWordBits_, false); + // 16 + 12 + 4 + TTBV PartialTrack2((TanL + z0 + Chi2rz), partialTrackWordBits_, false); + // 1 + 15 + 12 + 4 + TTBV PartialTrack1((TrackValid + InvR + phi0 + Chi2rphi), partialTrackWordBits_, false); + + int sortKey = (InTrack.sectorEta() < (int)(setup_->numSectorsEta() / 2)) ? 0 : 1; + // Set correct bit to valid for track valid + TrackKFOut Temp_track( + PartialTrack1.set(31), PartialTrack2, PartialTrack3, sortKey, track, iTrack, iLink, true); + + InTrackStreams[iLink / numWorkers_][iLink % numWorkers_][iTrack] = (std::make_shared(Temp_track)); + + } // Iterate over Tracks + + //Pad out input streams to Dist server with extra null track if odd number of tracks on a stream + int iFinTrack = (int)streamsTracks[iLink].size(); + if (iFinTrack % numWorkers_ != 0) { + TrackKFOut null_track(0, 0, 0, iLink % numWorkers_, tt::FrameTrack(), iFinTrack + 1, iLink, true); + InTrackStreams[iLink / numWorkers_][iLink % numWorkers_][iFinTrack] = + (std::make_shared(null_track)); + } + } // Iterate over Links + // Fill products and match up tracks + + // One distribution server for every region, num inputs = num KF workers, num outputs = num output links + vector distServers( + setup_->numRegions(), + DistServer(numWorkers_, setup_->tfpNumChannel(), 2)); //Magic number for interleaving in dist server + + for (int iRegion = 0; iRegion < setup_->numRegions(); iRegion++) { + for (int iTrack = 0; iTrack < setup_->numFramesIO() * ((double)TTBV::S_ / setup_->tttrackBits()); iTrack++) { + TrackKFOutSAPtrCollection DistIn; + for (int iWorker = 0; iWorker < numWorkers_; iWorker++) + DistIn.push_back(InTrackStreams[iRegion][iWorker][iTrack]); // Reorganise input to distribution server + TrackKFOutSAPtrCollection DistOut = distServers[iRegion].clock(DistIn); // Run dist server + for (int iLink = 0; iLink < setup_->tfpNumChannel(); iLink++) + OutTrackStreams[iRegion][iLink][iTrack] = + DistOut[iLink]; // Reorganise output of distribution server in output streams + } + } + + // Pack output of distribution server onto each link, with correct partial tracks in correct places + for (int iRegion = 0; iRegion < setup_->numRegions(); iRegion++) { + for (int iLink = 0; iLink < setup_->tfpNumChannel(); iLink++) { + for (int iTrack = 0; iTrack < (int)OutTrackStreams[iRegion][iLink].size(); iTrack++) { + SortedPartialTracks[2 * iRegion + iLink].push_back( + OutTrackStreams[iRegion][iLink][iTrack]->PartialTrack1()); + SortedPartialTracks[2 * iRegion + iLink].push_back( + OutTrackStreams[iRegion][iLink][iTrack]->PartialTrack2()); + SortedPartialTracks[2 * iRegion + iLink].push_back( + OutTrackStreams[iRegion][iLink][iTrack]->PartialTrack3()); + OutputStreamsTracks[2 * iRegion + iLink].emplace_back(OutTrackStreams[iRegion][iLink][iTrack]->track()); + } + } + } + + const TTBV NullBitTrack(0, partialTrackWordBits_, false); + for (int iLink = 0; iLink < (int)OutputStreamsTracks.size(); iLink++) { + // Iterate through partial tracks + int numLinkTracks = (int)OutputStreamsTracks[iLink].size(); + if (numLinkTracks == 0) + continue; // Don't fill links if no tracks + if ((numLinkTracks % 2 != 0)) { + SortedPartialTracks[iLink].push_back(NullBitTrack); //Pad out final set of bits + OutputStreamsTracks[iLink].emplace_back( + OutputStreamsTracks[iLink][numLinkTracks++]); //Pad out with final repeated track + } //If there is an odd number of tracks + for (int iTrack = 0; iTrack < (int)(SortedPartialTracks[iLink].size()); iTrack++) { + if (iTrack % 2 != 1) // Write to links every other partial track, 3 partial tracks per full TTTrack + continue; + TTTrackRef TrackRef; + for (auto& it : ttTrackRefMap) { //Iterate through ttTrackRefMap to find TTTrackRef Key by a TTTrack Value + if (it.second == OutputStreamsTracks[iLink][(int)(iTrack - 1) / 3].first) + TrackRef = it.first; + } + if ((int)iTrack / 3 <= setup_->numFramesIO() * ((double)TTBV::S_ / setup_->tttrackBits())) + accepted[iLink].emplace_back( + std::make_pair(TrackRef, + (SortedPartialTracks[iLink][iTrack - 1].slice(partialTrackWordBits_) + + SortedPartialTracks[iLink][iTrack].slice(partialTrackWordBits_)) + .bs())); + else + lost[iLink].emplace_back( + std::make_pair(TrackRef, + (SortedPartialTracks[iLink][iTrack - 1].slice(partialTrackWordBits_) + + SortedPartialTracks[iLink][iTrack].slice(partialTrackWordBits_)) + .bs())); + } //Iterate through sorted partial tracks + } // Iterate through links + } // Config Supported + // store products + iEvent.emplace(edPutTokenAccepted_, move(accepted)); + iEvent.emplace(edPutTokenLost_, move(lost)); + } +} // namespace trklet + +DEFINE_FWK_MODULE(trklet::ProducerKFout); diff --git a/L1Trigger/TrackFindingTracklet/plugins/ProducerTBout.cc b/L1Trigger/TrackFindingTracklet/plugins/ProducerTBout.cc new file mode 100644 index 0000000000000..5dbfe96de2e43 --- /dev/null +++ b/L1Trigger/TrackFindingTracklet/plugins/ProducerTBout.cc @@ -0,0 +1,199 @@ +#include "FWCore/Framework/interface/stream/EDProducer.h" +#include "FWCore/Framework/interface/Run.h" +#include "FWCore/Framework/interface/EventSetup.h" +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/MakerMacros.h" +#include "FWCore/Utilities/interface/EDGetToken.h" +#include "FWCore/Utilities/interface/EDPutToken.h" +#include "FWCore/Utilities/interface/ESGetToken.h" +#include "FWCore/Utilities/interface/InputTag.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "DataFormats/Common/interface/Handle.h" + +#include "L1Trigger/TrackTrigger/interface/Setup.h" +#include "L1Trigger/TrackerTFP/interface/DataFormats.h" +#include "L1Trigger/TrackFindingTracklet/interface/ChannelAssignment.h" +#include "L1Trigger/TrackFindingTracklet/interface/Settings.h" + +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace edm; +using namespace trackerTFP; +using namespace tt; + +namespace trklet { + + /*! \class trklet::ProducerTBout + * \brief Transforms TTTracks and Streams from Tracklet pattern reco. into StreamsTrack + * by adding to the digitised track stream a reference to the corresponding TTTrack. + * (Could not be done in previous L1TrackFPGAProducer, as single EDProducer can't + * produce output containing both an EDProduct and refs to that product). + * Writes Tracks & stubs rejected/kept after truncation to separate StreamsTrack & StreamsStub branches. + * \author Thomas Schuh + * \date 2021, Oct + */ + class ProducerTBout : public stream::EDProducer<> { + public: + explicit ProducerTBout(const ParameterSet&); + ~ProducerTBout() override {} + + private: + void beginRun(const Run&, const EventSetup&) override; + void produce(Event&, const EventSetup&) override; + virtual void endJob() {} + + // ED input token of TTTracks + EDGetTokenT edGetTokenTTTracks_; + // ED input token of Tracklet tracks + EDGetTokenT edGetTokenTracks_; + // ED input token of Tracklet Stubs + EDGetTokenT edGetTokenStubs_; + // ED output token for stubs + EDPutTokenT edPutTokenAcceptedStubs_; + EDPutTokenT edPutTokenLostStubs_; + // ED output token for tracks + EDPutTokenT edPutTokenAcceptedTracks_; + EDPutTokenT edPutTokenLostTracks_; + // Setup token + ESGetToken esGetTokenSetup_; + // DataFormats token + ESGetToken esGetTokenDataFormats_; + // ChannelAssignment token + ESGetToken esGetTokenChannelAssignment_; + // configuration + ParameterSet iConfig_; + // helper class to store configurations + const Setup* setup_; + // helper class to extract structured data from tt::Frames + const DataFormats* dataFormats_; + // helper class to assign tracks to channel + ChannelAssignment* channelAssignment_; + // + bool enableTruncation_; + // + trklet::Settings settings_; + }; + + ProducerTBout::ProducerTBout(const ParameterSet& iConfig) : iConfig_(iConfig) { + const InputTag& inputTag = iConfig.getParameter("InputTag"); + const string& branchAcceptedStubs = iConfig.getParameter("BranchAcceptedStubs"); + const string& branchAcceptedTracks = iConfig.getParameter("BranchAcceptedTracks"); + const string& branchLostStubs = iConfig.getParameter("BranchLostStubs"); + const string& branchLostTracks = iConfig.getParameter("BranchLostTracks"); + // book in- and output ED products + edGetTokenTTTracks_ = consumes(inputTag); + edGetTokenTracks_ = consumes(inputTag); + edGetTokenStubs_ = consumes(inputTag); + edPutTokenAcceptedStubs_ = produces(branchAcceptedStubs); + edPutTokenAcceptedTracks_ = produces(branchAcceptedTracks); + edPutTokenLostStubs_ = produces(branchLostStubs); + edPutTokenLostTracks_ = produces(branchLostTracks); + // book ES products + esGetTokenSetup_ = esConsumes(); + esGetTokenDataFormats_ = esConsumes(); + esGetTokenChannelAssignment_ = esConsumes(); + // initial ES products + setup_ = nullptr; + dataFormats_ = nullptr; + channelAssignment_ = nullptr; + // + enableTruncation_ = iConfig.getParameter("EnableTruncation"); + } + + void ProducerTBout::beginRun(const Run& iRun, const EventSetup& iSetup) { + // helper class to store configurations + setup_ = &iSetup.getData(esGetTokenSetup_); + if (!setup_->configurationSupported()) + return; + // check process history if desired + if (iConfig_.getParameter("CheckHistory")) + setup_->checkHistory(iRun.processHistory()); + // helper class to extract structured data from tt::Frames + dataFormats_ = &iSetup.getData(esGetTokenDataFormats_); + // helper class to assign tracks to channel + channelAssignment_ = const_cast(&iSetup.getData(esGetTokenChannelAssignment_)); + } + + void ProducerTBout::produce(Event& iEvent, const EventSetup& iSetup) { + const int numStreamsTracks = setup_->numRegions() * channelAssignment_->numChannelsTrack(); + const int numStreamsStubs = setup_->numRegions() * channelAssignment_->numChannelsStub(); + // empty KFin products + StreamsStub streamAcceptedStubs(numStreamsStubs); + StreamsTrack streamAcceptedTracks(numStreamsTracks); + StreamsStub streamLostStubs(numStreamsStubs); + StreamsTrack streamLostTracks(numStreamsTracks); + // read in hybrid track finding product and produce KFin product + if (setup_->configurationSupported()) { + // create and structure TTrackRefs in h/w channel + vector> ttTrackRefs(numStreamsTracks); + Handle handleTTTracks; + iEvent.getByToken(edGetTokenTTTracks_, handleTTTracks); + int channelId(-1); + for (int i = 0; i < (int)handleTTTracks->size(); i++) { + const TTTrackRef ttTrackRef(handleTTTracks, i); + if (channelAssignment_->channelId(ttTrackRef, channelId)) + ttTrackRefs[channelId].push_back(ttTrackRef); + } + // get and trunacte tracks + Handle handleTracks; + iEvent.getByToken(edGetTokenTracks_, handleTracks); + channelId = 0; + for (const Stream& streamTrack : *handleTracks) { + const int nTracks = accumulate( + streamTrack.begin(), streamTrack.end(), 0, [](int& sum, const Frame& f) { return sum += f.any() ? 1 : 0; }); + StreamTrack& accepted = streamAcceptedTracks[channelId]; + StreamTrack& lost = streamLostTracks[channelId]; + auto limit = streamTrack.end(); + if (enableTruncation_ && (int)streamTrack.size() > setup_->numFrames()) + limit = next(streamTrack.begin(), setup_->numFrames()); + accepted.reserve(distance(streamTrack.begin(), limit)); + lost.reserve(distance(limit, streamTrack.end())); + int nFrame(0); + const deque& ttTracks = ttTrackRefs[channelId++]; + if ((int)ttTracks.size() != nTracks) { + cms::Exception exception("LogicError."); + const int region = channelId / channelAssignment_->numChannelsTrack(); + const int channel = channelId % channelAssignment_->numChannelsTrack(); + exception << "Region " << region << " output channel " << channel << " has " << nTracks + << " tracks found but created " << ttTracks.size() << " TTTracks."; + exception.addContext("trklet::ProducerTBout::produce"); + throw exception; + } + auto toFrameTrack = [&nFrame, &ttTracks](const Frame& frame) { + if (frame.any()) + return FrameTrack(ttTracks[nFrame++], frame); + return FrameTrack(); + }; + transform(streamTrack.begin(), limit, back_inserter(accepted), toFrameTrack); + transform(limit, streamTrack.end(), back_inserter(lost), toFrameTrack); + } + // get and trunacte stubs + Handle handleStubs; + iEvent.getByToken(edGetTokenStubs_, handleStubs); + const StreamsStub& streamsStub = *handleStubs; + // reserve output ed products + channelId = 0; + for (const StreamStub& streamStub : streamsStub) { + auto limit = streamStub.end(); + if (enableTruncation_ && (int)streamStub.size() > setup_->numFrames()) + limit = next(streamStub.begin(), setup_->numFrames()); + streamAcceptedStubs[channelId] = StreamStub(streamStub.begin(), limit); + streamLostStubs[channelId++] = StreamStub(limit, streamStub.end()); + } + } + // store products + iEvent.emplace(edPutTokenAcceptedStubs_, move(streamAcceptedStubs)); + iEvent.emplace(edPutTokenAcceptedTracks_, move(streamAcceptedTracks)); + iEvent.emplace(edPutTokenLostStubs_, move(streamLostStubs)); + iEvent.emplace(edPutTokenLostTracks_, move(streamLostTracks)); + } + +} // namespace trklet + +DEFINE_FWK_MODULE(trklet::ProducerTBout); diff --git a/L1Trigger/TrackFindingTracklet/plugins/ProducerTT.cc b/L1Trigger/TrackFindingTracklet/plugins/ProducerTT.cc new file mode 100644 index 0000000000000..21a75f2006889 --- /dev/null +++ b/L1Trigger/TrackFindingTracklet/plugins/ProducerTT.cc @@ -0,0 +1,134 @@ +#include "FWCore/Framework/interface/stream/EDProducer.h" +#include "FWCore/Framework/interface/Run.h" +#include "FWCore/Framework/interface/EventSetup.h" +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/MakerMacros.h" +#include "FWCore/Utilities/interface/EDGetToken.h" +#include "FWCore/Utilities/interface/EDPutToken.h" +#include "FWCore/Utilities/interface/ESGetToken.h" +#include "FWCore/Utilities/interface/InputTag.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "DataFormats/Common/interface/Handle.h" + +#include "L1Trigger/TrackTrigger/interface/Setup.h" +#include "L1Trigger/TrackerTFP/interface/DataFormats.h" + +#include +#include + +using namespace std; +using namespace edm; +using namespace trackerTFP; +using namespace tt; + +namespace trklet { + + /*! \class trklet::ProducerTT + * \brief Converts KF output into TTTracks + * \author Thomas Schuh + * \date 2021, Aug + */ + class ProducerTT : public stream::EDProducer<> { + public: + explicit ProducerTT(const ParameterSet&); + ~ProducerTT() override {} + + private: + void beginRun(const Run&, const EventSetup&) override; + void produce(Event&, const EventSetup&) override; + void endJob() {} + + // ED input token of kf stubs + EDGetTokenT edGetTokenStubs_; + // ED input token of kf tracks + EDGetTokenT edGetTokenTracks_; + // ED output token for TTTracks + EDPutTokenT edPutToken_; + // Setup token + ESGetToken esGetTokenSetup_; + // DataFormats token + ESGetToken esGetTokenDataFormats_; + // configuration + ParameterSet iConfig_; + // helper class to store configurations + const Setup* setup_; + // helper class to extract structured data from tt::Frames + const DataFormats* dataFormats_; + }; + + ProducerTT::ProducerTT(const ParameterSet& iConfig) : iConfig_(iConfig) { + const string& label = iConfig.getParameter("LabelKF"); + const string& branchStubs = iConfig.getParameter("BranchAcceptedStubs"); + const string& branchTracks = iConfig.getParameter("BranchAcceptedTracks"); + // book in- and output ED products + edGetTokenStubs_ = consumes(InputTag(label, branchStubs)); + edGetTokenTracks_ = consumes(InputTag(label, branchTracks)); + edPutToken_ = produces(branchTracks); + // book ES products + esGetTokenSetup_ = esConsumes(); + esGetTokenDataFormats_ = esConsumes(); + // initial ES products + setup_ = nullptr; + dataFormats_ = nullptr; + } + + void ProducerTT::beginRun(const Run& iRun, const EventSetup& iSetup) { + // helper class to store configurations + setup_ = &iSetup.getData(esGetTokenSetup_); + if (!setup_->configurationSupported()) + return; + // check process history if desired + if (iConfig_.getParameter("CheckHistory")) + setup_->checkHistory(iRun.processHistory()); + // helper class to extract structured data from tt::Frames + dataFormats_ = &iSetup.getData(esGetTokenDataFormats_); + } + + void ProducerTT::produce(Event& iEvent, const EventSetup& iSetup) { + // empty KFout product + TTTracks ttTracks; + // read in KF Product and produce KFout product + if (setup_->configurationSupported()) { + Handle handleStubs; + iEvent.getByToken(edGetTokenStubs_, handleStubs); + const StreamsStub& streamsStubs = *handleStubs.product(); + Handle handleTracks; + iEvent.getByToken(edGetTokenTracks_, handleTracks); + const StreamsTrack& streamsTracks = *handleTracks.product(); + // count number of kf tracks + int nTracks(0); + for (const StreamTrack& stream : streamsTracks) + nTracks += accumulate(stream.begin(), stream.end(), 0, [](int& sum, const FrameTrack& frame) { + return sum += frame.first.isNonnull() ? 1 : 0; + }); + ttTracks.reserve(nTracks); + // convert kf track frames per channel and stub frames per channel and layer to TTTracks + for (int channel = 0; channel < (int)streamsTracks.size(); channel++) { + const int offset = channel * setup_->numLayers(); + int iTrk(0); + for (const FrameTrack& frameTrack : streamsTracks[channel]) { + if (frameTrack.first.isNull()) + continue; + // convert stub frames to kf stubs + vector stubs; + stubs.reserve(setup_->numLayers()); + for (int layer = 0; layer < setup_->numLayers(); layer++) { + const FrameStub& frameStub = streamsStubs[offset + layer][iTrk]; + if (frameStub.first.isNonnull()) + stubs.emplace_back(frameStub, dataFormats_, layer); + } + // convert track frame to kf track + TrackKF track(frameTrack, dataFormats_); + // convert kf track and kf stubs to TTTrack + ttTracks.emplace_back(track.ttTrack(stubs)); + iTrk++; + } + } + } + // store products + iEvent.emplace(edPutToken_, move(ttTracks)); + } + +} // namespace trklet + +DEFINE_FWK_MODULE(trklet::ProducerTT); \ No newline at end of file diff --git a/L1Trigger/TrackFindingTracklet/python/Analyzer_cff.py b/L1Trigger/TrackFindingTracklet/python/Analyzer_cff.py new file mode 100644 index 0000000000000..5fd6ea8441bbe --- /dev/null +++ b/L1Trigger/TrackFindingTracklet/python/Analyzer_cff.py @@ -0,0 +1,11 @@ +import FWCore.ParameterSet.Config as cms + +from L1Trigger.TrackFindingTracklet.Analyzer_cfi import TrackFindingTrackletAnalyzer_params +from L1Trigger.TrackFindingTracklet.Producer_cfi import TrackFindingTrackletProducer_params + +TrackFindingTrackletAnalyzerTBout = cms.EDAnalyzer( 'trklet::AnalyzerTBout', TrackFindingTrackletAnalyzer_params, TrackFindingTrackletProducer_params ) +TrackFindingTrackletAnalyzerTracklet = cms.EDAnalyzer( 'trklet::AnalyzerTracklet', TrackFindingTrackletAnalyzer_params, TrackFindingTrackletProducer_params ) +TrackFindingTrackletAnalyzerKFin = cms.EDAnalyzer( 'trklet::AnalyzerKFin', TrackFindingTrackletAnalyzer_params, TrackFindingTrackletProducer_params ) +TrackFindingTrackletAnalyzerKF = cms.EDAnalyzer( 'trackerTFP::AnalyzerKF', TrackFindingTrackletAnalyzer_params, TrackFindingTrackletProducer_params ) +TrackFindingTrackletAnalyzerKFout = cms.EDAnalyzer( 'trklet::AnalyzerKFout', TrackFindingTrackletAnalyzer_params, TrackFindingTrackletProducer_params ) +TrackFindingTrackletAnalyzerTT = cms.EDAnalyzer( 'trklet::AnalyzerTT', TrackFindingTrackletAnalyzer_params, TrackFindingTrackletProducer_params ) diff --git a/L1Trigger/TrackFindingTracklet/python/Analyzer_cfi.py b/L1Trigger/TrackFindingTracklet/python/Analyzer_cfi.py new file mode 100644 index 0000000000000..81e769c5d6a03 --- /dev/null +++ b/L1Trigger/TrackFindingTracklet/python/Analyzer_cfi.py @@ -0,0 +1,11 @@ +# ParameterSet used by AnalyzerKFin and AnalyzerTracklet +import FWCore.ParameterSet.Config as cms + +TrackFindingTrackletAnalyzer_params = cms.PSet ( + + UseMCTruth = cms.bool( True ), # enables analyze of TPs + InputTagReconstructable = cms.InputTag("StubAssociator", "Reconstructable"), # + InputTagSelection = cms.InputTag("StubAssociator", "UseForAlgEff"), # + + +) \ No newline at end of file diff --git a/L1Trigger/TrackFindingTracklet/python/ChannelAssignment_cff.py b/L1Trigger/TrackFindingTracklet/python/ChannelAssignment_cff.py new file mode 100644 index 0000000000000..adb369d78606f --- /dev/null +++ b/L1Trigger/TrackFindingTracklet/python/ChannelAssignment_cff.py @@ -0,0 +1,5 @@ +import FWCore.ParameterSet.Config as cms + +from L1Trigger.TrackFindingTracklet.ChannelAssignment_cfi import ChannelAssignment_params + +ChannelAssignment = cms.ESProducer("trklet::ProducerChannelAssignment", ChannelAssignment_params) diff --git a/L1Trigger/TrackFindingTracklet/python/ChannelAssignment_cfi.py b/L1Trigger/TrackFindingTracklet/python/ChannelAssignment_cfi.py new file mode 100644 index 0000000000000..2e05d43acdfcb --- /dev/null +++ b/L1Trigger/TrackFindingTracklet/python/ChannelAssignment_cfi.py @@ -0,0 +1,34 @@ +# defines PSet to assign tracklet tracks and stubs to output channel based on their Pt or seed type as well as DTC stubs to input channel +import FWCore.ParameterSet.Config as cms + +ChannelAssignment_params = cms.PSet ( + + UseDuplicateRemoval = cms.bool ( True ), # use tracklet seed type as channel id if False, binned track pt used if True + PtBoundaries = cms.vdouble( 1.34 ), # positive pt Boundaries in GeV (symmetric negatives are assumed), last boundary is infinity, defining ot bins used by DR + + SeedTypes = cms.vstring( "L1L2", "L2L3", "L3L4", "L5L6", "D1D2", "D3D4", "L1D1", "L2D1" ), # seed types used in tracklet algorithm (position gives int value) + + SeedTypesSeedLayers = cms.PSet ( # seeding layers of seed types using default layer id [barrel: 1-6, discs: 11-15] + L1L2 = cms.vint32( 1, 2 ), + L2L3 = cms.vint32( 2, 3 ), + L3L4 = cms.vint32( 3, 4 ), + L5L6 = cms.vint32( 5, 6 ), + D1D2 = cms.vint32( 11, 12 ), + D3D4 = cms.vint32( 13, 14 ), + L1D1 = cms.vint32( 1, 11 ), + L2D1 = cms.vint32( 2, 11 ) + ), + SeedTypesProjectionLayers = cms.PSet ( # layers a seed types can project to using default layer id [barrel: 1-6, discs: 11-15] + L1L2 = cms.vint32( 3, 4, 5, 6, 11, 12, 13, 14 ), + L2L3 = cms.vint32( 1, 4, 5, 6, 11, 12, 13, 14 ), + L3L4 = cms.vint32( 1, 2, 5, 6, 11, 12 ), + L5L6 = cms.vint32( 1, 2, 3, 4 ), + D1D2 = cms.vint32( 1, 2, 13, 14, 15 ), + D3D4 = cms.vint32( 1, 11, 12, 15 ), + L1D1 = cms.vint32( 12, 13, 14, 15 ), + L2D1 = cms.vint32( 1, 12, 13, 14 ) + ), + + IRChannelsIn = cms.vint32( range(0, 48) ) # vector of DTC id indexed by connected IR module id (from order in processingmodules.dat) + +) diff --git a/L1Trigger/TrackFindingTracklet/python/Customize_cff.py b/L1Trigger/TrackFindingTracklet/python/Customize_cff.py new file mode 100644 index 0000000000000..436edaf44a235 --- /dev/null +++ b/L1Trigger/TrackFindingTracklet/python/Customize_cff.py @@ -0,0 +1,31 @@ +import FWCore.ParameterSet.Config as cms + +# configures track finding s/w to use KF emulator instead of KF simulator +def newKFConfig(process): + process.TTTracksFromTrackletEmulation.Fakefit = True + +# configures track finding s/w to behave as track finding f/w +def fwConfig(process): + newKFConfig(process) + process.TrackTriggerSetup.Firmware.FreqBE = 240 # Frequency of DTC & KF (determines truncation) + process.TTTracksFromTrackletEmulation.RemovalType = "" + process.TTTracksFromTrackletEmulation.DoMultipleMatches = False + process.TTTracksFromTrackletEmulation.StoreTrackBuilderOutput = True + process.ChannelAssignment.UseDuplicateRemoval = False + process.TrackTriggerSetup.KalmanFilter.NumWorker = 8 + +# configures track finding s/w to behave as a subchain of processing steps +def reducedConfig(process): + fwConfig(process) + process.TrackTriggerSetup.KalmanFilter.NumWorker = 1 + process.ChannelAssignment.SeedTypes = cms.vstring( "L1L2" ) + process.ChannelAssignment.SeedTypesSeedLayers = cms.PSet( L1L2 = cms.vint32( 1, 2 ) ) + process.ChannelAssignment.SeedTypesProjectionLayers = cms.PSet( L1L2 = cms.vint32( 3, 4, 5, 6 ) ) + # this are tt::Setup::dtcId in order as in process.TTTracksFromTrackletEmulation.processingModulesFile translated by + # reverssing naming logic described in L1FPGATrackProducer + # TO DO: Eliminate cfg param IRChannelsIn by taking this info from Tracklet wiring map. + process.ChannelAssignment.IRChannelsIn = cms.vint32( 0, 1, 25, 2, 26, 4, 28, 5, 29, 6, 30, 7, 31, 8, 32, 9, 33 ) + process.TTTracksFromTrackletEmulation.Reduced = True + process.TTTracksFromTrackletEmulation.memoryModulesFile = 'L1Trigger/TrackFindingTracklet/data/reduced_memorymodules.dat' + process.TTTracksFromTrackletEmulation.processingModulesFile = 'L1Trigger/TrackFindingTracklet/data/reduced_processingmodules.dat' + process.TTTracksFromTrackletEmulation.wiresFile = 'L1Trigger/TrackFindingTracklet/data/reduced_wires.dat' diff --git a/L1Trigger/TrackFindingTracklet/python/Demonstrator_cff.py b/L1Trigger/TrackFindingTracklet/python/Demonstrator_cff.py new file mode 100644 index 0000000000000..6ce8850ef51a3 --- /dev/null +++ b/L1Trigger/TrackFindingTracklet/python/Demonstrator_cff.py @@ -0,0 +1,8 @@ +import FWCore.ParameterSet.Config as cms + +from L1Trigger.TrackFindingTracklet.Demonstrator_cfi import TrackTriggerDemonstrator_params +from L1Trigger.TrackFindingTracklet.Producer_cfi import TrackFindingTrackletProducer_params + +TrackTriggerDemonstrator = cms.ESProducer("trackerTFP::ProducerDemonstrator", TrackTriggerDemonstrator_params) + +TrackerTFPDemonstrator = cms.EDAnalyzer("trklet::AnalyzerDemonstrator", TrackTriggerDemonstrator_params, TrackFindingTrackletProducer_params) \ No newline at end of file diff --git a/L1Trigger/TrackFindingTracklet/python/Demonstrator_cfi.py b/L1Trigger/TrackFindingTracklet/python/Demonstrator_cfi.py new file mode 100644 index 0000000000000..44e368621a018 --- /dev/null +++ b/L1Trigger/TrackFindingTracklet/python/Demonstrator_cfi.py @@ -0,0 +1,11 @@ +# configuration of Demonstrator. This is used to compare FW with SW for the subset fo the chain between LabelIn & LabelOut. FW must be wrapped by EMP & compiled with IPBB. +import FWCore.ParameterSet.Config as cms + +TrackTriggerDemonstrator_params = cms.PSet ( + + LabelIn = cms.string( "TrackFindingTrackletProducerTBout" ), # + LabelOut = cms.string( "TrackFindingTrackletProducerKFin" ), # + DirIPBB = cms.string( "/heplnw039/tschuh/work/proj/kfin/" ), # path to ipbb proj area + RunTime = cms.double( 8.0 ) # runtime in us + +) \ No newline at end of file diff --git a/L1Trigger/TrackFindingTracklet/python/L1HybridEmulationTracks_cff.py b/L1Trigger/TrackFindingTracklet/python/L1HybridEmulationTracks_cff.py index 3ac44e808ef26..63eeb319ff0e4 100644 --- a/L1Trigger/TrackFindingTracklet/python/L1HybridEmulationTracks_cff.py +++ b/L1Trigger/TrackFindingTracklet/python/L1HybridEmulationTracks_cff.py @@ -6,13 +6,15 @@ from SimTracker.TrackTriggerAssociation.TrackTriggerAssociator_cff import * +from L1Trigger.TrackTrigger.ProducerHPH_cff import * + # prompt hybrid emulation TTTrackAssociatorFromPixelDigis.TTTracks = cms.VInputTag(cms.InputTag("l1tTTTracksFromTrackletEmulation", "Level1TTTracks") ) L1THybridTracks = cms.Sequence(offlineBeamSpot*l1tTTTracksFromTrackletEmulation) L1THybridTracksWithAssociators = cms.Sequence(offlineBeamSpot*l1tTTTracksFromTrackletEmulation*TrackTriggerAssociatorTracks) -# extended hybrid emulation +# extended hybrid (=displaced tracking) emulation TTTrackAssociatorFromPixelDigisExtended = TTTrackAssociatorFromPixelDigis.clone( TTTracks = cms.VInputTag(cms.InputTag("l1tTTTracksFromExtendedTrackletEmulation", "Level1TTTracks") ) ) @@ -23,4 +25,3 @@ # both (prompt + extended) hybrid emulation L1TPromptExtendedHybridTracks = cms.Sequence(offlineBeamSpot*l1tTTTracksFromTrackletEmulation*l1tTTTracksFromExtendedTrackletEmulation) L1TPromptExtendedHybridTracksWithAssociators = cms.Sequence(offlineBeamSpot*l1tTTTracksFromTrackletEmulation*TrackTriggerAssociatorTracks*l1tTTTracksFromExtendedTrackletEmulation*TTTrackAssociatorFromPixelDigisExtended) - diff --git a/L1Trigger/TrackFindingTracklet/python/Producer_cff.py b/L1Trigger/TrackFindingTracklet/python/Producer_cff.py new file mode 100644 index 0000000000000..a2b4a4548fd27 --- /dev/null +++ b/L1Trigger/TrackFindingTracklet/python/Producer_cff.py @@ -0,0 +1,17 @@ +import FWCore.ParameterSet.Config as cms + +from L1Trigger.TrackTrigger.ProducerSetup_cff import TrackTriggerSetup +from L1Trigger.TrackerTFP.Producer_cfi import TrackerTFPProducer_params +from L1Trigger.TrackerTFP.ProducerES_cff import TrackTriggerDataFormats +from L1Trigger.TrackerTFP.ProducerLayerEncoding_cff import TrackTriggerLayerEncoding +from L1Trigger.TrackerTFP.KalmanFilterFormats_cff import TrackTriggerKalmanFilterFormats +from L1Trigger.TrackFindingTracklet.ChannelAssignment_cff import ChannelAssignment +from L1Trigger.TrackFindingTracklet.Producer_cfi import TrackFindingTrackletProducer_params + +TrackFindingTrackletProducerIRin = cms.EDProducer( 'trklet::ProducerIRin', TrackFindingTrackletProducer_params ) +TrackFindingTrackletProducerTBout = cms.EDProducer( 'trklet::ProducerTBout', TrackFindingTrackletProducer_params ) +TrackFindingTrackletProducerKFin = cms.EDProducer( 'trklet::ProducerKFin', TrackFindingTrackletProducer_params ) +TrackFindingTrackletProducerKF = cms.EDProducer( 'trackerTFP::ProducerKF', TrackFindingTrackletProducer_params ) +TrackFindingTrackletProducerTT = cms.EDProducer( 'trklet::ProducerTT', TrackFindingTrackletProducer_params ) +TrackFindingTrackletProducerAS = cms.EDProducer( 'trklet::ProducerAS', TrackFindingTrackletProducer_params ) +TrackFindingTrackletProducerKFout = cms.EDProducer( 'trklet::ProducerKFout', TrackFindingTrackletProducer_params ) \ No newline at end of file diff --git a/L1Trigger/TrackFindingTracklet/python/Producer_cfi.py b/L1Trigger/TrackFindingTracklet/python/Producer_cfi.py new file mode 100644 index 0000000000000..0519783a8f65d --- /dev/null +++ b/L1Trigger/TrackFindingTracklet/python/Producer_cfi.py @@ -0,0 +1,22 @@ +import FWCore.ParameterSet.Config as cms + +TrackFindingTrackletProducer_params = cms.PSet ( + + InputTag = cms.InputTag( "TTTracksFromTrackletEmulation", "Level1TTTracks"), # + InputTagDTC = cms.InputTag( "TrackerDTCProducer", "StubAccepted"), # + LabelTBout = cms.string ( "TrackFindingTrackletProducerTBout" ), # + LabelKFin = cms.string ( "TrackFindingTrackletProducerKFin" ), # + LabelKF = cms.string ( "TrackFindingTrackletProducerKF" ), # + LabelTT = cms.string ( "TrackFindingTrackletProducerTT" ), # + LabelAS = cms.string ( "TrackFindingTrackletProducerAS" ), # + LabelKFout = cms.string ( "TrackFindingTrackletProducerKFout" ), # + BranchAcceptedStubs = cms.string ( "StubAccepted" ), # + BranchAcceptedTracks = cms.string ( "TrackAccepted" ), # + BranchLostStubs = cms.string ( "StubLost" ), # + BranchLostTracks = cms.string ( "TrackLost" ), # + CheckHistory = cms.bool ( False ), # checks if input sample production is configured as current process + EnableTruncation = cms.bool ( True ), # enable emulation of truncation for TBout, KF, KFin, lost stubs are filled in BranchLost + PrintKFDebug = cms.bool ( False ), # print end job internal unused MSB + UseTTStubResiduals = cms.bool ( False ), # stub residuals are recalculated from seed parameter and TTStub position + +) \ No newline at end of file diff --git a/L1Trigger/TrackFindingTracklet/python/l1tTTTracksFromTrackletEmulation_cfi.py b/L1Trigger/TrackFindingTracklet/python/l1tTTTracksFromTrackletEmulation_cfi.py index 2745ec30a8f03..5779fce86d024 100644 --- a/L1Trigger/TrackFindingTracklet/python/l1tTTTracksFromTrackletEmulation_cfi.py +++ b/L1Trigger/TrackFindingTracklet/python/l1tTTTracksFromTrackletEmulation_cfi.py @@ -1,9 +1,10 @@ import FWCore.ParameterSet.Config as cms from L1Trigger.TrackTrigger.TrackQualityParams_cfi import * +from L1Trigger.TrackFindingTracklet.ChannelAssignment_cff import ChannelAssignment l1tTTTracksFromTrackletEmulation = cms.EDProducer("L1FPGATrackProducer", TTStubSource = cms.InputTag("TTStubsFromPhase2TrackerDigis","StubAccepted"), - InputTagTTDTC = cms.InputTag("TrackerDTCProducer", "StubAccepted"), + InputTagTTDTC = cms.InputTag("TrackerDTCProducer", "StubAccepted"), readMoreMcTruth = cms.bool(True), MCTruthClusterInputTag = cms.InputTag("TTClusterAssociatorFromPixelDigis", "ClusterAccepted"), MCTruthStubInputTag = cms.InputTag("TTStubAssociatorFromPixelDigis", "StubAccepted"), @@ -11,6 +12,7 @@ BeamSpotSource = cms.InputTag("offlineBeamSpot"), asciiFileName = cms.untracked.string(""), Extended = cms.bool(False), + Reduced = cms.bool(False), Hnpar = cms.uint32(4), # (if running on CRAB use "../../fitpattern.txt" etc instead) fitPatternFile = cms.FileInPath('L1Trigger/TrackFindingTracklet/data/fitpattern.txt'), @@ -19,11 +21,16 @@ wiresFile = cms.FileInPath('L1Trigger/TrackFindingTracklet/data/wires_hourglassExtended.dat'), # Quality Flag and Quality params TrackQuality = cms.bool(True), - TrackQualityPSet = cms.PSet(TrackQualityParams) + TrackQualityPSet = cms.PSet(TrackQualityParams), + Fakefit = cms.bool(False), # True causes Tracklet reco to output TTTracks before DR & KF + StoreTrackBuilderOutput = cms.bool(False), # if True EDProducts for TrackBuilder tracks and stubs will be filled + RemovalType = cms.string("merge"), # Duplicate track removal + DoMultipleMatches = cms.bool(True) # Allow tracklet tracks multiple stubs per layer ) l1tTTTracksFromExtendedTrackletEmulation = l1tTTTracksFromTrackletEmulation.clone( Extended = cms.bool(True), + Reduced = cms.bool(False), Hnpar = cms.uint32(5), # specifying where the TrackletEngineDisplaced(TED)/TripletEngine(TRE) tables are located tableTEDFile = cms.FileInPath('L1Trigger/TrackFindingTracklet/data/table_TED/table_TED_D1PHIA1_D2PHIA1.txt'), @@ -31,5 +38,4 @@ # Quality Flag and Quality params TrackQuality = cms.bool(False), TrackQualityPSet = cms.PSet(TrackQualityParams) - ) - + ) \ No newline at end of file diff --git a/L1Trigger/TrackFindingTracklet/src/AllInnerStubsMemory.cc b/L1Trigger/TrackFindingTracklet/src/AllInnerStubsMemory.cc index 5ee9e5b1cda63..32295dab1fb5e 100644 --- a/L1Trigger/TrackFindingTracklet/src/AllInnerStubsMemory.cc +++ b/L1Trigger/TrackFindingTracklet/src/AllInnerStubsMemory.cc @@ -15,10 +15,7 @@ void AllInnerStubsMemory::writeStubs(bool first, unsigned int iSector) { for (unsigned int j = 0; j < stubs_.size(); j++) { string stub = stubs_[j]->strinner(); - out_ << "0x"; - out_ << std::setfill('0') << std::setw(2); - out_ << hex << j << dec; - out_ << " " << stub << " " << hexFormat(stub) << endl; + out_ << hexstr(j) << " " << stub << " " << hexFormat(stub) << endl; } out_.close(); } diff --git a/L1Trigger/TrackFindingTracklet/src/AllProjectionsMemory.cc b/L1Trigger/TrackFindingTracklet/src/AllProjectionsMemory.cc index d15cb03d753de..409bd8eb7e663 100644 --- a/L1Trigger/TrackFindingTracklet/src/AllProjectionsMemory.cc +++ b/L1Trigger/TrackFindingTracklet/src/AllProjectionsMemory.cc @@ -29,10 +29,7 @@ void AllProjectionsMemory::writeAP(bool first, unsigned int iSector) { for (unsigned int j = 0; j < tracklets_.size(); j++) { string proj = (layer_ > 0) ? tracklets_[j]->trackletprojstrlayer(layer_) : tracklets_[j]->trackletprojstrdisk(disk_); - out_ << "0x"; - out_ << std::setfill('0') << std::setw(2); - out_ << hex << j << dec; - out_ << " " << proj << " " << trklet::hexFormat(proj) << endl; + out_ << hexstr(j) << " " << proj << " " << trklet::hexFormat(proj) << endl; } out_.close(); diff --git a/L1Trigger/TrackFindingTracklet/src/AllStubsMemory.cc b/L1Trigger/TrackFindingTracklet/src/AllStubsMemory.cc index db3993fdd74c5..5861e260feb7a 100644 --- a/L1Trigger/TrackFindingTracklet/src/AllStubsMemory.cc +++ b/L1Trigger/TrackFindingTracklet/src/AllStubsMemory.cc @@ -15,10 +15,7 @@ void AllStubsMemory::writeStubs(bool first, unsigned int iSector) { for (unsigned int j = 0; j < stubs_.size(); j++) { string stub = stubs_[j]->str(); - out_ << "0x"; - out_ << std::setfill('0') << std::setw(2); - out_ << hex << j << dec; - out_ << " " << stub << " " << hexFormat(stub) << endl; + out_ << hexstr(j) << " " << stub << " " << hexFormat(stub) << endl; } out_.close(); } diff --git a/L1Trigger/TrackFindingTracklet/src/CandidateMatchMemory.cc b/L1Trigger/TrackFindingTracklet/src/CandidateMatchMemory.cc index 06092b28350ed..adef2141b7223 100644 --- a/L1Trigger/TrackFindingTracklet/src/CandidateMatchMemory.cc +++ b/L1Trigger/TrackFindingTracklet/src/CandidateMatchMemory.cc @@ -48,10 +48,7 @@ void CandidateMatchMemory::writeCM(bool first, unsigned int iSector) { projindex = (1 << 7) - 1; } tmp.set(projindex, 7, true, __LINE__, __FILE__); - out_ << "0x"; - out_ << std::setfill('0') << std::setw(2); - out_ << hex << j << dec; - out_ << " " << tmp.str() << "|" << stubid << " " << trklet::hexFormat(tmp.str() + stubid) << endl; + out_ << hexstr(j) << " " << tmp.str() << "|" << stubid << " " << trklet::hexFormat(tmp.str() + stubid) << endl; } out_.close(); diff --git a/L1Trigger/TrackFindingTracklet/src/ChannelAssignment.cc b/L1Trigger/TrackFindingTracklet/src/ChannelAssignment.cc new file mode 100644 index 0000000000000..bcbb76e087ab0 --- /dev/null +++ b/L1Trigger/TrackFindingTracklet/src/ChannelAssignment.cc @@ -0,0 +1,200 @@ +#include "L1Trigger/TrackFindingTracklet/interface/ChannelAssignment.h" +#include "L1Trigger/TrackFindingTracklet/interface/Settings.h" + +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace edm; +using namespace tt; + +namespace trklet { + + ChannelAssignment::ChannelAssignment(const edm::ParameterSet& iConfig, const Setup* setup) + : setup_(setup), + useDuplicateRemoval_(iConfig.getParameter("UseDuplicateRemoval")), + boundaries_(iConfig.getParameter>("PtBoundaries")), + seedTypeNames_(iConfig.getParameter>("SeedTypes")), + numSeedTypes_(seedTypeNames_.size()), + numChannelsTrack_(useDuplicateRemoval_ ? 2 * boundaries_.size() : numSeedTypes_), + channelEncoding_(iConfig.getParameter>("IRChannelsIn")) { + const ParameterSet& pSetSeedTypesSeedLayers = iConfig.getParameter("SeedTypesSeedLayers"); + const ParameterSet& pSetSeedTypesProjectionLayers = iConfig.getParameter("SeedTypesProjectionLayers"); + seedTypesSeedLayers_.reserve(numSeedTypes_); + seedTypesProjectionLayers_.reserve(numSeedTypes_); + for (const string& s : seedTypeNames_) { + seedTypesSeedLayers_.emplace_back(pSetSeedTypesSeedLayers.getParameter>(s)); + seedTypesProjectionLayers_.emplace_back(pSetSeedTypesProjectionLayers.getParameter>(s)); + } + auto acc = [](int& sum, vector ints) { return sum += (int)ints.size(); }; + numChannelsStub_ = accumulate(seedTypesProjectionLayers_.begin(), seedTypesProjectionLayers_.end(), 0, acc); + offsetsStubs_.reserve(numSeedTypes_); + for (int seed = 0; seed < numSeedTypes_; seed++) { + const auto it = next(seedTypesProjectionLayers_.begin(), seed); + offsetsStubs_.emplace_back(accumulate(seedTypesProjectionLayers_.begin(), it, 0, acc)); + } + // consistency check + static constexpr int offsetBarrel = 1; + static constexpr int numBarrelLayer = 6; + static constexpr int offsetDisk = 11; + static constexpr int invalidSeedLayer = -1; + static constexpr int invalidLayerDisk = 0; + const Settings settings; + const auto& seedlayers = settings.seedlayers(); + const auto& projlayers = settings.projlayers(); + const auto& projdisks = settings.projdisks(); + // convert Seetings layer ids into ChannelAssignment layer ids + vector> allSeedingLayer(seedlayers.size()); + vector> allProjectionLayer(seedlayers.size()); + for (int iSeed = 0; iSeed < (int)seedlayers.size(); iSeed++) + for (const auto& layer : seedlayers[iSeed]) + if (layer != invalidSeedLayer) + allSeedingLayer[iSeed].insert(layer < numBarrelLayer ? layer + offsetBarrel + : layer + offsetDisk - numBarrelLayer); + for (int iSeed = 0; iSeed < (int)projlayers.size(); iSeed++) + for (const auto& layer : projlayers[iSeed]) + if (layer != invalidLayerDisk) + allProjectionLayer[iSeed].insert(layer); + for (int iSeed = 0; iSeed < (int)projdisks.size(); iSeed++) + for (const auto& disk : projdisks[iSeed]) + if (disk != invalidLayerDisk) + allProjectionLayer[iSeed].insert(disk - offsetBarrel + offsetDisk); + // check if ChannelAssignment seedTypesSeedLayers_ and seedTypesProjectionLayers_ are subsets of Settings pendants + for (int iSubSeed = 0; iSubSeed < numSeedTypes_; iSubSeed++) { + const vector& seedLayers = seedTypesSeedLayers_[iSubSeed]; + bool subset(false); + for (int iAllSeed = 0; iAllSeed < (int)seedlayers.size(); iAllSeed++) { + // compare seed layer + const set& asl = allSeedingLayer[iAllSeed]; + set sl(seedLayers.begin(), seedLayers.end()); + set intersect; + set_intersection(sl.begin(), sl.end(), asl.begin(), asl.end(), inserter(intersect, intersect.begin())); + if (intersect == sl) { + subset = true; + // compare projection layer + const vector& projectionLayers = seedTypesProjectionLayers_[iSubSeed]; + const set& apl = allProjectionLayer[iAllSeed]; + set pl(projectionLayers.begin(), projectionLayers.end()); + set intersect; + set_intersection(pl.begin(), pl.end(), apl.begin(), apl.end(), inserter(intersect, intersect.begin())); + if (intersect == pl) + break; + set difference; + set_difference( + pl.begin(), pl.end(), intersect.begin(), intersect.end(), inserter(difference, difference.begin())); + cms::Exception exception("LogicError."); + exception << "ProjectionLayers ( "; + for (int layer : difference) + exception << layer << " "; + exception << ") are not supported with seed type ( "; + for (int layer : seedLayers) + exception << layer << " "; + exception << ")"; + exception.addContext("trklet::ChannelAssignment::ChannelAssignment"); + throw exception; + } + } + if (subset) + continue; + cms::Exception exception("LogicError."); + exception << "SeedLayers ( "; + for (int layer : seedLayers) + exception << layer << " "; + exception << ") are not supported"; + exception.addContext("trklet::ChannelAssignment::ChannelAssignment"); + throw exception; + } + auto bigger = [](const vector& lhs, const vector& rhs) { return lhs.size() < rhs.size(); }; + numSeedingLayers_ = max_element(seedTypesSeedLayers_.begin(), seedTypesSeedLayers_.end(), bigger)->size(); + maxNumProjectionLayers_ = + max_element(seedTypesProjectionLayers_.begin(), seedTypesProjectionLayers_.end(), bigger)->size(); + } + + // sets channelId of given TTTrackRef, return false if track outside pt range + bool ChannelAssignment::channelId(const TTTrackRef& ttTrackRef, int& channelId) { + if (!useDuplicateRemoval_) { + const int seedType = ttTrackRef->trackSeedType(); + if (seedType >= numSeedTypes_) { + cms::Exception exception("logic_error"); + exception << "TTTracks form seed type" << seedType << " not in supported list: ("; + for (const auto& s : seedTypeNames_) + exception << s << " "; + exception << ")."; + exception.addContext("trklet:ChannelAssignment:channelId"); + throw exception; + } + channelId = ttTrackRef->phiSector() * numSeedTypes_ + seedType; + return true; + } + const double pt = ttTrackRef->momentum().perp(); + channelId = -1; + for (double boundary : boundaries_) { + if (pt < boundary) + break; + else + channelId++; + } + if (channelId == -1) + return false; + channelId = ttTrackRef->rInv() < 0. ? channelId : numChannelsTrack_ - channelId - 1; + channelId += ttTrackRef->phiSector() * numChannelsTrack_; + return true; + } + + // sets layerId of given TTStubRef and seedType, returns false if seeed stub + bool ChannelAssignment::layerId(int seedType, const TTStubRef& ttStubRef, int& layerId) const { + layerId = -1; + if (seedType < 0 || seedType >= numSeedTypes_) { + cms::Exception exception("logic_error"); + exception.addContext("trklet::ChannelAssignment::layerId"); + exception << "TTTracks with with seed type " << seedType << " not supported."; + throw exception; + } + const int layer = setup_->layerId(ttStubRef); + const vector& seedingLayers = seedTypesSeedLayers_[seedType]; + if (find(seedingLayers.begin(), seedingLayers.end(), layer) != seedingLayers.end()) + return false; + const vector& projectingLayers = seedTypesProjectionLayers_[seedType]; + const auto pos = find(projectingLayers.begin(), projectingLayers.end(), layer); + if (pos == projectingLayers.end()) { + const string& name = seedTypeNames_[seedType]; + cms::Exception exception("logic_error"); + exception.addContext("trklet::ChannelAssignment::layerId"); + exception << "TTStub from layer " << layer << " (barrel: 1-6; discs: 11-15) from seed type " << name + << " not supported."; + throw exception; + } + layerId = distance(projectingLayers.begin(), pos); + return true; + } + + // return tracklet layerId (barrel: [0-5], endcap: [6-10]) for given TTStubRef + int ChannelAssignment::trackletLayerId(const TTStubRef& ttStubRef) const { + static constexpr int offsetBarrel = 1; + static constexpr int offsetDisks = 5; + return setup_->layerId(ttStubRef) - (setup_->barrel(ttStubRef) ? offsetBarrel : offsetDisks); + } + + // index of first stub channel belonging to given track channel + int ChannelAssignment::offsetStub(int channelTrack) const { + return channelTrack / numChannelsTrack_ * numChannelsStub_ + offsetsStubs_[channelTrack % numChannelsTrack_]; + } + + // + int ChannelAssignment::channelId(int seedType, int layerId) const { + const vector& projections = seedTypesProjectionLayers_.at(seedType); + const vector& seeds = seedTypesSeedLayers_.at(seedType); + const auto itp = find(projections.begin(), projections.end(), layerId); + const auto its = find(seeds.begin(), seeds.end(), layerId); + if (its != seeds.end()) + return (int)projections.size() + distance(seeds.begin(), its); + if (itp != projections.end()) + return distance(projections.begin(), itp); + return -1; + } + +} // namespace trklet diff --git a/L1Trigger/TrackFindingTracklet/src/ChannelAssignmentRcd.cc b/L1Trigger/TrackFindingTracklet/src/ChannelAssignmentRcd.cc new file mode 100644 index 0000000000000..63f58f4d7b206 --- /dev/null +++ b/L1Trigger/TrackFindingTracklet/src/ChannelAssignmentRcd.cc @@ -0,0 +1,4 @@ +#include "L1Trigger/TrackFindingTracklet/interface/ChannelAssignmentRcd.h" +#include "FWCore/Framework/interface/eventsetuprecord_registration_macro.h" + +EVENTSETUP_RECORD_REG(trklet::ChannelAssignmentRcd); diff --git a/L1Trigger/TrackFindingTracklet/src/CleanTrackMemory.cc b/L1Trigger/TrackFindingTracklet/src/CleanTrackMemory.cc index b5adf1859e29c..38fe074aa1622 100644 --- a/L1Trigger/TrackFindingTracklet/src/CleanTrackMemory.cc +++ b/L1Trigger/TrackFindingTracklet/src/CleanTrackMemory.cc @@ -26,10 +26,7 @@ void CleanTrackMemory::writeCT(bool first, unsigned int iSector) { out_ << "BX = " << (bitset<3>)bx_ << " Event : " << event_ << endl; for (unsigned int j = 0; j < tracks_.size(); j++) { - out_ << "0x"; - out_ << std::setfill('0') << std::setw(2); - out_ << hex << j << dec << " "; - out_ << tracks_[j]->trackfitstr() << " " << trklet::hexFormat(tracks_[j]->trackfitstr()); + out_ << hexstr(j) << " " << tracks_[j]->trackfitstr() << " " << trklet::hexFormat(tracks_[j]->trackfitstr()); out_ << "\n"; } out_.close(); diff --git a/L1Trigger/TrackFindingTracklet/src/DTCLinkMemory.cc b/L1Trigger/TrackFindingTracklet/src/DTCLinkMemory.cc index d80531fa86687..09760a9c44a3a 100644 --- a/L1Trigger/TrackFindingTracklet/src/DTCLinkMemory.cc +++ b/L1Trigger/TrackFindingTracklet/src/DTCLinkMemory.cc @@ -55,9 +55,7 @@ void DTCLinkMemory::writeStubs(bool first, unsigned int iSector) { FPGAWord ldcode(lcode, 2, true); string stub = stubs_[j]->str() + "|" + ldcode.str() + "|1"; - out_ << std::setfill('0') << std::setw(2); - out_ << hex << j << dec; - out_ << " " << stub << " " << trklet::hexFormat(stub) << endl; + out_ << hexstr(j) << " " << stub << " " << trklet::hexFormat(stub) << endl; } out_.close(); } diff --git a/L1Trigger/TrackFindingTracklet/src/ES_ChannelAssignment.cc b/L1Trigger/TrackFindingTracklet/src/ES_ChannelAssignment.cc new file mode 100644 index 0000000000000..c98934bd494ff --- /dev/null +++ b/L1Trigger/TrackFindingTracklet/src/ES_ChannelAssignment.cc @@ -0,0 +1,4 @@ +#include "FWCore/Utilities/interface/typelookup.h" +#include "L1Trigger/TrackFindingTracklet/interface/ChannelAssignment.h" + +TYPELOOKUP_DATA_REG(trklet::ChannelAssignment); diff --git a/L1Trigger/TrackFindingTracklet/src/FPGAWord.cc b/L1Trigger/TrackFindingTracklet/src/FPGAWord.cc index 08109d4574224..3531e4dce243b 100644 --- a/L1Trigger/TrackFindingTracklet/src/FPGAWord.cc +++ b/L1Trigger/TrackFindingTracklet/src/FPGAWord.cc @@ -38,11 +38,11 @@ void FPGAWord::set(int value, int nbits, bool positive, int line, const char* fi } assert(value < (1 << nbits)); } else { - if (value > (1 << (nbits - 1))) { - edm::LogProblem("Tracklet") << "value too large:" << value << " " << (1 << (nbits - 1)) << " (" << file << ":" + if (value >= (1 << (nbits - 1))) { + edm::LogProblem("Tracklet") << "value too large:" << value << " " << (1 << (nbits - 1)) - 1 << " (" << file << ":" << line << ")"; } - assert(value <= (1 << (nbits - 1))); + assert(value < (1 << (nbits - 1))); if (value < -(1 << (nbits - 1))) { edm::LogProblem("Tracklet") << "value too negative:" << value << " " << -(1 << (nbits - 1)) << " (" << file << ":" << line << ")"; diff --git a/L1Trigger/TrackFindingTracklet/src/FitTrack.cc b/L1Trigger/TrackFindingTracklet/src/FitTrack.cc index 7b1a9eca7a504..3c4874e58fe70 100644 --- a/L1Trigger/TrackFindingTracklet/src/FitTrack.cc +++ b/L1Trigger/TrackFindingTracklet/src/FitTrack.cc @@ -4,6 +4,8 @@ #include "L1Trigger/TrackFindingTracklet/interface/HybridFit.h" #include "L1Trigger/TrackFindingTracklet/interface/Tracklet.h" #include "L1Trigger/TrackFindingTracklet/interface/Stub.h" +#include "L1Trigger/TrackFindingTracklet/interface/StubStreamData.h" +#include "DataFormats/L1TrackTrigger/interface/TTBV.h" #include "FWCore/MessageLogger/interface/MessageLogger.h" #include "FWCore/Utilities/interface/Exception.h" @@ -124,13 +126,14 @@ void FitTrack::trackFitKF(Tracklet* tracklet, stubidslist.push_back(std::make_pair(layer, it->phiregionaddress())); } - // And that's all we need! The rest is just for fitting (in PurgeDuplicate) - return; - } + // And that's all we need! The rest is just for track fit (done in PurgeDuplicate) - HybridFit hybridFitter(iSector_, settings_, globals_); - hybridFitter.Fit(tracklet, trackstublist); - return; + } else { + // Track fit only called here if not running duplicate removal + // before fit. (e.g. If skipping duplicate removal). + HybridFit hybridFitter(iSector_, settings_, globals_); + hybridFitter.Fit(tracklet, trackstublist); + } } } #endif @@ -867,7 +870,14 @@ std::vector FitTrack::orderedMatches(vector& fullma return tmp; } -void FitTrack::execute(unsigned int iSector) { +// Adds the fitted track to the output memories to be used by pure Tracklet algo. +// (Also used by Hybrid algo with non-exact Old KF emulation) +// Also create output streams, that bypass these memories, (so can include gaps in time), +// to be used by Hybrid case with exact New KF emulation. + +void FitTrack::execute(deque& streamTrackRaw, + vector>& streamsStubRaw, + unsigned int iSector) { // merge const std::vector& matches1 = orderedMatches(fullmatch1_); const std::vector& matches2 = orderedMatches(fullmatch2_); @@ -889,8 +899,8 @@ void FitTrack::execute(unsigned int iSector) { indexArray[i] = 0; } - int countAll = 0; - int countFit = 0; + unsigned int countAll = 0; + unsigned int countFit = 0; Tracklet* bestTracklet = nullptr; do { @@ -989,12 +999,17 @@ void FitTrack::execute(unsigned int iSector) { std::vector trackstublist; std::vector> stubidslist; + // Track Builder cut of >= 4 layers with stubs. if ((bestTracklet->getISeed() >= (int)N_SEED_PROMPT && nMatchesUniq >= 1) || nMatchesUniq >= 2) { //For seeds index >=8 (triplet seeds), there are three stubs associated from start. countFit++; #ifdef USEHYBRID - trackFitKF(bestTracklet, trackstublist, stubidslist); + if (settings_.fakefit()) { + trackFitFake(bestTracklet, trackstublist, stubidslist); + } else { + trackFitKF(bestTracklet, trackstublist, stubidslist); + } #else if (settings_.fakefit()) { trackFitFake(bestTracklet, trackstublist, stubidslist); @@ -1021,7 +1036,51 @@ void FitTrack::execute(unsigned int iSector) { } } - } while (bestTracklet != nullptr); + // store bit and clock accurate TB output + if (settings_.storeTrackBuilderOutput() && bestTracklet) { + // add gap if enough layer to form track + if (!bestTracklet->fit()) { + static const string invalid = "0"; + streamTrackRaw.emplace_back(invalid); + for (auto& stream : streamsStubRaw) + stream.emplace_back(StubStreamData()); + continue; + } + // convert Track word + const string rinv = bestTracklet->fpgarinv().str(); + const string phi0 = bestTracklet->fpgaphi0().str(); + const string z0 = bestTracklet->fpgaz0().str(); + const string t = bestTracklet->fpgat().str(); + const int seedType = bestTracklet->getISeed(); + const string seed = TTBV(seedType, settings_.nbitsseed()).str(); + const string valid("1"); + streamTrackRaw.emplace_back(valid + seed + rinv + phi0 + z0 + t); + + unsigned int ihit(0); + for (unsigned int ilayer = 0; ilayer < N_LAYER + N_DISK; ilayer++) { + if (bestTracklet->match(ilayer)) { + const Residual& resid = bestTracklet->resid(ilayer); + // create bit accurate 64 bit word + const string valid("1"); + string r = resid.stubptr()->r().str(); + const string& phi = resid.fpgaphiresid().str(); + const string& rz = resid.fpgarzresid().str(); + const L1TStub* stub = resid.stubptr()->l1tstub(); + static constexpr int widthDisk2Sidentifier = 8; + bool disk2S = (stub->disk() != 0) && (stub->isPSmodule() == 0); + if (disk2S) + r = string(widthDisk2Sidentifier, '0') + r; + // store seed, L1TStub, and bit accurate 64 bit word in clock accurate output + streamsStubRaw[ihit++].emplace_back(seedType, *stub, valid + r + phi + rz); + } + } + // fill all layer with no stubs with gaps + while (ihit < streamsStubRaw.size()) { + streamsStubRaw[ihit++].emplace_back(); + } + } + + } while (bestTracklet != nullptr && countAll < settings_.maxStep("TB")); if (settings_.writeMonitorData("FT")) { globals_->ofstream("fittrack.txt") << getName() << " " << countAll << " " << countFit << endl; diff --git a/L1Trigger/TrackFindingTracklet/src/FullMatchMemory.cc b/L1Trigger/TrackFindingTracklet/src/FullMatchMemory.cc index f4bf27d54e5e1..90b2428b0acb2 100644 --- a/L1Trigger/TrackFindingTracklet/src/FullMatchMemory.cc +++ b/L1Trigger/TrackFindingTracklet/src/FullMatchMemory.cc @@ -16,9 +16,10 @@ FullMatchMemory::FullMatchMemory(string name, Settings const& settings) : Memory } void FullMatchMemory::addMatch(Tracklet* tracklet, const Stub* stub) { - if (!settings_.doKF() || !settings_.doMultipleMatches()) { //When using KF we allow multiple matches + if (!settings_.doKF() || !settings_.doMultipleMatches()) { + // When allowing only one stub per track per layer (or no KF implying same). for (auto& match : matches_) { - if (match.first == tracklet) { //Better match, replace + if (match.first == tracklet) { //Better match: replace existing one match.second = stub; return; } @@ -52,10 +53,7 @@ void FullMatchMemory::writeMC(bool first, unsigned int iSector) { for (unsigned int j = 0; j < matches_.size(); j++) { string match = (layer_ > 0) ? matches_[j].first->fullmatchstr(layer_) : matches_[j].first->fullmatchdiskstr(disk_); - out_ << "0x"; - out_ << std::setfill('0') << std::setw(2); - out_ << hex << j << dec; - out_ << " " << match << " " << trklet::hexFormat(match) << endl; + out_ << hexstr(j) << " " << match << " " << trklet::hexFormat(match) << endl; } out_.close(); diff --git a/L1Trigger/TrackFindingTracklet/src/HybridFit.cc b/L1Trigger/TrackFindingTracklet/src/HybridFit.cc index 2524ad097dddf..9d292d22adfd0 100644 --- a/L1Trigger/TrackFindingTracklet/src/HybridFit.cc +++ b/L1Trigger/TrackFindingTracklet/src/HybridFit.cc @@ -212,11 +212,11 @@ void HybridFit::Fit(Tracklet* tracklet, std::vector& trackstublist) double phi0fit = reco::reduceRange(phi0 - iSector_ * 2 * M_PI / N_SECTOR + 0.5 * settings_.dphisectorHG()); double rinvfit = 0.01 * settings_.c() * settings_.bfield() * qoverpt; - int irinvfit = rinvfit / settings_.krinvpars(); - int iphi0fit = phi0fit / settings_.kphi0pars(); - int itanlfit = trk.tanLambda() / settings_.ktpars(); - int iz0fit = trk.z0() / settings_.kz0pars(); - int id0fit = d0 / settings_.kd0pars(); + int irinvfit = floor(rinvfit / settings_.krinvpars()); + int iphi0fit = floor(phi0fit / settings_.kphi0pars()); + int itanlfit = floor(trk.tanLambda() / settings_.ktpars()); + int iz0fit = floor(trk.z0() / settings_.kz0pars()); + int id0fit = floor(d0 / settings_.kd0pars()); int ichi2rphifit = chi2rphi / 16; int ichi2rzfit = trk.chi2rz() / 16; diff --git a/L1Trigger/TrackFindingTracklet/src/InputLinkMemory.cc b/L1Trigger/TrackFindingTracklet/src/InputLinkMemory.cc index d9bcb6589d513..9138831bd147f 100644 --- a/L1Trigger/TrackFindingTracklet/src/InputLinkMemory.cc +++ b/L1Trigger/TrackFindingTracklet/src/InputLinkMemory.cc @@ -23,9 +23,7 @@ void InputLinkMemory::writeStubs(bool first, unsigned int iSector) { for (unsigned int j = 0; j < stubs_.size(); j++) { string stub = stubs_[j]->str(); - out_ << std::setfill('0') << std::setw(2); - out_ << hex << j << dec; - out_ << " " << stub << " " << trklet::hexFormat(stub) << endl; + out_ << hexstr(j) << " " << stub << " " << trklet::hexFormat(stub) << endl; } out_.close(); } diff --git a/L1Trigger/TrackFindingTracklet/src/InputRouter.cc b/L1Trigger/TrackFindingTracklet/src/InputRouter.cc index 2ee8e965a90c1..93b98ca20c0f8 100644 --- a/L1Trigger/TrackFindingTracklet/src/InputRouter.cc +++ b/L1Trigger/TrackFindingTracklet/src/InputRouter.cc @@ -74,6 +74,7 @@ void InputRouter::execute() { iadd++; } } - assert(iadd == 1); + if (!(settings_.reduced())) + assert(iadd == 1); } } diff --git a/L1Trigger/TrackFindingTracklet/src/KFin.cc b/L1Trigger/TrackFindingTracklet/src/KFin.cc new file mode 100644 index 0000000000000..0a82487b89a50 --- /dev/null +++ b/L1Trigger/TrackFindingTracklet/src/KFin.cc @@ -0,0 +1,434 @@ +#include "L1Trigger/TrackFindingTracklet/interface/KFin.h" + +#include +#include +#include + +using namespace std; +using namespace edm; +using namespace tt; +using namespace trackerTFP; + +namespace trklet { + + KFin::KFin(const ParameterSet& iConfig, + const Setup* setup, + const DataFormats* dataFormats, + const LayerEncoding* layerEncoding, + const ChannelAssignment* channelAssignment, + const Settings* settings, + int region) + : enableTruncation_(iConfig.getParameter("EnableTruncation")), + useTTStubResiduals_(iConfig.getParameter("UseTTStubResiduals")), + setup_(setup), + dataFormats_(dataFormats), + layerEncoding_(layerEncoding), + channelAssignment_(channelAssignment), + settings_(settings), + region_(region), + input_(channelAssignment_->numChannelsTrack()) { + // unified tracklet digitisation granularity + baseUinv2R_ = .5 * settings_->kphi1() / settings_->kr() * pow(2, settings_->rinv_shift()); + baseUphiT_ = settings_->kphi1() * pow(2, settings_->phi0_shift()); + baseUcot_ = settings_->kz() / settings_->kr() * pow(2, settings_->t_shift()); + baseUzT_ = settings_->kz() * pow(2, settings_->z0_shift()); + baseUr_ = settings_->kr(); + baseUphi_ = settings_->kphi1(); + baseUz_ = settings_->kz(); + // KF input format digitisation granularity (identical to TMTT) + baseLinv2R_ = dataFormats->base(Variable::inv2R, Process::kfin); + baseLphiT_ = dataFormats->base(Variable::phiT, Process::kfin); + baseLcot_ = dataFormats->base(Variable::cot, Process::kfin); + baseLzT_ = dataFormats->base(Variable::zT, Process::kfin); + baseLr_ = dataFormats->base(Variable::r, Process::kfin); + baseLphi_ = dataFormats->base(Variable::phi, Process::kfin); + baseLz_ = dataFormats->base(Variable::z, Process::kfin); + // Finer granularity (by powers of 2) than the TMTT one. Used to transform from Tracklet to TMTT base. + baseHinv2R_ = baseLinv2R_ * pow(2, floor(log2(baseUinv2R_ / baseLinv2R_))); + baseHphiT_ = baseLphiT_ * pow(2, floor(log2(baseUphiT_ / baseLphiT_))); + baseHcot_ = baseLcot_ * pow(2, floor(log2(baseUcot_ / baseLcot_))); + baseHzT_ = baseLzT_ * pow(2, floor(log2(baseUzT_ / baseLzT_))); + baseHr_ = baseLr_ * pow(2, floor(log2(baseUr_ / baseLr_))); + baseHphi_ = baseLphi_ * pow(2, floor(log2(baseUphi_ / baseLphi_))); + baseHz_ = baseLz_ * pow(2, floor(log2(baseUz_ / baseLz_))); + // calculate digitisation granularity used for inverted cot(theta) + const int baseShiftInvCot = ceil(log2(setup_->outerRadius() / setup_->hybridRangeR())) - setup_->widthDSPbu(); + baseInvCot_ = pow(2, baseShiftInvCot); + } + + // read in and organize input tracks and stubs + void KFin::consume(const StreamsTrack& streamsTrack, const StreamsStub& streamsStub) { + static const double maxCot = sinh(setup_->maxEta()) + setup_->beamWindowZ() / setup_->chosenRofZ(); + static const int unusedMSBcot = floor(log2(baseUcot_ * pow(2, settings_->nbitst()) / (2. * maxCot))); + static const double baseCot = + baseUcot_ * pow(2, settings_->nbitst() - unusedMSBcot - 1 - setup_->widthAddrBRAM18()); + const int offsetTrack = region_ * channelAssignment_->numChannelsTrack(); + // count tracks and stubs to reserve container + int nTracks(0); + int nStubs(0); + for (int channel = 0; channel < channelAssignment_->numChannelsTrack(); channel++) { + const int channelTrack = offsetTrack + channel; + const int offsetStub = channelAssignment_->offsetStub(channelTrack); + const StreamTrack& streamTrack = streamsTrack[channelTrack]; + input_[channel].reserve(streamTrack.size()); + for (int frame = 0; frame < (int)streamTrack.size(); frame++) { + if (streamTrack[frame].first.isNull()) + continue; + nTracks++; + for (int layer = 0; layer < channelAssignment_->numProjectionLayers(channel); layer++) + if (streamsStub[offsetStub + layer][frame].first.isNonnull()) + nStubs++; + } + } + stubs_.reserve(nStubs + nTracks * channelAssignment_->numSeedingLayers()); + tracks_.reserve(nTracks); + // store tracks and stubs + for (int channel = 0; channel < channelAssignment_->numChannelsTrack(); channel++) { + const int channelTrack = offsetTrack + channel; + const int offsetStub = channelAssignment_->offsetStub(channelTrack); + const StreamTrack& streamTrack = streamsTrack[channelTrack]; + vector& input = input_[channel]; + for (int frame = 0; frame < (int)streamTrack.size(); frame++) { + const TTTrackRef& ttTrackRef = streamTrack[frame].first; + if (ttTrackRef.isNull()) { + input.push_back(nullptr); + continue; + } + //convert track parameter + const double r2Inv = digi(-ttTrackRef->rInv() / 2., baseUinv2R_); + const double phi0U = + digi(tt::deltaPhi(ttTrackRef->phi() - region_ * setup_->baseRegion() + setup_->hybridRangePhi() / 2.), + baseUphiT_); + const double phi0S = digi(phi0U - setup_->hybridRangePhi() / 2., baseUphiT_); + const double cot = digi(ttTrackRef->tanL(), baseUcot_); + const double z0 = digi(ttTrackRef->z0(), baseUzT_); + const double phiT = digi(phi0S + r2Inv * digi(dataFormats_->chosenRofPhi(), baseUr_), baseUphiT_); + const double zT = digi(z0 + cot * digi(setup_->chosenRofZ(), baseUr_), baseUzT_); + // kill tracks outside of fiducial range + if (abs(phiT) > setup_->baseRegion() / 2. || abs(zT) > setup_->hybridMaxCot() * setup_->chosenRofZ() || + abs(z0) > setup_->beamWindowZ()) { + input.push_back(nullptr); + continue; + } + // convert stubs + vector stubs; + stubs.reserve(channelAssignment_->numProjectionLayers(channel) + channelAssignment_->numSeedingLayers()); + for (int layer = 0; layer < channelAssignment_->numProjectionLayers(channel); layer++) { + const FrameStub& frameStub = streamsStub[offsetStub + layer][frame]; + const TTStubRef& ttStubRef = frameStub.first; + const int layerId = channelAssignment_->layerId(channel, layer); + if (ttStubRef.isNull()) + continue; + // parse residuals from tt::Frame and take r and layerId from tt::TTStubRef + const bool barrel = setup_->barrel(ttStubRef); + const int layerIdTracklet = channelAssignment_->trackletLayerId(ttStubRef); + const double basePhi = barrel ? settings_->kphi1() : settings_->kphi(layerIdTracklet); + const double baseRZ = barrel ? settings_->kz(layerIdTracklet) : settings_->kz(); + const int widthRZ = barrel ? settings_->zresidbits() : settings_->rresidbits(); + TTBV hw(frameStub.second); + const TTBV hwRZ(hw, widthRZ, 0, true); + hw >>= widthRZ; + const TTBV hwPhi(hw, settings_->phiresidbits(), 0, true); + hw >>= settings_->phiresidbits(); + const double r = digi(setup_->stubR(hw, ttStubRef) - dataFormats_->chosenRofPhi(), baseUr_); + double phi = hwPhi.val(basePhi); + if (basePhi > baseUphi_) + phi += baseUphi_ / 2.; + const double z = digi(hwRZ.val(baseRZ) * (barrel ? 1. : -cot), baseUz_); + // determine module type + bool psTilt; + if (barrel) { + const double posZ = (r + digi(dataFormats_->chosenRofPhi(), baseUr_)) * cot + z0 + z; + const int indexLayerId = setup_->indexLayerId(ttStubRef); + const double limit = setup_->tiltedLayerLimitZ(indexLayerId); + psTilt = abs(posZ) < limit; + } else + psTilt = setup_->psModule(ttStubRef); + if (useTTStubResiduals_) { + const GlobalPoint gp = setup_->stubPos(ttStubRef); + const double ttR = r; + const double ttZ = gp.z() - (z0 + (ttR + dataFormats_->chosenRofPhi()) * cot); + stubs_.emplace_back(ttStubRef, layerId, ttR, phi, ttZ, psTilt); + } else + stubs_.emplace_back(ttStubRef, layerId, r, phi, z, psTilt); + stubs.push_back(&stubs_.back()); + } + // create fake seed stubs, since TrackBuilder doesn't output these stubs, required by the KF. + for (int layerId : channelAssignment_->seedingLayers(channel)) { + const vector& ttStubRefs = ttTrackRef->getStubRefs(); + auto sameLayer = [this, layerId](const TTStubRef& ttStubRef) { + return setup_->layerId(ttStubRef) == layerId; + }; + const TTStubRef& ttStubRef = *find_if(ttStubRefs.begin(), ttStubRefs.end(), sameLayer); + const bool barrel = setup_->barrel(ttStubRef); + double r; + if (barrel) + r = digi(setup_->hybridLayerR(layerId - setup_->offsetLayerId()) - dataFormats_->chosenRofPhi(), baseUr_); + else { + r = (z0 + + digi(setup_->hybridDiskZ(layerId - setup_->offsetLayerId() - setup_->offsetLayerDisks()), baseUzT_)) * + digi(1. / digi(abs(cot), baseCot), baseInvCot_); + r = digi(r - digi(dataFormats_->chosenRofPhi(), baseUr_), baseUr_); + } + static constexpr double phi = 0.; + static constexpr double z = 0.; + // determine module type + bool psTilt; + if (barrel) { + const double posZ = + digi(digi(setup_->hybridLayerR(layerId - setup_->offsetLayerId()), baseUr_) * cot + z0, baseUz_); + const int indexLayerId = setup_->indexLayerId(ttStubRef); + const double limit = digi(setup_->tiltedLayerLimitZ(indexLayerId), baseUz_); + psTilt = abs(posZ) < limit; + } else + psTilt = true; + const GlobalPoint gp = setup_->stubPos(ttStubRef); + const double ttR = gp.perp() - dataFormats_->chosenRofPhi(); + const double ttZ = gp.z() - (z0 + (ttR + dataFormats_->chosenRofPhi()) * cot); + if (useTTStubResiduals_) + stubs_.emplace_back(ttStubRef, layerId, ttR, phi, ttZ, psTilt); + else + stubs_.emplace_back(ttStubRef, layerId, r, phi, z, psTilt); + stubs.push_back(&stubs_.back()); + } + const bool valid = frame < setup_->numFrames() ? true : enableTruncation_; + tracks_.emplace_back(ttTrackRef, valid, r2Inv, phiT, cot, zT, stubs); + input.push_back(&tracks_.back()); + } + } + } + + // fill output products + void KFin::produce(StreamsStub& accpetedStubs, + StreamsTrack& acceptedTracks, + StreamsStub& lostStubs, + StreamsTrack& lostTracks) { + static constexpr int usedMSBpitchOverRaddr = 1; + static const double baseR = + baseLr_ * + pow(2, dataFormats_->width(Variable::r, Process::zht) - setup_->widthAddrBRAM18() + usedMSBpitchOverRaddr); + static const double baseRinvR = + baseLr_ * pow(2, dataFormats_->width(Variable::r, Process::zht) - setup_->widthAddrBRAM18()); + static const double basePhi = baseLinv2R_ * baseLr_; + static const double baseInvR = + pow(2., ceil(log2(baseLr_ / setup_->tbInnerRadius())) - setup_->widthDSPbu()) / baseLr_; + static const double maxCot = sinh(setup_->maxEta()) + setup_->beamWindowZ() / setup_->chosenRofZ(); + static constexpr int usedMSBCotLutaddr = 3; + static const double baseCotLut = pow(2., ceil(log2(maxCot)) - setup_->widthAddrBRAM18() + usedMSBCotLutaddr); + // base transform into high precision TMTT format + for (Track& track : tracks_) { + track.inv2R_ = redigi(track.inv2R_, baseUinv2R_, baseHinv2R_, setup_->widthDSPbu()); + track.phiT_ = redigi(track.phiT_, baseUphiT_, baseHphiT_, setup_->widthDSPbu()); + track.cot_ = redigi(track.cot_, baseUcot_, baseHcot_, setup_->widthDSPbu()); + track.zT_ = redigi(track.zT_, baseUzT_, baseHzT_, setup_->widthDSPbu()); + for (Stub* stub : track.stubs_) { + stub->r_ = redigi(stub->r_, baseUr_, baseHr_, setup_->widthDSPbu()); + stub->phi_ = redigi(stub->phi_, baseUphi_, baseHphi_, setup_->widthDSPbu()); + stub->z_ = redigi(stub->z_, baseUz_, baseHz_, setup_->widthDSPbu()); + } + } + // find sector + for (Track& track : tracks_) { + const int sectorPhi = track.phiT_ < 0. ? 0 : 1; + track.phiT_ -= (sectorPhi - .5) * setup_->baseSector(); + int sectorEta(-1); + for (; sectorEta < setup_->numSectorsEta(); sectorEta++) + if (track.zT_ < digi(setup_->chosenRofZ() * sinh(setup_->boundarieEta(sectorEta + 1)), baseHzT_)) + break; + if (sectorEta >= setup_->numSectorsEta() || sectorEta <= -1) { + track.valid_ = false; + continue; + } + track.cot_ = track.cot_ - digi(setup_->sectorCot(sectorEta), baseHcot_); + track.zT_ = track.zT_ - digi(setup_->chosenRofZ() * setup_->sectorCot(sectorEta), baseHzT_); + track.sector_ = sectorPhi * setup_->numSectorsEta() + sectorEta; + } + // base transform into TMTT format + for (Track& track : tracks_) { + if (!track.valid_) + continue; + // store track parameter shifts + const double dinv2R = digi(track.inv2R_ - digi(track.inv2R_, baseLinv2R_), baseHinv2R_); + const double dphiT = digi(track.phiT_ - digi(track.phiT_, baseLphiT_), baseHphiT_); + const double dcot = digi(track.cot_ - digi(track.cot_, baseLcot_), baseHcot_); + const double dzT = digi(track.zT_ - digi(track.zT_, baseLzT_), baseHzT_); + // shift track parameter; + track.inv2R_ = digi(track.inv2R_, baseLinv2R_); + track.phiT_ = digi(track.phiT_, baseLphiT_); + track.cot_ = digi(track.cot_, baseLcot_); + track.zT_ = digi(track.zT_, baseLzT_); + // range checks + if (!dataFormats_->format(Variable::inv2R, Process::kfin).inRange(track.inv2R_, true)) + track.valid_ = false; + if (!dataFormats_->format(Variable::phiT, Process::kfin).inRange(track.phiT_, true)) + track.valid_ = false; + if (!dataFormats_->format(Variable::cot, Process::kfin).inRange(track.cot_, true)) + track.valid_ = false; + if (!dataFormats_->format(Variable::zT, Process::kfin).inRange(track.zT_, true)) + track.valid_ = false; + if (!track.valid_) + continue; + // adjust stub residuals by track parameter shifts + for (Stub* stub : track.stubs_) { + const double dphi = digi(dphiT + stub->r_ * dinv2R, baseHphi_); + const double r = stub->r_ + digi(dataFormats_->chosenRofPhi() - setup_->chosenRofZ(), baseHr_); + const double dz = digi(dzT + r * dcot, baseHz_); + stub->phi_ = digi(stub->phi_ + dphi, baseLphi_); + stub->z_ = digi(stub->z_ + dz, baseLz_); + // range checks + if (!dataFormats_->format(Variable::phi, Process::kfin).inRange(stub->phi_)) + stub->valid_ = false; + if (!dataFormats_->format(Variable::z, Process::kfin).inRange(stub->z_)) + stub->valid_ = false; + } + } + // encode layer id + for (Track& track : tracks_) { + if (!track.valid_) + continue; + const int sectorEta = track.sector_ % setup_->numSectorsEta(); + const int zT = dataFormats_->format(Variable::zT, Process::kfin).toUnsigned(track.zT_); + const int cot = dataFormats_->format(Variable::cot, Process::kfin).toUnsigned(track.cot_); + track.maybe_ = TTBV(0, setup_->numLayers()); + for (Stub* stub : track.stubs_) { + if (!stub->valid_) + continue; + // replace layerId by encoded layerId + stub->layer_ = layerEncoding_->layerIdKF(sectorEta, zT, cot, stub->layer_); + // kill stubs from layers which can't be crossed by track + if (stub->layer_ == -1) + stub->valid_ = false; + if (stub->valid_) { + if (track.maybe_[stub->layer_]) { + for (Stub* s : track.stubs_) { + if (s == stub) + break; + if (s->layer_ == stub->layer_) + s->valid_ = false; + } + } else + track.maybe_.set(stub->layer_); + } + } + // lookup maybe layers + track.maybe_ &= layerEncoding_->maybePattern(sectorEta, zT, cot); + } + // kill tracks with not enough layer + for (Track& track : tracks_) { + if (!track.valid_) + continue; + TTBV hits(0, setup_->numLayers()); + for (const Stub* stub : track.stubs_) + if (stub->valid_) + hits.set(stub->layer_); + if (hits.count() < setup_->kfMinLayers()) + track.valid_ = false; + } + // calculate stub uncertainties + for (Track& track : tracks_) { + if (!track.valid_) + continue; + const int sectorEta = track.sector_ % setup_->numSectorsEta(); + const double inv2R = abs(track.inv2R_); + for (Stub* stub : track.stubs_) { + if (!stub->valid_) + continue; + const bool barrel = setup_->barrel(stub->ttStubRef_); + const bool ps = barrel ? setup_->psModule(stub->ttStubRef_) : stub->psTilt_; + const bool tilt = barrel ? (ps && !stub->psTilt_) : false; + const double length = ps ? setup_->lengthPS() : setup_->length2S(); + const double pitch = ps ? setup_->pitchPS() : setup_->pitch2S(); + const double pitchOverR = digi(pitch / (digi(stub->r_, baseR) + dataFormats_->chosenRofPhi()), basePhi); + const double r = digi(stub->r_, baseRinvR) + dataFormats_->chosenRofPhi(); + const double sumdz = track.zT_ + stub->z_; + const double dZ = digi(sumdz - digi(setup_->chosenRofZ(), baseLr_) * track.cot_, baseLcot_ * baseLr_); + const double sumcot = track.cot_ + digi(setup_->sectorCot(sectorEta), baseHcot_); + const double cot = digi(abs(dZ * digi(1. / r, baseInvR) + sumcot), baseCotLut); + double lengthZ = length; + double lengthR = 0.; + if (!barrel) { + lengthZ = length * cot; + lengthR = length; + } else if (tilt) { + lengthZ = length * abs(setup_->tiltApproxSlope() * cot + setup_->tiltApproxIntercept()); + lengthR = setup_->tiltUncertaintyR(); + } + const double scat = digi(setup_->scattering(), baseLr_); + stub->dZ_ = lengthZ + baseLz_; + stub->dPhi_ = (scat + digi(lengthR, baseLr_)) * inv2R + pitchOverR; + stub->dPhi_ = digi(stub->dPhi_, baseLphi_) + baseLphi_; + } + } + // fill products StreamsStub& accpetedStubs, StreamsTrack& acceptedTracks, StreamsStub& lostStubs, StreamsTrack& lostTracks + auto frameTrack = [this](Track* track) { + const TTBV maybe(track->maybe_); + const TTBV sectorPhi( + dataFormats_->format(Variable::sectorPhi, Process::kfin).ttBV(track->sector_ / setup_->numSectorsEta())); + const TTBV sectorEta( + dataFormats_->format(Variable::sectorEta, Process::kfin).ttBV(track->sector_ % setup_->numSectorsEta())); + const TTBV inv2R(dataFormats_->format(Variable::inv2R, Process::kfin).ttBV(track->inv2R_)); + const TTBV phiT(dataFormats_->format(Variable::phiT, Process::kfin).ttBV(track->phiT_)); + const TTBV cot(dataFormats_->format(Variable::cot, Process::kfin).ttBV(track->cot_)); + const TTBV zT(dataFormats_->format(Variable::zT, Process::kfin).ttBV(track->zT_)); + return FrameTrack(track->ttTrackRef_, + Frame("1" + maybe.str() + sectorPhi.str() + sectorEta.str() + phiT.str() + inv2R.str() + + zT.str() + cot.str())); + }; + auto frameStub = [this](Track* track, int layer) { + auto equal = [layer](Stub* stub) { return stub->valid_ && stub->layer_ == layer; }; + const auto it = find_if(track->stubs_.begin(), track->stubs_.end(), equal); + if (it == track->stubs_.end() || !(*it)->valid_) + return FrameStub(); + Stub* stub = *it; + const TTBV r(dataFormats_->format(Variable::r, Process::kfin).ttBV(stub->r_)); + const TTBV phi(dataFormats_->format(Variable::phi, Process::kfin).ttBV(stub->phi_)); + const TTBV z(dataFormats_->format(Variable::z, Process::kfin).ttBV(stub->z_)); + const TTBV dPhi(dataFormats_->format(Variable::dPhi, Process::kfin).ttBV(stub->dPhi_)); + const TTBV dZ(dataFormats_->format(Variable::dZ, Process::kfin).ttBV(stub->dZ_)); + return FrameStub(stub->ttStubRef_, Frame("1" + r.str() + phi.str() + z.str() + dPhi.str() + dZ.str())); + }; + auto invalid = [](Track* track) { return track && !track->valid_; }; + auto acc = [invalid](int& sum, Track* track) { return sum += (invalid(track) ? 1 : 0); }; + const int offsetTrack = region_ * channelAssignment_->numChannelsTrack(); + for (int channel = 0; channel < channelAssignment_->numChannelsTrack(); channel++) { + const int channelTrack = offsetTrack + channel; + const int offsetStub = channelTrack * setup_->numLayers(); + vector& input = input_[channel]; + // fill lost tracks and stubs without gaps + const int lost = accumulate(input.begin(), input.end(), 0, acc); + lostTracks[channelTrack].reserve(lost); + for (int layer = 0; layer < setup_->numLayers(); layer++) + lostStubs[offsetStub + layer].reserve(lost); + for (Track* track : input) { + if (!track || track->valid_) + continue; + lostTracks[channelTrack].emplace_back(frameTrack(track)); + for (int layer = 0; layer < setup_->numLayers(); layer++) + lostStubs[offsetStub + layer].emplace_back(frameStub(track, layer)); + } + // fill accepted tracks and stubs with gaps + acceptedTracks[channelTrack].reserve(input.size()); + for (int layer = 0; layer < setup_->numLayers(); layer++) + accpetedStubs[offsetStub + layer].reserve(input.size()); + for (Track* track : input) { + if (!track || !track->valid_) { // fill gap + acceptedTracks[channelTrack].emplace_back(FrameTrack()); + for (int layer = 0; layer < setup_->numLayers(); layer++) + accpetedStubs[offsetStub + layer].emplace_back(FrameStub()); + continue; + } + acceptedTracks[channelTrack].emplace_back(frameTrack(track)); + for (int layer = 0; layer < setup_->numLayers(); layer++) + accpetedStubs[offsetStub + layer].emplace_back(frameStub(track, layer)); + } + } + } + + // basetransformation of val from baseLow into baseHigh using widthMultiplier bit multiplication + double KFin::redigi(double val, double baseLow, double baseHigh, int widthMultiplier) const { + const double base = pow(2, 1 - widthMultiplier); + const double transform = digi(baseLow / baseHigh, base); + return (floor(val * transform / baseLow) + .5) * baseHigh; + } + +} // namespace trklet \ No newline at end of file diff --git a/L1Trigger/TrackFindingTracklet/src/L1TStub.cc b/L1Trigger/TrackFindingTracklet/src/L1TStub.cc index d7cc37d26b863..d2078be8d95cd 100644 --- a/L1Trigger/TrackFindingTracklet/src/L1TStub.cc +++ b/L1Trigger/TrackFindingTracklet/src/L1TStub.cc @@ -11,6 +11,10 @@ L1TStub::L1TStub(std::string DTClink, std::string stubword, int isPSmodule, int isFlipped, + bool tiltedBarrel, + unsigned int tiltedRingId, + unsigned int endcapRingId, + unsigned int detId, double x, double y, double z, @@ -32,8 +36,6 @@ L1TStub::L1TStub(std::string DTClink, layer_ += 1000; } - ladder_ = -1; - module_ = -1; strip_ = strip; x_ = x; y_ = y; @@ -44,6 +46,10 @@ L1TStub::L1TStub(std::string DTClink, bend_ = bend; isPSmodule_ = isPSmodule; isFlipped_ = isFlipped; + tiltedBarrel_ = tiltedBarrel; + tiltedRingId_ = tiltedRingId; + endcapRingId_ = endcapRingId; + detId_ = detId; allstubindex_ = 999; } @@ -59,8 +65,7 @@ void L1TStub::write(ofstream& out) { } bool L1TStub::operator==(const L1TStub& other) const { - return (other.iphi() == iphi_ && other.iz() == iz_ && other.layer() == layer_ && other.ladder() == ladder_ && - other.module() == module_); + return (other.iphi() == iphi_ && other.iz() == iz_ && other.layer() == layer_ && other.detId() == detId_); } void L1TStub::lorentzcor(double shift) { @@ -122,15 +127,3 @@ bool L1TStub::tpmatch2(int tp) const { return match1 && match2; } - -bool L1TStub::isTilted() const { - //here layer_ runs 0-5 for barrel, >1000 for disk - //disk modules and outer barrel modules are not tilted by construction - if (layer_ >= N_PSLAYER) - return false; - - assert(layer_ < N_PSLAYER); // safety for acccessing # modules/plank - if ((module_ <= N_TILTED_RINGS) || (module_ >= N_TILTED_RINGS + N_MOD_PLANK.at(layer_))) - return true; - return false; -} diff --git a/L1Trigger/TrackFindingTracklet/src/MatchCalculator.cc b/L1Trigger/TrackFindingTracklet/src/MatchCalculator.cc index f63e1ece941d8..bda660edffddc 100644 --- a/L1Trigger/TrackFindingTracklet/src/MatchCalculator.cc +++ b/L1Trigger/TrackFindingTracklet/src/MatchCalculator.cc @@ -14,6 +14,7 @@ #include "DataFormats/Math/interface/deltaPhi.h" #include +#include using namespace std; using namespace trklet; @@ -113,15 +114,23 @@ void MatchCalculator::addInput(MemoryBase* memory, string input) { throw cms::Exception("BadConfig") << __FILE__ << " " << __LINE__ << " could not find input " << input; } -void MatchCalculator::execute(double phioffset) { +void MatchCalculator::execute(unsigned int iSector, double phioffset) { unsigned int countall = 0; unsigned int countsel = 0; + //bool print = getName() == "MC_L4PHIC" && iSector == 3; + Tracklet* oldTracklet = nullptr; std::vector, const Stub*> > mergedMatches = mergeMatches(matches_); - for (unsigned int j = 0; j < mergedMatches.size(); j++) { + // Number of clock cycles the pipeline in HLS takes to process the projection merging to + // produce the first projectio + unsigned int mergedepth = 3; + + unsigned int maxProc = std::min(settings_.maxStep("MC") - mergedepth, (unsigned int)mergedMatches.size()); + + for (unsigned int j = 0; j < maxProc; j++) { if (settings_.debugTracklet() && j == 0) { edm::LogVerbatim("Tracklet") << getName() << " has " << mergedMatches.size() << " candidate matches"; } @@ -221,17 +230,32 @@ void MatchCalculator::execute(double phioffset) { } bool imatch = (std::abs(ideltaphi) <= (int)phimatchcuttable_.lookup(seedindex)) && - (std::abs(ideltaz * fact_) <= (int)zmatchcuttable_.lookup(seedindex)); + (ideltaz * fact_ < (int)zmatchcuttable_.lookup(seedindex)) && + (ideltaz * fact_ >= -(int)zmatchcuttable_.lookup(seedindex)); + + bool keep = true; + if (!settings_.doKF() || !settings_.doMultipleMatches()) { + // Case of allowing only one stub per track per layer (or no KF which implies the same). + if (imatch && tracklet->match(layerdisk_)) { + // Veto match if is not the best one for this tracklet (in given layer) + auto res = tracklet->resid(layerdisk_); + keep = abs(ideltaphi) < abs(res.fpgaphiresid().value()); + imatch = keep; + } + } if (settings_.debugTracklet()) { - edm::LogVerbatim("Tracklet") << getName() << " imatch = " << imatch << " ideltaphi cut " << ideltaphi << " " - << phimatchcuttable_.lookup(seedindex) << " ideltaz*fact cut " << ideltaz * fact_ - << " " << zmatchcuttable_.lookup(seedindex); + edm::LogVerbatim("Tracklet") << getName() << " imatch = " << imatch << " keep = " << keep << " ideltaphi cut " + << ideltaphi << " " << phimatchcuttable_.lookup(seedindex) << " ideltaz*fact cut " + << ideltaz * fact_ << " " << zmatchcuttable_.lookup(seedindex); } if (imatch) { countsel++; + // TO DO: storing the matches in both FullMatchMemory & Tracklet is ugly. + // Should clean this up, to avoid the need to store them in Tracklet. + tracklet->addMatch(layerdisk_, ideltaphi, ideltaz, @@ -279,7 +303,6 @@ void MatchCalculator::execute(double phioffset) { ir += ircorr; int ideltaphi = fpgastub->phi().value() * settings_.kphi() / settings_.kphi() - iphi; - int irstub = fpgastub->r().value(); int ialphafact = 0; if (!stub->isPSmodule()) { @@ -385,10 +408,25 @@ void MatchCalculator::execute(double phioffset) { match = false; imatch = false; } + + bool keep = true; + if (!settings_.doKF() || !settings_.doMultipleMatches()) { + // Case of allowing only one stub per track per layer (or no KF which implies the same). + if (imatch && tracklet->match(layerdisk_)) { + // Veto match if is not the best one for this tracklet (in given layer) + auto res = tracklet->resid(layerdisk_); + keep = abs(ideltaphi) < abs(res.fpgaphiresid().value()); + imatch = keep; + } + } + if (not keep) + match = false; // FIX: should calc keep with float point here. + if (settings_.debugTracklet()) { - edm::LogVerbatim("Tracklet") << "imatch match disk: " << imatch << " " << match << " " << std::abs(ideltaphi) - << " " << drphicut / (settings_.kphi() * stub->r()) << " " << std::abs(ideltar) - << " " << drcut / settings_.krprojshiftdisk() << " r = " << stub->r(); + edm::LogVerbatim("Tracklet") << "imatch match disk: " << imatch << " " << match << " keep = " << keep << " " + << std::abs(ideltaphi) << " " << drphicut / (settings_.kphi() * stub->r()) << " " + << std::abs(ideltar) << " " << drcut / settings_.krprojshiftdisk() + << " r = " << stub->r(); } if (imatch) { diff --git a/L1Trigger/TrackFindingTracklet/src/MatchEngine.cc b/L1Trigger/TrackFindingTracklet/src/MatchEngine.cc index ae6ef25cfc1fb..a6fff9eb7dc3a 100644 --- a/L1Trigger/TrackFindingTracklet/src/MatchEngine.cc +++ b/L1Trigger/TrackFindingTracklet/src/MatchEngine.cc @@ -60,11 +60,11 @@ void MatchEngine::addInput(MemoryBase* memory, string input) { throw cms::Exception("BadConfig") << __FILE__ << " " << __LINE__ << " could not find input: " << input; } -void MatchEngine::execute() { +void MatchEngine::execute(unsigned int iSector) { unsigned int countall = 0; unsigned int countpass = 0; - bool print = (getName() == "ME_L3PHIC20"); + bool print = (iSector == 3 && getName() == "ME_L3PHIC20"); print = false; constexpr unsigned int kNBitsBuffer = 3; @@ -222,10 +222,22 @@ void MatchEngine::execute() { //Read vmstub memory and extract data fields const VMStubME& vmstub = vmstubs_->getVMStubMEBin(rzbin, istubtmp); - bool isPSmodule = vmstub.isPSmodule(); - int stubfinerz = vmstub.finerz().value(); + bool isPSmodule = false; + + if (barrel_) { + isPSmodule = layerdisk_ < N_PSLAYER; + } else { + if (layerdisk_ < N_LAYER + 2) { + isPSmodule = ((rzbin & 7) < 3) || ((rzbin & 7) == 3 && stubfinerz <= 3); + } else { + isPSmodule = ((rzbin & 7) < 3) || ((rzbin & 7) == 3 && stubfinerz <= 2); + } + } + + assert(isPSmodule == vmstub.isPSmodule()); + int nbits = isPSmodule ? N_BENDBITS_PS : N_BENDBITS_2S; int deltaphi = projfinephi - vmstub.finephi().value(); diff --git a/L1Trigger/TrackFindingTracklet/src/MatchEngineUnit.cc b/L1Trigger/TrackFindingTracklet/src/MatchEngineUnit.cc index 43b3ee79cbe46..30d6762c7f139 100644 --- a/L1Trigger/TrackFindingTracklet/src/MatchEngineUnit.cc +++ b/L1Trigger/TrackFindingTracklet/src/MatchEngineUnit.cc @@ -1,20 +1,26 @@ #include "L1Trigger/TrackFindingTracklet/interface/MatchEngineUnit.h" #include "L1Trigger/TrackFindingTracklet/interface/TrackletLUT.h" +#include "L1Trigger/TrackFindingTracklet/interface/Settings.h" using namespace std; using namespace trklet; -MatchEngineUnit::MatchEngineUnit(bool barrel, unsigned int layerdisk, const TrackletLUT& luttable) - : luttable_(luttable), candmatches_(3) { +MatchEngineUnit::MatchEngineUnit(const Settings& settings, + bool barrel, + unsigned int layerdisk, + const TrackletLUT& luttable) + : settings_(settings), luttable_(luttable), candmatches_(3) { idle_ = true; + print_ = false; + imeu_ = -1; barrel_ = barrel; layerdisk_ = layerdisk; - goodpair_ = false; - goodpair__ = false; - havepair_ = false; - havepair__ = false; + good__ = false; + good___ = false; } +void MatchEngineUnit::setAlmostFull() { almostfullsave_ = candmatches_.nearfull(); } + void MatchEngineUnit::init(VMStubsMEMemory* vmstubsmemory, unsigned int nrzbins, unsigned int rzbin, @@ -28,8 +34,7 @@ void MatchEngineUnit::init(VMStubsMEMemory* vmstubsmemory, bool usesecondMinus, bool usesecondPlus, bool isPSseed, - Tracklet* proj, - bool) { + Tracklet* proj) { vmstubsmemory_ = vmstubsmemory; idle_ = false; nrzbins_ = nrzbins; @@ -58,126 +63,112 @@ void MatchEngineUnit::init(VMStubsMEMemory* vmstubsmemory, isPSseed_ = isPSseed; proj_ = proj; - //Even when you init a new projection you need to process the pipeline - //This should be fixed to be done more cleanly - but require synchronizaton - //with the HLS code - if (goodpair__) { - candmatches_.store(tmppair__); - } - - havepair__ = havepair_; - goodpair__ = goodpair_; - tmppair__ = tmppair_; - - havepair_ = false; - goodpair_ = false; + good__ = false; } -void MatchEngineUnit::step(bool) { - bool almostfull = candmatches_.nearfull(); - - if (goodpair__) { - assert(havepair__); - candmatches_.store(tmppair__); - } - - havepair__ = havepair_; - goodpair__ = goodpair_; - tmppair__ = tmppair_; - - havepair_ = false; - goodpair_ = false; +void MatchEngineUnit::step() { + good__ = !idle() && !almostfullsave_; - if (idle() || almostfull) + if (!good__) return; unsigned int slot = (phibin_ + use_[iuse_].second) * nrzbins_ + rzbin_ + use_[iuse_].first; - int projfinerz = projfinerz_ - (1 << NFINERZBITS) * use_[iuse_].first; - int projfinephi = projfinephi_; + projfinerz__ = projfinerz_ - (1 << NFINERZBITS) * use_[iuse_].first; + projfinephi__ = projfinephi_; if (use_[iuse_].second == 0) { if (shift_ == -1) { - projfinephi -= (1 << NFINEPHIBITS); + projfinephi__ -= (1 << NFINEPHIBITS); } } else { //When we get here shift_ is either 1 or -1 if (shift_ == 1) { - projfinephi += (1 << NFINEPHIBITS); + projfinephi__ += (1 << NFINEPHIBITS); } } - const VMStubME& vmstub = vmstubsmemory_->getVMStubMEBin(slot, istub_); + vmstub__ = vmstubsmemory_->getVMStubMEBin(slot, istub_); - bool isPSmodule = vmstub.isPSmodule(); - int stubfinerz = vmstub.finerz().value(); - int stubfinephi = vmstub.finephi().value(); + isPSseed__ = isPSseed_; + projrinv__ = projrinv_; + proj__ = proj_; - int deltaphi = stubfinephi - projfinephi; + istub_++; + if (istub_ >= vmstubsmemory_->nStubsBin(slot)) { + iuse_++; + if (iuse_ < use_.size()) { + istub_ = 0; + } else { + idle_ = true; + } + } +} - bool dphicut = (abs(deltaphi) < 3); +void MatchEngineUnit::processPipeline() { + if (good___) { + bool isPSmodule = vmstub___.isPSmodule(); + int stubfinerz = vmstub___.finerz().value(); + int stubfinephi = vmstub___.finephi().value(); - int nbits = isPSmodule ? 3 : 4; + int deltaphi = stubfinephi - projfinephi___; - int diskps = (!barrel_) && isPSmodule; + constexpr int idphicut = 3; - unsigned int index = (diskps << (4 + 5)) + (projrinv_ << nbits) + vmstub.bend().value(); + bool dphicut = (abs(deltaphi) < idphicut); - //Check if stub z position consistent - int idrz = stubfinerz - projfinerz; - bool pass; + int nbits = isPSmodule ? N_BENDBITS_PS : N_BENDBITS_2S; - if (barrel_) { - if (isPSseed_) { - pass = idrz >= -1 && idrz <= 1; - } else { - pass = idrz >= -5 && idrz <= 5; - } - } else { - if (isPSmodule) { - pass = idrz >= -1 && idrz <= 1; - } else { - pass = idrz >= -3 && idrz <= 3; - } - } + int diskps = (!barrel_) && isPSmodule; - // Detailed printout for comparison with HLS code - bool print = false; - if (print) - edm::LogVerbatim("Tracklet") << "MEU TrkId stubindex : " << 128 * proj_->TCIndex() + proj_->trackletIndex() << " " - << vmstub.stubindex().value() << " " - << ((pass && dphicut) && luttable_.lookup(index)) << " index=" << index - << " projrinv bend : " << projrinv_ << " " << vmstub.bend().value() - << " shift_ isPSseed_ :" << shift_ << " " << isPSseed_ << " slot=" << slot; + //here we always use the larger number of bits for the bend + unsigned int index = (diskps << (N_BENDBITS_2S + NRINVBITS)) + (projrinv___ << nbits) + vmstub___.bend().value(); - //Check if stub bend and proj rinv consistent + //Check if stub z position consistent + int idrz = stubfinerz - projfinerz___; + bool pass; - goodpair_ = (pass && dphicut) && luttable_.lookup(index); - havepair_ = true; + if (barrel_) { + if (isPSseed___) { + constexpr int drzcut = 1; + pass = std::abs(idrz) <= drzcut; + } else { + constexpr int drzcut = 5; + pass = std::abs(idrz) <= drzcut; + } + } else { + if (isPSmodule) { + constexpr int drzcut = 1; + pass = std::abs(idrz) <= drzcut; + } else { + constexpr int drzcut = 3; + pass = std::abs(idrz) <= drzcut; + } + } - if (havepair_) { - std::pair tmppair(proj_, vmstub.stub()); - tmppair_ = tmppair; - } + bool goodpair = (pass && dphicut) && luttable_.lookup(index); - istub_++; - if (istub_ >= vmstubsmemory_->nStubsBin(slot)) { - iuse_++; - if (iuse_ < use_.size()) { - istub_ = 0; - } else { - idle_ = true; + std::pair tmppair(proj___, vmstub___.stub()); + + if (goodpair) { + candmatches_.store(tmppair); } } + + proj___ = proj__; + projfinephi___ = projfinephi__; + projfinerz___ = projfinerz__; + projrinv___ = projrinv__; + isPSseed___ = isPSseed__; + good___ = good__; + vmstub___ = vmstub__; } void MatchEngineUnit::reset() { candmatches_.reset(); idle_ = true; istub_ = 0; - goodpair_ = false; - goodpair__ = false; - havepair_ = false; - havepair__ = false; + good__ = false; + good___ = false; } int MatchEngineUnit::TCID() const { @@ -185,14 +176,17 @@ int MatchEngineUnit::TCID() const { return peek().first->TCID(); } - if (idle_ && !havepair_ && !havepair__) { - return 16383; + if (good___) { + return proj___->TCID(); } - if (havepair__) { - return tmppair__.first->TCID(); + + if (good__) { + return proj__->TCID(); } - if (havepair_) { - return tmppair_.first->TCID(); + + if (idle_) { + return (1 << (settings_.nbitstrackletindex() + settings_.nbitstcindex())) - 1; } + return proj_->TCID(); } diff --git a/L1Trigger/TrackFindingTracklet/src/MatchProcessor.cc b/L1Trigger/TrackFindingTracklet/src/MatchProcessor.cc index 6c0526337f9b4..0d4e3a056c41c 100644 --- a/L1Trigger/TrackFindingTracklet/src/MatchProcessor.cc +++ b/L1Trigger/TrackFindingTracklet/src/MatchProcessor.cc @@ -82,7 +82,8 @@ MatchProcessor::MatchProcessor(string name, Settings const& settings, Globals* g nMatchEngines_ = 4; for (unsigned int iME = 0; iME < nMatchEngines_; iME++) { - MatchEngineUnit tmpME(barrel_, layerdisk_, luttable_); + MatchEngineUnit tmpME(settings_, barrel_, layerdisk_, luttable_); + tmpME.setimeu(iME); matchengines_.push_back(tmpME); } } @@ -135,15 +136,16 @@ void MatchProcessor::execute(unsigned int iSector, double phimin) { /* The code is organized in three 'steps' corresponding to the PR, ME, and MC functions. The output from - the PR step is buffered in a 'circular' buffer, and similarly the ME output is put in a circular buffer. - - The implementation is done in steps, emulating what can be done in firmware. One each step we do: + the PR step is buffered in a 'circular' buffer, and similarly the ME output is put in a circular buffer. + The implementation is done in steps, emulating what can be done in firmware. On each step we do: 1) A projection is read and if there is space it is insert into the inputProjBuffer_ 2) Process next match in the ME - if there is an idle ME the next projection is inserted 3) Readout match from ME and send to match calculator + + However, for the pipelining to work in HLS these blocks are executed in reverse order */ @@ -181,8 +183,6 @@ void MatchProcessor::execute(unsigned int iSector, double phimin) { bool good__ = false; for (unsigned int istep = 0; istep < settings_.maxStep("MP"); istep++) { - bool projBuffNearFull = inputProjBuffer_.nearfull(); - // This print statement is useful for detailed comparison with the HLS code // It prints out detailed status information for each clock step /* @@ -192,7 +192,6 @@ void MatchProcessor::execute(unsigned int iSector, double phimin) { for (auto& matchengine : matchengines_) { cout <<" MEU"< candmatch = matchengines_[iMEbest].read(); const Stub* fpgastub = candmatch.second; Tracklet* tracklet = candmatch.first; + //Consistency check if (oldTracklet != nullptr) { //allow equal here since we can have more than one cadidate match per tracklet projection //cout << "old new : "<TCID()<<" "<TCID()<<" "<getName(); - } - - Tracklet* proj = projMem->getTracklet(iproj); - - FPGAWord fpgaphi = proj->proj(layerdisk_).fpgaphiproj(); - - unsigned int iphi = (fpgaphi.value() >> (fpgaphi.nbits() - nvmbits_)) & (nvmbins_ - 1); - - int nextrabits = 2; - int overlapbits = nvmbits_ + nextrabits; - - unsigned int extrabits = fpgaphi.bits(fpgaphi.nbits() - overlapbits, nextrabits); - - unsigned int ivmPlus = iphi; - - int shift = 0; - - if (extrabits == ((1U << nextrabits) - 1) && iphi != ((1U << settings_.nbitsvmme(layerdisk_)) - 1)) { - shift = 1; - ivmPlus++; - } - unsigned int ivmMinus = iphi; - if (extrabits == 0 && iphi != 0) { - shift = -1; - ivmMinus--; - } - - int projrinv = -1; - if (barrel_) { - FPGAWord phider = proj->proj(layerdisk_).fpgaphiprojder(); - projrinv = (1 << (nrinv_ - 1)) - 1 - (phider.value() >> (phider.nbits() - nrinv_)); - } else { - //The next lines looks up the predicted bend based on: - // 1 - r projections - // 2 - phi derivative - // 3 - the sign - i.e. if track is forward or backward - - int rindex = (proj->proj(layerdisk_).fpgarzproj().value() >> - (proj->proj(layerdisk_).fpgarzproj().nbits() - nrbits_)) & - ((1 << nrbits_) - 1); - - int phiderindex = (proj->proj(layerdisk_).fpgaphiprojder().value() >> - (proj->proj(layerdisk_).fpgaphiprojder().nbits() - nphiderbits_)) & - ((1 << nphiderbits_) - 1); - - int signindex = proj->proj(layerdisk_).fpgarzprojder().value() < 0; - - int bendindex = (signindex << (nphiderbits_ + nrbits_)) + (rindex << (nphiderbits_)) + phiderindex; - - projrinv = rinvbendlut_.lookup(bendindex); - - proj->proj(layerdisk_).setBendIndex(projrinv); - } - assert(projrinv >= 0); - - unsigned int slot = proj->proj(layerdisk_).fpgarzbin1projvm().value(); - bool second = proj->proj(layerdisk_).fpgarzbin2projvm().value(); - - unsigned int projfinephi = - (fpgaphi.value() >> (fpgaphi.nbits() - (nvmbits_ + NFINEPHIBITS))) & ((1 << NFINEPHIBITS) - 1); - int projfinerz = proj->proj(layerdisk_).fpgafinerzvm().value(); - - bool isPSseed = proj->PSseed(); - - int nbins = (1 << N_RZBITS); - if (layerdisk_ >= N_LAYER) { - nbins *= 2; //twice as many bins in disks (since there are two disks) - } - - VMStubsMEMemory* stubmem = vmstubs_[0]; - bool usefirstMinus = stubmem->nStubsBin(ivmMinus * nbins + slot) != 0; - bool usesecondMinus = (second && (stubmem->nStubsBin(ivmMinus * nbins + slot + 1) != 0)); - bool usefirstPlus = ivmPlus != ivmMinus && stubmem->nStubsBin(ivmPlus * nbins + slot) != 0; - bool usesecondPlus = ivmPlus != ivmMinus && (second && (stubmem->nStubsBin(ivmPlus * nbins + slot + 1) != 0)); - - good_ = usefirstPlus || usesecondPlus || usefirstMinus || usesecondMinus; - - if (good_) { - ProjectionTemp tmpProj(proj, - slot, - projrinv, - projfinerz, - projfinephi, - ivmMinus, - shift, - usefirstMinus, - usefirstPlus, - usesecondMinus, - usesecondPlus, - isPSseed); - tmpProj_ = tmpProj; - } - - iproj++; - if (iproj == projMem->nTracklets()) { - iproj = 0; - do { - iprojmem++; - } while (iprojmem < inputprojs_.size() && inputprojs_[iprojmem]->nTracklets() == 0); - } + if (iprojmem < inputprojs_.size()) { + TrackletProjectionsMemory* projMem = inputprojs_[iprojmem]; + if (!projBuffNearFull) { + if (settings_.debugTracklet()) { + edm::LogVerbatim("Tracklet") << getName() << " have projection in memory : " << projMem->getName(); + } + + Tracklet* proj = projMem->getTracklet(iproj); + + FPGAWord fpgaphi = proj->proj(layerdisk_).fpgaphiproj(); + + unsigned int iphi = (fpgaphi.value() >> (fpgaphi.nbits() - nvmbits_)) & (nvmbins_ - 1); + + int nextrabits = 2; + int overlapbits = nvmbits_ + nextrabits; + + unsigned int extrabits = fpgaphi.bits(fpgaphi.nbits() - overlapbits - nextrabits, nextrabits); + + unsigned int ivmPlus = iphi; + + int shift = 0; + + if (extrabits == ((1U << nextrabits) - 1) && iphi != ((1U << settings_.nbitsvmme(layerdisk_)) - 1)) { + shift = 1; + ivmPlus++; + } + unsigned int ivmMinus = iphi; + if (extrabits == 0 && iphi != 0) { + shift = -1; + ivmMinus--; + } + + int projrinv = -1; + if (barrel_) { + FPGAWord phider = proj->proj(layerdisk_).fpgaphiprojder(); + projrinv = (1 << (nrinv_ - 1)) - 1 - (phider.value() >> (phider.nbits() - nrinv_)); + } else { + //The next lines looks up the predicted bend based on: + // 1 - r projections + // 2 - phi derivative + // 3 - the sign - i.e. if track is forward or backward + + int rindex = + (proj->proj(layerdisk_).fpgarzproj().value() >> (proj->proj(layerdisk_).fpgarzproj().nbits() - nrbits_)) & + ((1 << nrbits_) - 1); + + int phiprojder = proj->proj(layerdisk_).fpgaphiprojder().value(); + + int phiderindex = (phiprojder >> (proj->proj(layerdisk_).fpgaphiprojder().nbits() - nphiderbits_)) & + ((1 << nphiderbits_) - 1); + + int signindex = proj->proj(layerdisk_).fpgarzprojder().value() < 0; + + int bendindex = (signindex << (nphiderbits_ + nrbits_)) + (rindex << (nphiderbits_)) + phiderindex; + + projrinv = rinvbendlut_.lookup(bendindex); + + proj->proj(layerdisk_).setBendIndex(projrinv); + } + assert(projrinv >= 0); + + unsigned int slot = proj->proj(layerdisk_).fpgarzbin1projvm().value(); + bool second = proj->proj(layerdisk_).fpgarzbin2projvm().value(); + + unsigned int projfinephi = + (fpgaphi.value() >> (fpgaphi.nbits() - (nvmbits_ + NFINEPHIBITS))) & ((1 << NFINEPHIBITS) - 1); + int projfinerz = proj->proj(layerdisk_).fpgafinerzvm().value(); + + bool isPSseed = proj->PSseed(); + + int nbins = (1 << N_RZBITS); + if (layerdisk_ >= N_LAYER) { + nbins *= 2; //twice as many bins in disks (since there are two disks) + } + + VMStubsMEMemory* stubmem = vmstubs_[0]; + bool usefirstMinus = stubmem->nStubsBin(ivmMinus * nbins + slot) != 0; + bool usesecondMinus = (second && (stubmem->nStubsBin(ivmMinus * nbins + slot + 1) != 0)); + bool usefirstPlus = ivmPlus != ivmMinus && stubmem->nStubsBin(ivmPlus * nbins + slot) != 0; + bool usesecondPlus = ivmPlus != ivmMinus && (second && (stubmem->nStubsBin(ivmPlus * nbins + slot + 1) != 0)); + + good_ = usefirstPlus || usesecondPlus || usefirstMinus || usesecondMinus; + + if (good_) { + ProjectionTemp tmpProj(proj, + slot, + projrinv, + projfinerz, + projfinephi, + ivmMinus, + shift, + usefirstMinus, + usefirstPlus, + usesecondMinus, + usesecondPlus, + isPSseed); + tmpProj_ = tmpProj; + } + + iproj++; + if (iproj == projMem->nTracklets()) { + iproj = 0; + do { + iprojmem++; + } while (iprojmem < inputprojs_.size() && inputprojs_[iprojmem]->nTracklets() == 0); } } else { @@ -415,7 +425,8 @@ void MatchProcessor::execute(unsigned int iSector, double phimin) { // // - if ((projdone && !meactive) || (istep == settings_.maxStep("MP") - 1)) { + if ((projdone && !meactive && inputProjBuffer_.rptr() == inputProjBuffer_.wptr()) || + (istep == settings_.maxStep("MP") - 1)) { if (settings_.writeMonitorData("MP")) { globals_->ofstream("matchprocessor.txt") << getName() << " " << istep << " " << countall << " " << countsel << " " << countme << " " << countinputproj << endl; @@ -506,7 +517,8 @@ bool MatchProcessor::matchCalculator(Tracklet* tracklet, const Stub* fpgastub, b } bool imatch = (std::abs(ideltaphi) <= phimatchcuttable_.lookup(seedindex)) && - (std::abs(ideltaz << dzshift_) <= zmatchcuttable_.lookup(seedindex)); + (ideltaz << dzshift_ < zmatchcuttable_.lookup(seedindex)) && + (ideltaz << dzshift_ >= -zmatchcuttable_.lookup(seedindex)); if (settings_.debugTracklet()) { edm::LogVerbatim("Tracklet") << getName() << " imatch = " << imatch << " ideltaphi cut " << ideltaphi << " " @@ -520,6 +532,17 @@ bool MatchProcessor::matchCalculator(Tracklet* tracklet, const Stub* fpgastub, b << endl; } + bool keep = true; + if (!settings_.doKF() || !settings_.doMultipleMatches()) { + // Case of allowing only one stub per track per layer (or no KF which implies the same). + if (imatch && tracklet->match(layerdisk_)) { + // Veto match if is not the best one for this tracklet (in given layer) + auto res = tracklet->resid(layerdisk_); + keep = abs(ideltaphi) < abs(res.fpgaphiresid().value()); + imatch = keep; + } + } + if (imatch) { tracklet->addMatch(layerdisk_, ideltaphi, @@ -671,6 +694,19 @@ bool MatchProcessor::matchCalculator(Tracklet* tracklet, const Stub* fpgastub, b << " " << drcut / settings_.krprojshiftdisk() << " r = " << stub->r(); } + bool keep = true; + if (!settings_.doKF() || !settings_.doMultipleMatches()) { + // Case of allowing only one stub per track per layer (or no KF which implies the same). + if (imatch && tracklet->match(layerdisk_)) { + // Veto match if is not the best one for this tracklet (in given layer) + auto res = tracklet->resid(layerdisk_); + keep = abs(ideltaphi) < abs(res.fpgaphiresid().value()); + imatch = keep; + } + } + if (not keep) + match = false; // FIX: should calc keep with float point here. + if (imatch) { if (settings_.debugTracklet()) { edm::LogVerbatim("Tracklet") << "MatchCalculator found match in disk " << getName(); diff --git a/L1Trigger/TrackFindingTracklet/src/MemoryBase.cc b/L1Trigger/TrackFindingTracklet/src/MemoryBase.cc index 580dae3a8df7f..f0461f2c20ddd 100644 --- a/L1Trigger/TrackFindingTracklet/src/MemoryBase.cc +++ b/L1Trigger/TrackFindingTracklet/src/MemoryBase.cc @@ -6,6 +6,7 @@ #include #include +#include using namespace trklet; using namespace std; @@ -106,3 +107,9 @@ size_t MemoryBase::find_nth(const string& haystack, size_t pos, const string& ne return found_pos; return find_nth(haystack, found_pos + 1, needle, nth - 1); } + +std::string MemoryBase::hexstr(unsigned int index) { + std::ostringstream oss; + oss << "0x" << std::setfill('0') << std::setw(2) << hex << index << dec; + return oss.str(); +} diff --git a/L1Trigger/TrackFindingTracklet/src/PurgeDuplicate.cc b/L1Trigger/TrackFindingTracklet/src/PurgeDuplicate.cc index c334a7c488b01..b186cde0ab151 100644 --- a/L1Trigger/TrackFindingTracklet/src/PurgeDuplicate.cc +++ b/L1Trigger/TrackFindingTracklet/src/PurgeDuplicate.cc @@ -323,26 +323,29 @@ void PurgeDuplicate::execute(std::vector& outputtracks_, unsigned int iSe // Make the final track objects, fit with KF, and send to output for (unsigned int itrk = 0; itrk < numStublists; itrk++) { - Tracklet* tracklet = inputtracklets_[itrk]; - std::vector trackstublist = inputstublists_[itrk]; - - HybridFit hybridFitter(iSector, settings_, globals_); - hybridFitter.Fit(tracklet, trackstublist); - - // If the track was accepted (and thus fit), add to output - if (tracklet->fit()) { - // Add track to output if it wasn't merged into another - Track* outtrack = tracklet->getTrack(); - outtrack->setSector(iSector); - if (trackInfo[itrk].second == true) - outtrack->setDuplicate(true); - else + bool duplicateTrack = trackInfo[itrk].second; + if (not duplicateTrack) { // Don't waste CPU by calling KF for duplicates + + Tracklet* tracklet = inputtracklets_[itrk]; + std::vector trackstublist = inputstublists_[itrk]; + + // Run KF track fit + HybridFit hybridFitter(iSector, settings_, globals_); + hybridFitter.Fit(tracklet, trackstublist); + + // If the track was accepted (and thus fit), add to output + if (tracklet->fit()) { + // Add fitted Track to output (later converted to TTTrack) + Track* outtrack = tracklet->getTrack(); + outtrack->setSector(iSector); + // Also store fitted track as more detailed Tracklet object. outputtracklets_[trackInfo[itrk].first]->addTrack(tracklet); - // Add all tracks to standalone root file output - outtrack->setStubIDpremerge(inputstubidslists_[itrk]); - outtrack->setStubIDprefit(mergedstubidslists_[itrk]); - outputtracks_.push_back(*outtrack); + // Add all tracks to standalone root file output + outtrack->setStubIDpremerge(inputstubidslists_[itrk]); + outtrack->setStubIDprefit(mergedstubidslists_[itrk]); + outputtracks_.push_back(*outtrack); + } } } } @@ -494,7 +497,7 @@ double PurgeDuplicate::getPhiRes(Tracklet* curTracklet, const Stub* curStub) { // Get phi projection of tracklet int seedindex = curTracklet->seedIndex(); // If this stub is a seed stub, set projection=phi, so that res=0 - if ((seedindex == 0 && (Layer == 1 || Layer == 2)) || (seedindex == 1 && (Layer == 2 || abs(Disk) == 0)) || + if ((seedindex == 0 && (Layer == 1 || Layer == 2)) || (seedindex == 1 && (Layer == 2 || Layer == 3)) || (seedindex == 2 && (Layer == 3 || Layer == 4)) || (seedindex == 3 && (Layer == 5 || Layer == 6)) || (seedindex == 4 && (abs(Disk) == 1 || abs(Disk) == 2)) || (seedindex == 5 && (abs(Disk) == 3 || abs(Disk) == 4)) || (seedindex == 6 && (Layer == 1 || abs(Disk) == 1)) || diff --git a/L1Trigger/TrackFindingTracklet/src/SLHCEvent.cc b/L1Trigger/TrackFindingTracklet/src/SLHCEvent.cc index 4ea8f49d3f953..1c0e0f1e9427b 100644 --- a/L1Trigger/TrackFindingTracklet/src/SLHCEvent.cc +++ b/L1Trigger/TrackFindingTracklet/src/SLHCEvent.cc @@ -16,13 +16,32 @@ bool SLHCEvent::addStub(string DTClink, string stubword, int isPSmodule, int isFlipped, + bool tiltedBarrel, + unsigned int tiltedRingId, + unsigned int endcapRingId, + unsigned int detId, double x, double y, double z, double bend, double strip, vector tps) { - L1TStub stub(DTClink, region, layerdisk, stubword, isPSmodule, isFlipped, x, y, z, bend, strip, tps); + L1TStub stub(DTClink, + region, + layerdisk, + stubword, + isPSmodule, + isFlipped, + tiltedBarrel, + tiltedRingId, + endcapRingId, + detId, + x, + y, + z, + bend, + strip, + tps); stubs_.push_back(stub); return true; @@ -92,13 +111,34 @@ SLHCEvent::SLHCEvent(istream& in) { in >> DTClink >> region >> layerdisk >> stubword >> isPSmodule >> isFlipped >> x >> y >> z >> bend >> strip >> ntps; + // TO FIX: READ THESE FROM INPUT FILE + bool tiltedBarrel = false; + unsigned int tiltedRingId = 999999; + unsigned int endcapRingId = 999999; + unsigned int detId = 999999; // Lower sensor in module + for (unsigned int itps = 0; itps < ntps; itps++) { int tp; in >> tp; tps.push_back(tp); } - L1TStub stub(DTClink, region, layerdisk, stubword, isPSmodule, isFlipped, x, y, z, bend, strip, tps); + L1TStub stub(DTClink, + region, + layerdisk, + stubword, + isPSmodule, + isFlipped, + tiltedBarrel, + tiltedRingId, + endcapRingId, + detId, + x, + y, + z, + bend, + strip, + tps); in >> tmp; diff --git a/L1Trigger/TrackFindingTracklet/src/Sector.cc b/L1Trigger/TrackFindingTracklet/src/Sector.cc index a1f0ade45f3b9..f3cd083cf729b 100644 --- a/L1Trigger/TrackFindingTracklet/src/Sector.cc +++ b/L1Trigger/TrackFindingTracklet/src/Sector.cc @@ -28,6 +28,7 @@ #include "L1Trigger/TrackFindingTracklet/interface/TripletEngine.h" #include "L1Trigger/TrackFindingTracklet/interface/TrackletCalculator.h" #include "L1Trigger/TrackFindingTracklet/interface/TrackletProcessor.h" +#include "L1Trigger/TrackFindingTracklet/interface/TrackletProcessorDisplaced.h" #include "L1Trigger/TrackFindingTracklet/interface/TrackletCalculatorDisplaced.h" #include "L1Trigger/TrackFindingTracklet/interface/ProjectionRouter.h" #include "L1Trigger/TrackFindingTracklet/interface/MatchEngine.h" @@ -35,6 +36,7 @@ #include "L1Trigger/TrackFindingTracklet/interface/MatchProcessor.h" #include "L1Trigger/TrackFindingTracklet/interface/FitTrack.h" #include "L1Trigger/TrackFindingTracklet/interface/PurgeDuplicate.h" +#include "L1Trigger/TrackFindingTracklet/interface/StubStreamData.h" #include "L1Trigger/TrackFindingTracklet/interface/Util.h" #include "FWCore/MessageLogger/interface/MessageLogger.h" @@ -42,6 +44,8 @@ #include "DataFormats/Math/interface/deltaPhi.h" #include "L1Trigger/TrackFindingTracklet/interface/TrackletLUT.h" +#include + using namespace std; using namespace trklet; @@ -93,7 +97,8 @@ bool Sector::addStub(L1TStub stub, string dtc) { nadd++; } - assert(nadd == 1); + if (!(settings_.reduced())) + assert(nadd == 1); return true; } @@ -154,6 +159,8 @@ void Sector::addProc(string procType, string procName) { addProcToVec(TC_, procName, settings_, globals_); } else if (procType == "TrackletProcessor:") { addProcToVec(TP_, procName, settings_, globals_); + } else if (procType == "TrackletProcessorDisplaced:") { + addProcToVec(TPD_, procName, settings_, globals_); } else if (procType == "TrackletCalculatorDisplaced:") { addProcToVec(TCD_, procName, settings_, globals_); } else if (procType == "ProjectionRouter:") { @@ -338,7 +345,7 @@ void Sector::executeVMR() { i->execute(); } for (auto& i : VMRCM_) { - i->execute(); + i->execute(isector_); } } @@ -366,6 +373,12 @@ void Sector::executeTP() { } } +void Sector::executeTPD() { + for (auto& i : TPD_) { + i->execute(isector_, phimin_, phimax_); + } +} + void Sector::executeTC() { for (auto& i : TC_) { i->execute(isector_, phimin_, phimax_); @@ -393,13 +406,13 @@ void Sector::executePR() { void Sector::executeME() { for (auto& i : ME_) { - i->execute(); + i->execute(isector_); } } void Sector::executeMC() { for (auto& i : MC_) { - i->execute(phimin_); + i->execute(isector_, phimin_); } } @@ -409,12 +422,33 @@ void Sector::executeMP() { } } -void Sector::executeFT() { +// Order here reflects Tracklet algo that calls FitTrack before PurgeDuplicates. +// If using Hybrid, then PurgeDuplicates runs both duplicate removal & KF steps. +// (unless duplicate removal disabled, in which case FitTrack runs KF). + +void Sector::executeFT(vector>& streamsTrackRaw, vector>& streamsStubRaw) { + const int numChannels = streamsTrackRaw.size() / N_SECTOR; + const int maxNumProjectionLayers = streamsStubRaw.size() / streamsTrackRaw.size(); + const int offsetTrack = isector_ * numChannels; + int channelTrack(0); + for (auto& i : FT_) { - i->execute(isector_); + // Temporary streams for a single TrackBuilder (i.e. seed type) + deque streamTrackTmp; + vector> streamsStubTmp(maxNumProjectionLayers); + i->execute(streamTrackTmp, streamsStubTmp, isector_); + if (!settings_.storeTrackBuilderOutput()) + continue; + const int offsetStub = (offsetTrack + channelTrack) * maxNumProjectionLayers; + streamsTrackRaw[offsetTrack + channelTrack] = vector(streamTrackTmp.begin(), streamTrackTmp.end()); + channelTrack++; + int channelStub(0); + for (auto& stream : streamsStubTmp) + streamsStubRaw[offsetStub + channelStub++] = vector(stream.begin(), stream.end()); } } +// Returns tracks reconstructed by L1 track chain. void Sector::executePD(std::vector& tracks) { for (auto& i : PD_) { i->execute(tracks, isector_); diff --git a/L1Trigger/TrackFindingTracklet/src/StubPairsMemory.cc b/L1Trigger/TrackFindingTracklet/src/StubPairsMemory.cc index 40d81f17e3147..ea29fe811d0fd 100644 --- a/L1Trigger/TrackFindingTracklet/src/StubPairsMemory.cc +++ b/L1Trigger/TrackFindingTracklet/src/StubPairsMemory.cc @@ -23,10 +23,8 @@ void StubPairsMemory::writeSP(bool first, unsigned int iSector) { for (unsigned int j = 0; j < stubs_.size(); j++) { string stub1index = stubs_[j].first.stub()->stubindex().str(); string stub2index = stubs_[j].second.stub()->stubindex().str(); - out_ << "0x"; - out_ << std::setfill('0') << std::setw(2); - out_ << hex << j << dec; - out_ << " " << stub1index << "|" << stub2index << " " << trklet::hexFormat(stub1index + stub2index) << endl; + out_ << hexstr(j) << " " << stub1index << "|" << stub2index << " " << trklet::hexFormat(stub1index + stub2index) + << endl; } out_.close(); diff --git a/L1Trigger/TrackFindingTracklet/src/StubTripletsMemory.cc b/L1Trigger/TrackFindingTracklet/src/StubTripletsMemory.cc index 73a63404b83c5..5f3307e9d98b7 100644 --- a/L1Trigger/TrackFindingTracklet/src/StubTripletsMemory.cc +++ b/L1Trigger/TrackFindingTracklet/src/StubTripletsMemory.cc @@ -25,9 +25,7 @@ void StubTripletsMemory::writeST(bool first, unsigned int iSector) { string stub1index = stubs1_[j]->stubindex().str(); string stub2index = stubs2_[j]->stubindex().str(); string stub3index = stubs3_[j]->stubindex().str(); - out_ << std::setfill('0') << std::setw(2); - out_ << hex << j << dec; - out_ << " " << stub1index << "|" << stub2index << "|" << stub3index << endl; + out_ << hexstr(j) << " " << stub1index << "|" << stub2index << "|" << stub3index << endl; } out_.close(); diff --git a/L1Trigger/TrackFindingTracklet/src/TrackFitMemory.cc b/L1Trigger/TrackFindingTracklet/src/TrackFitMemory.cc index 55e95adadf29d..85eb0775a5353 100644 --- a/L1Trigger/TrackFindingTracklet/src/TrackFitMemory.cc +++ b/L1Trigger/TrackFindingTracklet/src/TrackFitMemory.cc @@ -26,10 +26,7 @@ void TrackFitMemory::writeTF(bool first, unsigned int iSector) { out_ << "BX = " << (bitset<3>)bx_ << " Event : " << event_ << endl; for (unsigned int j = 0; j < tracks_.size(); j++) { - out_ << "0x"; - out_ << std::setfill('0') << std::setw(2); - out_ << hex << j << dec << " "; - out_ << tracks_[j]->trackfitstr() << " " << trklet::hexFormat(tracks_[j]->trackfitstr()); + out_ << hexstr(j) << " " << tracks_[j]->trackfitstr() << " " << trklet::hexFormat(tracks_[j]->trackfitstr()); out_ << "\n"; } out_.close(); diff --git a/L1Trigger/TrackFindingTracklet/src/Tracklet.cc b/L1Trigger/TrackFindingTracklet/src/Tracklet.cc index 0861aaec04f49..0b271e05d1ad1 100644 --- a/L1Trigger/TrackFindingTracklet/src/Tracklet.cc +++ b/L1Trigger/TrackFindingTracklet/src/Tracklet.cc @@ -735,9 +735,12 @@ std::string Tracklet::trackfitstr() const { return oss; } +// Create a Track object from stubs & digitized track helix params + Track Tracklet::makeTrack(const vector& l1stubs) { assert(fit()); + // Digitized track helix params TrackPars ipars(fpgafitpars_.rinv().value(), fpgafitpars_.phi0().value(), fpgafitpars_.d0().value(), diff --git a/L1Trigger/TrackFindingTracklet/src/TrackletCalculator.cc b/L1Trigger/TrackFindingTracklet/src/TrackletCalculator.cc index 2ad45e30c6717..74e93e2040eb2 100644 --- a/L1Trigger/TrackFindingTracklet/src/TrackletCalculator.cc +++ b/L1Trigger/TrackFindingTracklet/src/TrackletCalculator.cc @@ -42,8 +42,11 @@ TrackletCalculator::TrackletCalculator(string name, Settings const& settings, Gl << "TrackletCalculator::TrackletCalculator phicrit approximation may be invalid! Please check."; } + // reduced config has only one TC, so this must be the first + const bool isFirstTC = (iTC_ == 0 || settings_.reduced()); + // write the drinv and invt inverse tables - if ((settings_.writeInvTable() || settings_.writeHLSInvTable() || settings_.writeTable()) && iTC_ == 0) { + if ((settings_.writeInvTable() || settings_.writeHLSInvTable() || settings_.writeTable()) && isFirstTC) { void (*writeLUT)(const VarInv&, const string&) = nullptr; if (settings.writeInvTable()) { // Verilog version writeLUT = [](const VarInv& x, const string& basename) -> void { @@ -61,7 +64,7 @@ TrackletCalculator::TrackletCalculator(string name, Settings const& settings, Gl // write the firmware design for the calculation of the tracklet parameters // and projections - if ((settings_.writeVerilog() || settings_.writeHLS()) && iTC_ == 0) { + if ((settings_.writeVerilog() || settings_.writeHLS()) && isFirstTC) { void (*writeDesign)(const vector&, const string&) = nullptr; if (settings.writeVerilog()) { // Verilog version writeDesign = [](const vector& v, const string& basename) -> void { diff --git a/L1Trigger/TrackFindingTracklet/src/TrackletCalculatorBase.cc b/L1Trigger/TrackFindingTracklet/src/TrackletCalculatorBase.cc index 433993eb89eb6..bf05456826184 100644 --- a/L1Trigger/TrackFindingTracklet/src/TrackletCalculatorBase.cc +++ b/L1Trigger/TrackFindingTracklet/src/TrackletCalculatorBase.cc @@ -630,7 +630,7 @@ bool TrackletCalculatorBase::barrelSeeding(const Stub* innerFPGAStub, continue; if (irprojdisk[i] < settings_.rmindisk() / ITC->rD_0_final.K() || - irprojdisk[i] > settings_.rmaxdisk() / ITC->rD_0_final.K()) + irprojdisk[i] >= settings_.rmaxdisk() / ITC->rD_0_final.K()) continue; projs[i + N_LAYER].init(settings_, @@ -1023,7 +1023,7 @@ bool TrackletCalculatorBase::diskSeeding(const Stub* innerFPGAStub, continue; //check that r projection in range - if (irprojdisk[i] <= 0 || irprojdisk[i] > settings_.rmaxdisk() / ITC->rD_0_final.K()) + if (irprojdisk[i] <= 0 || irprojdisk[i] >= settings_.rmaxdisk() / ITC->rD_0_final.K()) continue; projs[settings_.projdisks(iSeed_, i) + N_LAYER - 1].init(settings_, @@ -1384,7 +1384,7 @@ bool TrackletCalculatorBase::overlapSeeding(const Stub* innerFPGAStub, continue; //check that r projection in range - if (irprojdisk[i] <= 0 || irprojdisk[i] > settings_.rmaxdisk() / ITC->rD_0_final.K()) + if (irprojdisk[i] <= 0 || irprojdisk[i] >= settings_.rmaxdisk() / ITC->rD_0_final.K()) continue; projs[N_LAYER + i + 1].init(settings_, diff --git a/L1Trigger/TrackFindingTracklet/src/TrackletCalculatorDisplaced.cc b/L1Trigger/TrackFindingTracklet/src/TrackletCalculatorDisplaced.cc index 56fd768ef6163..b7a45459c64d6 100644 --- a/L1Trigger/TrackFindingTracklet/src/TrackletCalculatorDisplaced.cc +++ b/L1Trigger/TrackFindingTracklet/src/TrackletCalculatorDisplaced.cc @@ -591,8 +591,8 @@ bool TrackletCalculatorDisplaced::LLLSeeding(const Stub* innerFPGAStub, return false; } - double phicritapprox = phi0approx - asin(0.5 * settings_.rcrit() * rinvapprox); - int phicrit = iphi0 - 2 * irinv; + double phicritapprox = phi0approx - asin((0.5 * settings_.rcrit() * rinvapprox) + (d0approx / settings_.rcrit())); + int phicrit = iphi0 - 2 * irinv - 2 * id0; int iphicritmincut = settings_.phicritminmc() / globals_->ITC_L1L2()->phi0_final.K(); int iphicritmaxcut = settings_.phicritmaxmc() / globals_->ITC_L1L2()->phi0_final.K(); @@ -691,7 +691,7 @@ bool TrackletCalculatorDisplaced::LLLSeeding(const Stub* innerFPGAStub, continue; //check r projection in range - if (rprojdiskapprox[i] < settings_.rmindisk() || rprojdiskapprox[i] > settings_.rmaxdisk()) + if (rprojdiskapprox[i] < settings_.rmindisk() || rprojdiskapprox[i] >= settings_.rmaxdisk()) continue; projs[N_LAYER + i].init(settings_, @@ -1006,8 +1006,8 @@ bool TrackletCalculatorDisplaced::DDLSeeding(const Stub* innerFPGAStub, if (!success) return false; - double phicritapprox = phi0approx - asin(0.5 * settings_.rcrit() * rinvapprox); - int phicrit = iphi0 - 2 * irinv; + double phicritapprox = phi0approx - asin((0.5 * settings_.rcrit() * rinvapprox) + (d0approx / settings_.rcrit())); + int phicrit = iphi0 - 2 * irinv - 2 * id0; int iphicritmincut = settings_.phicritminmc() / globals_->ITC_L1L2()->phi0_final.K(); int iphicritmaxcut = settings_.phicritmaxmc() / globals_->ITC_L1L2()->phi0_final.K(); @@ -1097,7 +1097,7 @@ bool TrackletCalculatorDisplaced::DDLSeeding(const Stub* innerFPGAStub, if (iphiprojdisk[i] >= (1 << settings_.nphibitsstub(0)) - 1) continue; - if (irprojdisk[i] < settings_.rmindisk() / krprojdisk || irprojdisk[i] > settings_.rmaxdisk() / krprojdisk) + if (irprojdisk[i] < settings_.rmindisk() / krprojdisk || irprojdisk[i] >= settings_.rmaxdisk() / krprojdisk) continue; projs[N_LAYER + i + 2].init(settings_, @@ -1402,8 +1402,8 @@ bool TrackletCalculatorDisplaced::LLDSeeding(const Stub* innerFPGAStub, if (!success) return false; - double phicritapprox = phi0approx - asin(0.5 * settings_.rcrit() * rinvapprox); - int phicrit = iphi0 - 2 * irinv; + double phicritapprox = phi0approx - asin((0.5 * settings_.rcrit() * rinvapprox) + (d0approx / settings_.rcrit())); + int phicrit = iphi0 - 2 * irinv - 2 * id0; int iphicritmincut = settings_.phicritminmc() / globals_->ITC_L1L2()->phi0_final.K(); int iphicritmaxcut = settings_.phicritmaxmc() / globals_->ITC_L1L2()->phi0_final.K(); @@ -1494,7 +1494,7 @@ bool TrackletCalculatorDisplaced::LLDSeeding(const Stub* innerFPGAStub, continue; //Check r range of projection - if (irprojdisk[i] < settings_.rmindisk() / krprojdisk || irprojdisk[i] > settings_.rmaxdisk() / krprojdisk) + if (irprojdisk[i] < settings_.rmindisk() / krprojdisk || irprojdisk[i] >= settings_.rmaxdisk() / krprojdisk) continue; projs[N_LAYER + i + 1].init(settings_, @@ -1826,7 +1826,7 @@ void TrackletCalculatorDisplaced::approxprojdisk(double halfRinv, // double C_0 = -d0_0 * halfRinv_0; phiproj = phi0 - A + B * (1 + C - 2 * A_0 * A_0) + sixth * pow(-A_0 + B_0, 3); - phiprojder = -halfRinv / t - d0 * t * t * zmeanInv * zmeanInv; + phiprojder = -halfRinv / t + d0 * t * zmeanInv * zmeanInv; phiproj = angle0to2pi::make0To2pi(phiproj); diff --git a/L1Trigger/TrackFindingTracklet/src/TrackletConfigBuilder.cc b/L1Trigger/TrackFindingTracklet/src/TrackletConfigBuilder.cc index 2e9d4123eddeb..0bef9768a887b 100644 --- a/L1Trigger/TrackFindingTracklet/src/TrackletConfigBuilder.cc +++ b/L1Trigger/TrackFindingTracklet/src/TrackletConfigBuilder.cc @@ -4,16 +4,22 @@ #include #include #include +#include #include #include +#include #include "L1Trigger/TrackFindingTracklet/interface/TrackletConfigBuilder.h" #include "L1Trigger/TrackFindingTracklet/interface/Settings.h" +#ifdef CMSSW_GIT_HASH +#include "L1Trigger/TrackFindingTracklet/interface/Util.h" +#include "L1Trigger/TrackTrigger/interface/Setup.h" +#endif using namespace std; using namespace trklet; -TrackletConfigBuilder::TrackletConfigBuilder(const Settings& settings) : settings_(settings) { +TrackletConfigBuilder::TrackletConfigBuilder(const Settings& settings, const tt::Setup* setup) : settings_(settings) { NSector_ = N_SECTOR; rcrit_ = settings.rcrit(); @@ -53,18 +59,146 @@ TrackletConfigBuilder::TrackletConfigBuilder(const Settings& settings) : setting buildTC(); buildProjections(); + + setDTCphirange(setup); + + if (settings_.writeConfig()) { + static std::once_flag runOnce; // Only one thread should call this. + std::call_once(runOnce, &TrackletConfigBuilder::writeDTCphirange, this); + } } +//--- Calculate phi range of modules read by each DTC. + +#ifdef CMSSW_GIT_HASH + +void TrackletConfigBuilder::setDTCphirange(const tt::Setup* setup) { + list vecDTCinfo_unsorted; + + // Loop over DTCs in this tracker nonant. + unsigned int numDTCsPerSector = setup->numDTCsPerRegion(); + for (unsigned int dtcId = 0; dtcId < numDTCsPerSector; dtcId++) { + typedef std::pair PhiRange; + std::map dtcPhiRange; + + // Loop over all tracker nonants, taking worst case not all identical. + for (unsigned int iSector = 0; iSector < N_SECTOR; iSector++) { + unsigned int dtcId_regI = iSector * numDTCsPerSector + dtcId; + const std::vector& dtcModules = setup->dtcModules(dtcId_regI); + for (const tt::SensorModule* sm : dtcModules) { + // Convert layer number to Hybrid convention. + int layer = sm->layerId(); // Barrel = 1-6, Endcap = 11-15; + if (sm->barrel()) { + layer--; // Barrel 0-5 + } else { + const int endcapOffsetHybrid = 5; + layer -= endcapOffsetHybrid; // Layer 6-19 + } + // Inner radius of module. + float r = sm->r() - 0.5 * sm->numColumns() * sm->pitchCol() * fabs(sm->sinTilt()); + // phi with respect to tracker nonant centre. + float phiMin = sm->phi() - 0.5 * sm->numRows() * sm->pitchRow() / r; + float phiMax = sm->phi() + 0.5 * sm->numRows() * sm->pitchRow() / r; + // Hybrid measures phi w.r.t. lower edge of tracker nonant. + const float phiOffsetHybrid = 0.5 * dphisectorHG_; + phiMin += phiOffsetHybrid; + phiMax += phiOffsetHybrid; + if (dtcPhiRange.find(layer) == dtcPhiRange.end()) { + dtcPhiRange[layer] = {phiMin, phiMax}; + } else { + dtcPhiRange.at(layer).first = std::min(phiMin, dtcPhiRange.at(layer).first); + dtcPhiRange.at(layer).second = std::max(phiMax, dtcPhiRange.at(layer).second); + } + } + } + for (const auto& p : dtcPhiRange) { + const unsigned int numSlots = setup->numATCASlots(); + std::string dtcName = settings_.slotToDTCname(dtcId % numSlots); + if (dtcId >= numSlots) + dtcName = "neg" + dtcName; + DTCinfo info; + info.name = dtcName; + info.layer = p.first; + info.phimin = p.second.first; + info.phimax = p.second.second; + vecDTCinfo_unsorted.push_back(info); + } + } + + // Put DTCinfo vector in traditional order (PS first). (Needed?) + for (const DTCinfo& info : vecDTCinfo_unsorted) { + string dtcname = info.name; + if (dtcname.find("PS") != std::string::npos) { + vecDTCinfo_.push_back(info); + } + } + for (const DTCinfo& info : vecDTCinfo_unsorted) { + string dtcname = info.name; + if (dtcname.find("PS") == std::string::npos) { + vecDTCinfo_.push_back(info); + } + } +} + +//--- Write DTC phi ranges to file to support stand-alone emulation. +//--- (Only needed to support stand-alone emulation) + +void TrackletConfigBuilder::writeDTCphirange() const { + bool first = true; + for (const DTCinfo& info : vecDTCinfo_) { + string dirName = settings_.tablePath(); + string fileName = dirName + "../dtcphirange.dat"; + std::ofstream out; + openfile(out, first, dirName, fileName, __FILE__, __LINE__); + if (first) { + out << "// layer & phi ranges of modules read by each DTC" << endl; + out << "// (Used by stand-alone emulation)" << endl; + } + out << info.name << " " << info.layer << " " << info.phimin << " " << info.phimax << endl; + out.close(); + first = false; + } +} + +#else + +//--- Set DTC phi ranges from .txt file (stand-alone operation only) + +void TrackletConfigBuilder::setDTCphirange(const tt::Setup* setup) { + // This file previously written by writeDTCphirange(). + const string fname = "../data/dtcphirange.txt"; + if (vecDTCinfo_.empty()) { // Only run once per thread. + std::ifstream str_dtc; + str_dtc.open(fname); + assert(str_dtc.good()); + string line; + while (ifstream, getline(line)) { + std::istringstream iss(line); + DTCinfo info; + iss >> info.name >> info.layer >> info.phimin >> info.phimax; + vecDTCinfo_.push_back(info); + } + str_dtc.close(); + } +} + +#endif + +//--- Helper fcn. to get the layers/disks for a seed + std::pair TrackletConfigBuilder::seedLayers(unsigned int iSeed) { return std::pair(settings_.seedlayers(0, iSeed), settings_.seedlayers(1, iSeed)); } +//--- Method to initialize the regions and VM in each layer + void TrackletConfigBuilder::initGeom() { for (unsigned int ilayer = 0; ilayer < N_LAYER + N_DISK; ilayer++) { double dphi = dphisectorHG_ / NRegions_[ilayer]; for (unsigned int iReg = 0; iReg < NRegions_[ilayer]; iReg++) { std::vector > emptyVec; projections_[ilayer].push_back(emptyVec); + // FIX: sector doesn't have hourglass shape double phimin = dphi * iReg; double phimax = phimin + dphi; std::pair tmp(phimin, phimax); @@ -100,6 +234,8 @@ void TrackletConfigBuilder::initGeom() { } } +//--- Helper fcn to get the radii of the two layers in a seed + std::pair TrackletConfigBuilder::seedRadii(unsigned int iseed) { std::pair seedlayers = seedLayers(iseed); @@ -112,7 +248,7 @@ std::pair TrackletConfigBuilder::seedRadii(unsigned int iseed) { r1 = rmean_[l1]; r2 = rmean_[l2]; } else if (iseed < 6) { //disk seeding - r1 = rmean_[0] + 40.0; //Somwwhat of a hack - but allows finding all the regions + r1 = rmean_[0] + 40.0; //FIX: Somewhat of a hack - but allows finding all the regions //when projecting to L1 r2 = r1 * zmean_[l2 - 6] / zmean_[l1 - 6]; } else { //overlap seeding @@ -123,6 +259,8 @@ std::pair TrackletConfigBuilder::seedRadii(unsigned int iseed) { return std::pair(r1, r2); } +//--- Helper function to determine if a pair of VM memories form valid TE + bool TrackletConfigBuilder::validTEPair(unsigned int iseed, unsigned int iTE1, unsigned int iTE2) { double rinvmin = 999.9; double rinvmax = -999.9; @@ -150,12 +288,15 @@ bool TrackletConfigBuilder::validTEPair(unsigned int iseed, unsigned int iTE1, u return true; } +//--- Builds the list of TE for each seeding combination + void TrackletConfigBuilder::buildTE() { for (unsigned int iseed = 0; iseed < N_SEED_PROMPT; iseed++) { for (unsigned int i1 = 0; i1 < VMStubsTE_[iseed].first.size(); i1++) { for (unsigned int i2 = 0; i2 < VMStubsTE_[iseed].second.size(); i2++) { if (validTEPair(iseed, i1, i2)) { std::pair tmp(i1, i2); + // Contains pairs of indices of all valid VM pairs in seeding layers TE_[iseed].push_back(tmp); } } @@ -163,6 +304,8 @@ void TrackletConfigBuilder::buildTE() { } } +//--- Builds the lists of TC for each seeding combination + void TrackletConfigBuilder::buildTC() { for (unsigned int iSeed = 0; iSeed < N_SEED_PROMPT; iSeed++) { unsigned int nTC = NTC_[iSeed]; @@ -187,6 +330,8 @@ void TrackletConfigBuilder::buildTC() { } } +//--- Helper fcn to return the phi range of a projection of a tracklet from a TC + std::pair TrackletConfigBuilder::seedPhiRange(double rproj, unsigned int iSeed, unsigned int iTC) { std::vector >& TCs = TC_[iSeed]; @@ -213,7 +358,36 @@ std::pair TrackletConfigBuilder::seedPhiRange(double rproj, unsi return std::pair(phimin, phimax); } +//--- Finds the projections needed for each seeding combination + void TrackletConfigBuilder::buildProjections() { + set emptyProjStandard = { + "TPROJ_L1L2H_L3PHIB", "TPROJ_L1L2E_L3PHIC", "TPROJ_L1L2K_L3PHIC", "TPROJ_L1L2H_L3PHID", "TPROJ_L1L2F_L5PHIA", + "TPROJ_L1L2G_L5PHID", "TPROJ_L1L2A_L6PHIA", "TPROJ_L1L2J_L6PHIB", "TPROJ_L1L2C_L6PHIC", "TPROJ_L1L2L_L6PHID", + "TPROJ_L3L4D_D1PHIB", "TPROJ_L2L3A_D1PHIC", "TPROJ_L3L4A_D1PHIC", "TPROJ_L1L2G_D2PHIA", "TPROJ_L1D1D_D2PHIA", + "TPROJ_L1D1E_D2PHIA", "TPROJ_L1L2J_D2PHIB", "TPROJ_L3L4D_D2PHIB", "TPROJ_L1D1A_D2PHIB", "TPROJ_L1D1F_D2PHIB", + "TPROJ_L1D1G_D2PHIB", "TPROJ_L1L2C_D2PHIC", "TPROJ_L2L3A_D2PHIC", "TPROJ_L3L4A_D2PHIC", "TPROJ_L1D1B_D2PHIC", + "TPROJ_L1D1C_D2PHIC", "TPROJ_L1D1H_D2PHIC", "TPROJ_L2D1A_D2PHIC", "TPROJ_L1L2F_D2PHID", "TPROJ_L1D1D_D2PHID", + "TPROJ_L1D1E_D2PHID", "TPROJ_L1L2G_D3PHIA", "TPROJ_L1D1D_D3PHIA", "TPROJ_L1D1E_D3PHIA", "TPROJ_L1L2J_D3PHIB", + "TPROJ_L1D1A_D3PHIB", "TPROJ_L1D1F_D3PHIB", "TPROJ_L1D1G_D3PHIB", "TPROJ_L1L2C_D3PHIC", "TPROJ_L2L3A_D3PHIC", + "TPROJ_L1D1B_D3PHIC", "TPROJ_L1D1C_D3PHIC", "TPROJ_L1D1H_D3PHIC", "TPROJ_L2D1A_D3PHIC", "TPROJ_L1L2F_D3PHID", + "TPROJ_L1D1D_D3PHID", "TPROJ_L1D1E_D3PHID", "TPROJ_L1L2G_D4PHIA", "TPROJ_L1D1D_D4PHIA", "TPROJ_L1D1E_D4PHIA", + "TPROJ_L1L2J_D4PHIB", "TPROJ_L1D1G_D4PHIB", "TPROJ_L1L2C_D4PHIC", "TPROJ_L2L3A_D4PHIC", "TPROJ_L1D1B_D4PHIC", + "TPROJ_L2D1A_D4PHIC", "TPROJ_L1L2F_D4PHID", "TPROJ_L1D1D_D4PHID", "TPROJ_L1D1E_D5PHIA", "TPROJ_L1D1G_D5PHIB", + "TPROJ_L1D1B_D5PHIC", "TPROJ_L1D1D_D5PHID"}; + + set emptyProjCombined = { + "TPROJ_L1L2J_L6PHIB", "TPROJ_L1L2C_L6PHIC", "TPROJ_L1L2G_D1PHIA", "TPROJ_L1L2J_D1PHIB", "TPROJ_L2L3D_D1PHIB", + "TPROJ_L3L4D_D1PHIB", "TPROJ_L1L2C_D1PHIC", "TPROJ_L2L3A_D1PHIC", "TPROJ_L3L4A_D1PHIC", "TPROJ_L1L2F_D1PHID", + "TPROJ_L1L2G_D2PHIA", "TPROJ_L1D1E_D2PHIA", "TPROJ_L1L2J_D2PHIB", "TPROJ_L2L3D_D2PHIB", "TPROJ_L3L4D_D2PHIB", + "TPROJ_L1D1G_D2PHIB", "TPROJ_L1L2C_D2PHIC", "TPROJ_L2L3A_D2PHIC", "TPROJ_L3L4A_D2PHIC", "TPROJ_L1D1B_D2PHIC", + "TPROJ_L2D1A_D2PHIC", "TPROJ_L1L2F_D2PHID", "TPROJ_L1D1D_D2PHID", "TPROJ_L1L2G_D3PHIA", "TPROJ_L1D1E_D3PHIA", + "TPROJ_L1L2J_D3PHIB", "TPROJ_L2L3D_D3PHIB", "TPROJ_L1D1G_D3PHIB", "TPROJ_L1L2C_D3PHIC", "TPROJ_L2L3A_D3PHIC", + "TPROJ_L1D1B_D3PHIC", "TPROJ_L2D1A_D3PHIC", "TPROJ_L1L2F_D3PHID", "TPROJ_L1D1D_D3PHID", "TPROJ_L1L2G_D4PHIA", + "TPROJ_L1D1E_D4PHIA", "TPROJ_L1L2J_D4PHIB", "TPROJ_L2L3D_D4PHIB", "TPROJ_L1D1G_D4PHIB", "TPROJ_L1L2C_D4PHIC", + "TPROJ_L2L3A_D4PHIC", "TPROJ_L1D1B_D4PHIC", "TPROJ_L2D1A_D4PHIC", "TPROJ_L1L2F_D4PHID", "TPROJ_L1D1D_D4PHID", + "TPROJ_L1D1E_D5PHIA", "TPROJ_L1D1G_D5PHIB", "TPROJ_L1D1B_D5PHIC", "TPROJ_L1D1D_D5PHID"}; + for (unsigned int iseed = 0; iseed < N_SEED_PROMPT; iseed++) { std::vector >& TCs = TC_[iseed]; @@ -228,7 +402,16 @@ void TrackletConfigBuilder::buildProjections() { std::pair phiRange = seedPhiRange(rproj, iseed, iTC); if (phiRange.first < allStubs_[ilayer][iReg].second && phiRange.second > allStubs_[ilayer][iReg].first) { std::pair tmp(iseed, iTC); //seedindex and TC - projections_[ilayer][iReg].push_back(tmp); + string projName = TPROJName(iseed, iTC, ilayer, iReg); + if (combinedmodules_) { + if (emptyProjCombined.find(projName) == emptyProjCombined.end()) { + projections_[ilayer][iReg].push_back(tmp); + } + } else { + if (emptyProjStandard.find(projName) == emptyProjStandard.end()) { + projections_[ilayer][iReg].push_back(tmp); + } + } } } } @@ -236,6 +419,9 @@ void TrackletConfigBuilder::buildProjections() { } } +//--- Helper function to calculate the phi position of a seed at radius r that is formed +//--- by two stubs at (r1,phi1) and (r2, phi2) + double TrackletConfigBuilder::phi(double r1, double phi1, double r2, double phi2, double r) { double rhoinv = rinv(r1, phi1, r2, phi2); if (std::abs(rhoinv) > rinvmax_) { @@ -244,12 +430,14 @@ double TrackletConfigBuilder::phi(double r1, double phi1, double r2, double phi2 return phi1 + asin(0.5 * r * rhoinv) - asin(0.5 * r1 * rhoinv); } +//--- Helper function to calculate rinv for two stubs at (r1,phi1) and (r2,phi2) + double TrackletConfigBuilder::rinv(double r1, double phi1, double r2, double phi2) { double deltaphi = phi1 - phi2; return 2 * sin(deltaphi) / sqrt(r2 * r2 + r1 * r1 - 2 * r1 * r2 * cos(deltaphi)); } -std::string TrackletConfigBuilder::iSeedStr(unsigned int iSeed) { +std::string TrackletConfigBuilder::iSeedStr(unsigned int iSeed) const { static std::string name[8] = {"L1L2", "L2L3", "L3L4", "L5L6", "D1D2", "D3D4", "L1D1", "L2D1"}; assert(iSeed < 8); @@ -264,14 +452,14 @@ std::string TrackletConfigBuilder::numStr(unsigned int i) { return num[i]; } -std::string TrackletConfigBuilder::iTCStr(unsigned int iTC) { +std::string TrackletConfigBuilder::iTCStr(unsigned int iTC) const { static std::string name[12] = {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L"}; assert(iTC < 12); return name[iTC]; } -std::string TrackletConfigBuilder::iRegStr(unsigned int iReg, unsigned int iSeed) { +std::string TrackletConfigBuilder::iRegStr(unsigned int iReg, unsigned int iSeed) const { static std::string name[8] = {"A", "B", "C", "D", "E", "F", "G", "H"}; static std::string nameOverlap[8] = {"X", "Y", "Z", "W", "Q", "R", "S", "T"}; @@ -290,7 +478,7 @@ std::string TrackletConfigBuilder::iRegStr(unsigned int iReg, unsigned int iSeed return name[iReg]; } -std::string TrackletConfigBuilder::TCName(unsigned int iSeed, unsigned int iTC) { +std::string TrackletConfigBuilder::TCName(unsigned int iSeed, unsigned int iTC) const { if (combinedmodules_) { return "TP_" + iSeedStr(iSeed) + iTCStr(iTC); } else { @@ -305,11 +493,11 @@ std::string TrackletConfigBuilder::LayerName(unsigned int ilayer) { std::string TrackletConfigBuilder::TPROJName(unsigned int iSeed, unsigned int iTC, unsigned int ilayer, - unsigned int ireg) { + unsigned int ireg) const { return "TPROJ_" + iSeedStr(iSeed) + iTCStr(iTC) + "_" + LayerName(ilayer) + "PHI" + iTCStr(ireg); } -std::string TrackletConfigBuilder::PRName(unsigned int ilayer, unsigned int ireg) { +std::string TrackletConfigBuilder::PRName(unsigned int ilayer, unsigned int ireg) const { if (combinedmodules_) { return "MP_" + LayerName(ilayer) + "PHI" + iTCStr(ireg); } else { @@ -318,6 +506,11 @@ std::string TrackletConfigBuilder::PRName(unsigned int ilayer, unsigned int ireg } void TrackletConfigBuilder::writeProjectionMemories(std::ostream& os, std::ostream& memories, std::ostream&) { + // Each TC (e.g. TC_L1L2D) writes a projection memory (TPROJ) for each layer the seed projects to, + // with name indicating the TC and which layer & phi region it projects to (e.g. TPROJ_L1L2D_L3PHIA). + // + // Each PR (e.g. PR_L3PHIA) reads all TPROJ memories for the given layer & phi region. + for (unsigned int ilayer = 0; ilayer < N_LAYER + N_DISK; ilayer++) { for (unsigned int ireg = 0; ireg < projections_[ilayer].size(); ireg++) { for (unsigned int imem = 0; imem < projections_[ilayer][ireg].size(); imem++) { @@ -340,7 +533,7 @@ std::string TrackletConfigBuilder::SPName(unsigned int l1, unsigned int l2, unsigned int ireg2, unsigned int ivm2, - unsigned int iseed) { + unsigned int iseed) const { return "SP_" + LayerName(l1) + "PHI" + iRegStr(ireg1, iseed) + numStr(ivm1) + "_" + LayerName(l2) + "PHI" + iRegStr(ireg2, iseed) + numStr(ivm2); } @@ -354,7 +547,7 @@ std::string TrackletConfigBuilder::SPDName(unsigned int l1, unsigned int l3, unsigned int ireg3, unsigned int ivm3, - unsigned int iseed) { + unsigned int iseed) const { return "SPD_" + LayerName(l1) + "PHI" + iRegStr(ireg1, iseed) + numStr(ivm1) + "_" + LayerName(l2) + "PHI" + iRegStr(ireg2, iseed) + numStr(ivm2) + "_" + LayerName(l3) + "PHI" + iRegStr(ireg3, iseed) + numStr(ivm3); } @@ -365,7 +558,7 @@ std::string TrackletConfigBuilder::TEName(unsigned int l1, unsigned int l2, unsigned int ireg2, unsigned int ivm2, - unsigned int iseed) { + unsigned int iseed) const { return "TE_" + LayerName(l1) + "PHI" + iRegStr(ireg1, iseed) + numStr(ivm1) + "_" + LayerName(l2) + "PHI" + iRegStr(ireg2, iseed) + numStr(ivm2); } @@ -376,31 +569,39 @@ std::string TrackletConfigBuilder::TEDName(unsigned int l1, unsigned int l2, unsigned int ireg2, unsigned int ivm2, - unsigned int iseed) { + unsigned int iseed) const { return "TED_" + LayerName(l1) + "PHI" + iRegStr(ireg1, iseed) + numStr(ivm1) + "_" + LayerName(l2) + "PHI" + iRegStr(ireg2, iseed) + numStr(ivm2); } -std::string TrackletConfigBuilder::TParName(unsigned int l1, unsigned int l2, unsigned int l3, unsigned int itc) { +std::string TrackletConfigBuilder::TParName(unsigned int l1, unsigned int l2, unsigned int l3, unsigned int itc) const { return "TPAR_" + LayerName(l1) + LayerName(l2) + LayerName(l3) + iTCStr(itc); } -std::string TrackletConfigBuilder::TCDName(unsigned int l1, unsigned int l2, unsigned int l3, unsigned int itc) { +std::string TrackletConfigBuilder::TCDName(unsigned int l1, unsigned int l2, unsigned int l3, unsigned int itc) const { return "TCD_" + LayerName(l1) + LayerName(l2) + LayerName(l3) + iTCStr(itc); } -std::string TrackletConfigBuilder::TPROJName( - unsigned int l1, unsigned int l2, unsigned int l3, unsigned int itc, unsigned int projlayer, unsigned int projreg) { +std::string TrackletConfigBuilder::TPROJName(unsigned int l1, + unsigned int l2, + unsigned int l3, + unsigned int itc, + unsigned int projlayer, + unsigned int projreg) const { return "TPROJ_" + LayerName(l1) + LayerName(l2) + LayerName(l3) + iTCStr(itc) + "_" + LayerName(projlayer) + "PHI" + iTCStr(projreg); } -std::string TrackletConfigBuilder::FTName(unsigned int l1, unsigned int l2, unsigned int l3) { +std::string TrackletConfigBuilder::FTName(unsigned int l1, unsigned int l2, unsigned int l3) const { return "FT_" + LayerName(l1) + LayerName(l2) + LayerName(l3); } -std::string TrackletConfigBuilder::TREName( - unsigned int l1, unsigned int ireg1, unsigned int l2, unsigned int ireg2, unsigned int iseed, unsigned int count) { +std::string TrackletConfigBuilder::TREName(unsigned int l1, + unsigned int ireg1, + unsigned int l2, + unsigned int ireg2, + unsigned int iseed, + unsigned int count) const { return "TRE_" + LayerName(l1) + iRegStr(ireg1, iseed) + LayerName(l2) + iRegStr(ireg2, iseed) + "_" + numStr(count); } @@ -411,16 +612,18 @@ std::string TrackletConfigBuilder::STName(unsigned int l1, unsigned int l3, unsigned int ireg3, unsigned int iseed, - unsigned int count) { + unsigned int count) const { return "ST_" + LayerName(l1) + iRegStr(ireg1, iseed) + LayerName(l2) + iRegStr(ireg2, iseed) + "_" + LayerName(l3) + iRegStr(ireg3, iseed) + "_" + numStr(count); } -std::string TrackletConfigBuilder::TCNAme(unsigned int iseed, unsigned int iTC) { - return "TC_" + iSeedStr(iseed) + iTCStr(iTC); -} - void TrackletConfigBuilder::writeSPMemories(std::ostream& os, std::ostream& memories, std::ostream& modules) { + // Each TE reads one VM in two seed layers, finds stub pairs & writes to a StubPair ("SP") memory. + // + // Each TC reads several StubPair (SP) memories, each containing a pair of VMs of two seeding layers. + // Several TC are created for each layer pair, and the SP distributed between them. + // If TC name is TC_L1L2C, "C" indicates this is the 3rd TC in L1L2. + if (combinedmodules_) return; @@ -443,13 +646,16 @@ void TrackletConfigBuilder::writeSPMemories(std::ostream& os, std::ostream& memo os << SPName(l1, TE1 / NVMTE_[iSeed].first, TE1, l2, TE2 / NVMTE_[iSeed].second, TE2, iSeed) << " input=> " << TEName(l1, TE1 / NVMTE_[iSeed].first, TE1, l2, TE2 / NVMTE_[iSeed].second, TE2, iSeed) - << ".stubpairout output=> " << TCNAme(iSeed, iTC) << ".stubpairin" << std::endl; + << ".stubpairout output=> " << TCName(iSeed, iTC) << ".stubpairin" << std::endl; } } } } void TrackletConfigBuilder::writeSPDMemories(std::ostream& wires, std::ostream& memories, std::ostream& modules) { + // Similar to writeSPMemories, but for displaced (=extended) tracking, + // with seeds based on triplets of layers. + if (!extended_) return; @@ -586,6 +792,10 @@ void TrackletConfigBuilder::writeSPDMemories(std::ostream& wires, std::ostream& } void TrackletConfigBuilder::writeAPMemories(std::ostream& os, std::ostream& memories, std::ostream& modules) { + // The AllProjection memories (e.g. AP_L2PHIA) contain the intercept point of the projection to + // a layer. Each is written by one PR module of similar name (e.g. PR_L2PHIA), and read by + // a MC (e.g. MC_L2PHIA). + if (combinedmodules_) return; @@ -602,6 +812,12 @@ void TrackletConfigBuilder::writeAPMemories(std::ostream& os, std::ostream& memo } void TrackletConfigBuilder::writeCMMemories(std::ostream& os, std::ostream& memories, std::ostream& modules) { + // The CandidateMatch memory (e.g. CM_L1PHIA1) are each written by ME module of similar name + // (e.g. ME_L1PHIA1) and contain indices of matching (tracklet projections,stubs) in the specified + // VM region. + // All CM memories in a given phi region (e.g. L1PHIA) are read by a MC module (e.g. MC_L1PHIA) that + // does more precise matching. + if (combinedmodules_) return; @@ -620,6 +836,12 @@ void TrackletConfigBuilder::writeCMMemories(std::ostream& os, std::ostream& memo } void TrackletConfigBuilder::writeVMPROJMemories(std::ostream& os, std::ostream& memories, std::ostream&) { + // The VMPROJ memories (e.g. VMPROJ_L2PHIA1) written by a PR module each correspond to projections to + // a single VM region in a layer. Each is filled by the PR using all projections (TPROJ) to this VM + // from different seeding layers. + // + // Each VMPROJ memory is read by a ME module, which matches the projection to stubs. + if (combinedmodules_) return; @@ -637,6 +859,12 @@ void TrackletConfigBuilder::writeVMPROJMemories(std::ostream& os, std::ostream& } void TrackletConfigBuilder::writeFMMemories(std::ostream& os, std::ostream& memories, std::ostream& modules) { + // All FullMatch (e.g. FM_L2L3_L1PHIA) memories corresponding to a matches between stubs & tracklets + // in a given region (e.g. L1PHIA) from all seeding layers, are written by a MC module (e.g. MC_L1PHIA). + // + // All FullMatch memories corresponding to a given seed pair are read by the TrackBuilder (e.g. FT_L1L2), + // which checks if the track has stubs in enough layers. + if (combinedmodules_) { for (unsigned int ilayer = 0; ilayer < N_LAYER + N_DISK; ilayer++) { for (unsigned int iReg = 0; iReg < NRegions_[ilayer]; iReg++) { @@ -671,6 +899,13 @@ void TrackletConfigBuilder::writeFMMemories(std::ostream& os, std::ostream& memo } void TrackletConfigBuilder::writeASMemories(std::ostream& os, std::ostream& memories, std::ostream& modules) { + // Each VMR writes AllStub memories (AS) for a single phi region (e.g. PHIC), + // merging data from all DTCs related to this phi region. It does so by merging data from + // the IL memories written by all IRs for this phi region. The wiring map lists all + // IL memories that feed (">") into a single VMR ("VMR_L1PHIC") that writes to the + // an AS memory ("AS_L1PHIC"). + // Multiple copies of each AS memory exist where several modules in chain want to read it. + if (combinedmodules_) { //First write AS memories used by MatchProcessor for (unsigned int ilayer = 0; ilayer < N_LAYER + N_DISK; ilayer++) { @@ -802,6 +1037,7 @@ void TrackletConfigBuilder::writeASMemories(std::ostream& os, std::ostream& memo } } } + } else { //First write AS memories used by MatchCalculator for (unsigned int ilayer = 0; ilayer < N_LAYER + N_DISK; ilayer++) { @@ -833,10 +1069,11 @@ void TrackletConfigBuilder::writeASMemories(std::ostream& os, std::ostream& memo for (unsigned int iTC = 0; iTC < TC_[iSeed].size(); iTC++) { bool used = false; + // Each TC processes data from several TEs. for (unsigned int iTE = 0; iTE < TC_[iSeed][iTC].size(); iTE++) { unsigned int theTE = TC_[iSeed][iTC][iTE]; - unsigned int TE1 = TE_[iSeed][theTE].first; + unsigned int TE1 = TE_[iSeed][theTE].first; // VM in inner/outer layer of this TE. unsigned int TE2 = TE_[iSeed][theTE].second; if (l1 == ilayer && iReg == TE1 / NVMTE_[iSeed].first) @@ -846,7 +1083,7 @@ void TrackletConfigBuilder::writeASMemories(std::ostream& os, std::ostream& memo } if (used) { - nmem++; + nmem++; // Another copy of memory memories << "AllStubs: AS_" << LayerName(ilayer) << "PHI" << iTCStr(iReg) << "n" << nmem << " [42]" << std::endl; os << "AS_" << LayerName(ilayer) << "PHI" << iTCStr(iReg) << "n" << nmem << " input=> VMR_" @@ -866,6 +1103,12 @@ void TrackletConfigBuilder::writeASMemories(std::ostream& os, std::ostream& memo } void TrackletConfigBuilder::writeVMSMemories(std::ostream& os, std::ostream& memories, std::ostream&) { + // Each VMR writes to Virtual Module memories ("VMS") to be used later by the ME or TE etc. + // Memory VMSTE_L1PHIC9-12 is the memory for small phi region C in L1 for the TE module. + // Numbers 9-12 correspond to the 4 VMs in this phi region. + // + // Each TE reads one VMS memory in each seeding layer. + if (combinedmodules_) { //First write VMS memories used by MatchProcessor for (unsigned int ilayer = 0; ilayer < N_LAYER + N_DISK; ilayer++) { @@ -906,6 +1149,7 @@ void TrackletConfigBuilder::writeVMSMemories(std::ostream& os, std::ostream& mem } } } + } else { //First write VMS memories used by MatchEngine for (unsigned int ilayer = 0; ilayer < N_LAYER + N_DISK; ilayer++) { @@ -920,7 +1164,8 @@ void TrackletConfigBuilder::writeVMSMemories(std::ostream& os, std::ostream& mem } } - //Next write VMS memories used by TrackletEngine + // Next write VMS memories used by TrackletEngine + // Each TE processes one VM region in inner + outer seeding layers, and needs its own copy of input memories. for (unsigned int iSeed = 0; iSeed < N_SEED_PROMPT; iSeed++) { for (unsigned int innerouterseed = 0; innerouterseed < 2; innerouterseed++) { //FIXME - code could be cleaner @@ -930,11 +1175,11 @@ void TrackletConfigBuilder::writeVMSMemories(std::ostream& os, std::ostream& mem unsigned int NVMTE1 = NVMTE_[iSeed].first; unsigned int NVMTE2 = NVMTE_[iSeed].second; - unsigned int ilayer = seedLayers(iSeed).first; - unsigned int NVMTE = NVMTE_[iSeed].first; + unsigned int ilayer = l1; + unsigned int NVMTE = NVMTE1; if (innerouterseed == 1) { - ilayer = seedLayers(iSeed).second; - NVMTE = NVMTE_[iSeed].second; + ilayer = l2; + NVMTE = NVMTE2; } for (unsigned int iVMTE = 0; iVMTE < NVMTE * NRegions_[ilayer]; iVMTE++) { @@ -947,7 +1192,7 @@ void TrackletConfigBuilder::writeVMSMemories(std::ostream& os, std::ostream& mem } for (unsigned int iTE = 0; iTE < TE_[iSeed].size(); iTE++) { - unsigned int TE1 = TE_[iSeed][iTE].first; + unsigned int TE1 = TE_[iSeed][iTE].first; // VM region in inner/outer layer of this TE unsigned int TE2 = TE_[iSeed][iTE].second; bool used = false; @@ -964,7 +1209,7 @@ void TrackletConfigBuilder::writeVMSMemories(std::ostream& os, std::ostream& mem if (innerouterseed == 1) inorout = "O"; - nmem++; + nmem++; // Add another copy of memory. memories << "VMStubsTE: VMSTE_" << LayerName(ilayer) << "PHI" << iRegStr(iReg, iSeed) << iVMTE + 1 << "n" << nmem << " [18]" << std::endl; os << "VMSTE_" << LayerName(ilayer) << "PHI" << iRegStr(iReg, iSeed) << iVMTE + 1 << "n" << nmem @@ -985,6 +1230,9 @@ void TrackletConfigBuilder::writeVMSMemories(std::ostream& os, std::ostream& mem } void TrackletConfigBuilder::writeTPARMemories(std::ostream& os, std::ostream& memories, std::ostream& modules) { + // Each TC module (e.g. TC_L1L2A) stores helix params in a single TPAR memory of similar name + // (e.g. TPAR_L1L2A). The TPAR is subsequently read by the TrackBuilder (FT). + if (combinedmodules_) { for (unsigned int iSeed = 0; iSeed < N_SEED_PROMPT; iSeed++) { for (unsigned int iTP = 0; iTP < TC_[iSeed].size(); iTP++) { @@ -1024,265 +1272,83 @@ void TrackletConfigBuilder::writeCTMemories(std::ostream& os, std::ostream& memo } void TrackletConfigBuilder::writeILMemories(std::ostream& os, std::ostream& memories, std::ostream& modules) { - //FIXME these should not be hardcoded - but for now wanted to avoid reading file - string dtcname[52]; - unsigned int layerdisk[52]; - double phimin[52]; - double phimax[52]; - - dtcname[0] = "PS10G_1"; - layerdisk[0] = 0; - phimin[0] = 0.304273; - phimax[0] = 0.742925; - dtcname[1] = "PS10G_1"; - layerdisk[1] = 6; - phimin[1] = -0.185672; - phimax[1] = 0.883803; - dtcname[2] = "PS10G_1"; - layerdisk[2] = 8; - phimin[2] = -0.132414; - phimax[2] = 0.830545; - dtcname[3] = "PS10G_1"; - layerdisk[3] = 10; - phimin[3] = -0.132414; - phimax[3] = 0.830545; - dtcname[4] = "PS10G_2"; - layerdisk[4] = 0; - phimin[4] = -0.0133719; - phimax[4] = 0.715599; - dtcname[5] = "PS10G_2"; - layerdisk[5] = 7; - phimin[5] = -0.110089; - phimax[5] = 0.808221; - dtcname[6] = "PS10G_2"; - layerdisk[6] = 9; - phimin[6] = -0.132414; - phimax[6] = 0.830545; - dtcname[7] = "PS10G_3"; - layerdisk[7] = 1; - phimin[7] = -0.11381; - phimax[7] = 0.822812; - dtcname[8] = "PS10G_3"; - layerdisk[8] = 7; - phimin[8] = -0.185672; - phimax[8] = 0.883803; - dtcname[9] = "PS10G_4"; - layerdisk[9] = 6; - phimin[9] = -0.0823971; - phimax[9] = 0.780529; - dtcname[10] = "PS10G_4"; - layerdisk[10] = 8; - phimin[10] = -0.0963091; - phimax[10] = 0.794441; - dtcname[11] = "PS10G_4"; - layerdisk[11] = 10; - phimin[11] = -0.0963091; - phimax[11] = 0.794441; - dtcname[12] = "PS_1"; - layerdisk[12] = 2; - phimin[12] = 0.0827748; - phimax[12] = 0.615357; - dtcname[13] = "PS_1"; - layerdisk[13] = 7; - phimin[13] = -0.0823971; - phimax[13] = 0.780529; - dtcname[14] = "PS_2"; - layerdisk[14] = 2; - phimin[14] = -0.0917521; - phimax[14] = 0.614191; - dtcname[15] = "PS_2"; - layerdisk[15] = 9; - phimin[15] = -0.0963091; - phimax[15] = 0.794441; - dtcname[16] = "2S_1"; - layerdisk[16] = 3; - phimin[16] = -0.0246209; - phimax[16] = 0.763311; - dtcname[17] = "2S_1"; - layerdisk[17] = 4; - phimin[17] = 0.261875; - phimax[17] = 0.403311; - dtcname[18] = "2S_2"; - layerdisk[18] = 4; - phimin[18] = -0.0542445; - phimax[18] = 0.715509; - dtcname[19] = "2S_3"; - layerdisk[19] = 5; - phimin[19] = 0.0410126; - phimax[19] = 0.730605; - dtcname[20] = "2S_4"; - layerdisk[20] = 5; - phimin[20] = -0.0428961; - phimax[20] = 0.693862; - dtcname[21] = "2S_4"; - layerdisk[21] = 8; - phimin[21] = -0.0676705; - phimax[21] = 0.765802; - dtcname[22] = "2S_5"; - layerdisk[22] = 6; - phimin[22] = -0.0648206; - phimax[22] = 0.762952; - dtcname[23] = "2S_5"; - layerdisk[23] = 9; - phimin[23] = -0.0676705; - phimax[23] = 0.765802; - dtcname[24] = "2S_6"; - layerdisk[24] = 7; - phimin[24] = -0.0648206; - phimax[24] = 0.762952; - dtcname[25] = "2S_6"; - layerdisk[25] = 10; - phimin[25] = -0.0676705; - phimax[25] = 0.765802; - dtcname[26] = "negPS10G_1"; - layerdisk[26] = 0; - phimin[26] = -0.023281; - phimax[26] = 0.372347; - dtcname[27] = "negPS10G_1"; - layerdisk[27] = 6; - phimin[27] = -0.185672; - phimax[27] = 0.883803; - dtcname[28] = "negPS10G_1"; - layerdisk[28] = 8; - phimin[28] = -0.132414; - phimax[28] = 0.830545; - dtcname[29] = "negPS10G_1"; - layerdisk[29] = 10; - phimin[29] = -0.132414; - phimax[29] = 0.830545; - dtcname[30] = "negPS10G_2"; - layerdisk[30] = 0; - phimin[30] = -0.0133719; - phimax[30] = 0.715599; - dtcname[31] = "negPS10G_2"; - layerdisk[31] = 7; - phimin[31] = -0.110089; - phimax[31] = 0.808221; - dtcname[32] = "negPS10G_2"; - layerdisk[32] = 9; - phimin[32] = -0.132414; - phimax[32] = 0.830545; - dtcname[33] = "negPS10G_3"; - layerdisk[33] = 1; - phimin[33] = -0.115834; - phimax[33] = 0.813823; - dtcname[34] = "negPS10G_3"; - layerdisk[34] = 7; - phimin[34] = -0.185672; - phimax[34] = 0.883803; - dtcname[35] = "negPS10G_4"; - layerdisk[35] = 6; - phimin[35] = -0.0823971; - phimax[35] = 0.780529; - dtcname[36] = "negPS10G_4"; - layerdisk[36] = 8; - phimin[36] = -0.0963091; - phimax[36] = 0.794441; - dtcname[37] = "negPS10G_4"; - layerdisk[37] = 10; - phimin[37] = -0.0963091; - phimax[37] = 0.794441; - dtcname[38] = "negPS_1"; - layerdisk[38] = 2; - phimin[38] = -0.0961318; - phimax[38] = 0.445198; - dtcname[39] = "negPS_1"; - layerdisk[39] = 7; - phimin[39] = -0.0823971; - phimax[39] = 0.780529; - dtcname[40] = "negPS_2"; - layerdisk[40] = 2; - phimin[40] = -0.0917521; - phimax[40] = 0.614191; - dtcname[41] = "negPS_2"; - layerdisk[41] = 9; - phimin[41] = -0.0963091; - phimax[41] = 0.794441; - dtcname[42] = "neg2S_1"; - layerdisk[42] = 3; - phimin[42] = -0.0246209; - phimax[42] = 0.763311; - dtcname[43] = "neg2S_1"; - layerdisk[43] = 4; - phimin[43] = 0.261875; - phimax[43] = 0.403311; - dtcname[44] = "neg2S_2"; - layerdisk[44] = 4; - phimin[44] = -0.0542445; - phimax[44] = 0.715509; - dtcname[45] = "neg2S_3"; - layerdisk[45] = 5; - phimin[45] = 0.0410126; - phimax[45] = 0.730605; - dtcname[46] = "neg2S_4"; - layerdisk[46] = 5; - phimin[46] = -0.0428961; - phimax[46] = 0.693862; - dtcname[47] = "neg2S_4"; - layerdisk[47] = 8; - phimin[47] = -0.06767; - phimax[47] = 0.765802; - dtcname[48] = "neg2S_5"; - layerdisk[48] = 6; - phimin[48] = -0.0648201; - phimax[48] = 0.762952; - dtcname[49] = "neg2S_5"; - layerdisk[49] = 9; - phimin[49] = -0.06767; - phimax[49] = 0.765802; - dtcname[50] = "neg2S_6"; - layerdisk[50] = 7; - phimin[50] = -0.0648201; - phimax[50] = 0.762952; - dtcname[51] = "neg2S_6"; - layerdisk[51] = 10; - phimin[51] = -0.06767; - phimax[51] = 0.765802; - - double dphi = 0.5 * dphisectorHG_ - M_PI / NSector_; + // Each Input Router (IR) reads stubs from one DTC (e.g. PS10G_1) & sends them + // to 4-8 InputLink (IL) memories (labelled PHIA-PHIH), each corresponding to a small + // phi region of a nonant, for each tracklet layer (L1-L6 or D1-D5) that the DTC + // reads. The InputLink memories have names such as IL_L1PHIC_PS10G_1 to reflect this. string olddtc = ""; - for (unsigned int i = 0; i < 52; i++) { - if (olddtc != dtcname[i]) { - modules << "InputRouter: IR_" << dtcname[i] << "_A" << std::endl; - modules << "InputRouter: IR_" << dtcname[i] << "_B" << std::endl; - memories << "DTCLink: DL_" << dtcname[i] << "_A [36]" << std::endl; - memories << "DTCLink: DL_" << dtcname[i] << "_B [36]" << std::endl; - os << "DL_" << dtcname[i] << "_A" - << " input=> output=> IR_" << dtcname[i] << "_A.stubin" << std::endl; - os << "DL_" << dtcname[i] << "_B" - << " input=> output=> IR_" << dtcname[i] << "_B.stubin" << std::endl; + for (const DTCinfo& info : vecDTCinfo_) { + string dtcname = info.name; + if (olddtc != dtcname) { + // Write one entry per DTC, with each DTC connected to one IR. + modules << "InputRouter: IR_" << dtcname << "_A" << std::endl; + modules << "InputRouter: IR_" << dtcname << "_B" << std::endl; + memories << "DTCLink: DL_" << dtcname << "_A [36]" << std::endl; + memories << "DTCLink: DL_" << dtcname << "_B [36]" << std::endl; + os << "DL_" << dtcname << "_A" + << " input=> output=> IR_" << dtcname << "_A.stubin" << std::endl; + os << "DL_" << dtcname << "_B" + << " input=> output=> IR_" << dtcname << "_B.stubin" << std::endl; } - olddtc = dtcname[i]; + olddtc = dtcname; } - for (unsigned int i = 0; i < 52; i++) { - double phimintmp = phimin[i] + dphi; - double phimaxtmp = phimax[i] + dphi; + for (const DTCinfo& info : vecDTCinfo_) { + string dtcname = info.name; + int layerdisk = info.layer; + + for (unsigned int iReg = 0; iReg < NRegions_[layerdisk]; iReg++) { + //--- Ian Tomalin's proposed bug fix + double phiminDTC_A = info.phimin - M_PI / N_SECTOR; // Phi range of each DTC. + double phimaxDTC_A = info.phimax - M_PI / N_SECTOR; + double phiminDTC_B = info.phimin + M_PI / N_SECTOR; // Phi range of each DTC. + double phimaxDTC_B = info.phimax + M_PI / N_SECTOR; + if (allStubs_[layerdisk][iReg].second > phiminDTC_A && allStubs_[layerdisk][iReg].first < phimaxDTC_A) { + memories << "InputLink: IL_" << LayerName(layerdisk) << "PHI" << iTCStr(iReg) << "_" << dtcname << "_A" + << " [36]" << std::endl; + os << "IL_" << LayerName(layerdisk) << "PHI" << iTCStr(iReg) << "_" << dtcname << "_A" + << " input=> IR_" << dtcname << "_A.stubout output=> VMR_" << LayerName(layerdisk) << "PHI" << iTCStr(iReg) + << ".stubin" << std::endl; + } + if (allStubs_[layerdisk][iReg].second > phiminDTC_B && allStubs_[layerdisk][iReg].first < phimaxDTC_B) { + memories << "InputLink: IL_" << LayerName(layerdisk) << "PHI" << iTCStr(iReg) << "_" << dtcname << "_B" + << " [36]" << std::endl; + os << "IL_" << LayerName(layerdisk) << "PHI" << iTCStr(iReg) << "_" << dtcname << "_B" + << " input=> IR_" << dtcname << "_B.stubout output=> VMR_" << LayerName(layerdisk) << "PHI" << iTCStr(iReg) + << ".stubin" << std::endl; + } + //--- Original (buggy) code + /* + double phiminDTC = info.phimin; // Phi range of each DTC. + double phimaxDTC = info.phimax; - for (unsigned int iReg = 0; iReg < NRegions_[layerdisk[i]]; iReg++) { - if (allStubs_[layerdisk[i]][iReg].first > phimaxtmp && allStubs_[layerdisk[i]][iReg].second < phimintmp) + if (allStubs_[layerdisk][iReg].first > phimaxDTC && allStubs_[layerdisk][iReg].second < phiminDTC) continue; - if (allStubs_[layerdisk[i]][iReg].second < phimaxtmp) { - memories << "InputLink: IL_" << LayerName(layerdisk[i]) << "PHI" << iTCStr(iReg) << "_" << dtcname[i] << "_A" + // Phi region range must be entirely contained in this DTC to keep this connection. + if (allStubs_[layerdisk][iReg].second < phimaxDTC) { + memories << "InputLink: IL_" << LayerName(layerdisk) << "PHI" << iTCStr(iReg) << "_" << dtcname << "_A" << " [36]" << std::endl; - os << "IL_" << LayerName(layerdisk[i]) << "PHI" << iTCStr(iReg) << "_" << dtcname[i] << "_A" - << " input=> IR_" << dtcname[i] << "_A.stubout output=> VMR_" << LayerName(layerdisk[i]) << "PHI" + os << "IL_" << LayerName(layerdisk) << "PHI" << iTCStr(iReg) << "_" << dtcname << "_A" + << " input=> IR_" << dtcname << "_A.stubout output=> VMR_" << LayerName(layerdisk) << "PHI" << iTCStr(iReg) << ".stubin" << std::endl; } - if (allStubs_[layerdisk[i]][iReg].first > phimintmp) { - memories << "InputLink: IL_" << LayerName(layerdisk[i]) << "PHI" << iTCStr(iReg) << "_" << dtcname[i] << "_B" + if (allStubs_[layerdisk][iReg].first > phiminDTC) { + memories << "InputLink: IL_" << LayerName(layerdisk) << "PHI" << iTCStr(iReg) << "_" << dtcname << "_B" << " [36]" << std::endl; - os << "IL_" << LayerName(layerdisk[i]) << "PHI" << iTCStr(iReg) << "_" << dtcname[i] << "_B" - << " input=> IR_" << dtcname[i] << "_B.stubout output=> VMR_" << LayerName(layerdisk[i]) << "PHI" + os << "IL_" << LayerName(layerdisk) << "PHI" << iTCStr(iReg) << "_" << dtcname << "_B" + << " input=> IR_" << dtcname << "_B.stubout output=> VMR_" << LayerName(layerdisk) << "PHI" << iTCStr(iReg) << ".stubin" << std::endl; } +*/ } } } +//--- Fill streams used to write wiring map to file + void TrackletConfigBuilder::writeAll(std::ostream& wires, std::ostream& memories, std::ostream& modules) { writeILMemories(wires, memories, modules); writeASMemories(wires, memories, modules); diff --git a/L1Trigger/TrackFindingTracklet/src/TrackletEngine.cc b/L1Trigger/TrackFindingTracklet/src/TrackletEngine.cc index 1c70057008575..7f32e78191fbc 100644 --- a/L1Trigger/TrackFindingTracklet/src/TrackletEngine.cc +++ b/L1Trigger/TrackFindingTracklet/src/TrackletEngine.cc @@ -134,6 +134,7 @@ void TrackletEngine::execute() { if (settings_.debugTracklet()) edm::LogVerbatim("Tracklet") << "Adding stub pair in " << getName(); + assert(stubpairs_ != nullptr); stubpairs_->addStubPair(innervmstub, outervmstub); countpass++; } diff --git a/L1Trigger/TrackFindingTracklet/src/TrackletEventProcessor.cc b/L1Trigger/TrackFindingTracklet/src/TrackletEventProcessor.cc index 5674fb0ff972f..3a0238126c82e 100644 --- a/L1Trigger/TrackFindingTracklet/src/TrackletEventProcessor.cc +++ b/L1Trigger/TrackFindingTracklet/src/TrackletEventProcessor.cc @@ -7,6 +7,7 @@ #include "L1Trigger/TrackFindingTracklet/interface/Track.h" #include "L1Trigger/TrackFindingTracklet/interface/TrackletConfigBuilder.h" #include "L1Trigger/TrackFindingTracklet/interface/IMATH_TrackletCalculator.h" +#include "L1Trigger/TrackFindingTracklet/interface/StubStreamData.h" #include "DataFormats/Math/interface/deltaPhi.h" @@ -24,9 +25,8 @@ TrackletEventProcessor::~TrackletEventProcessor() { } } -void TrackletEventProcessor::init(Settings const& theSettings) { +void TrackletEventProcessor::init(Settings const& theSettings, const tt::Setup* setup) { settings_ = &theSettings; - globals_ = make_unique(*settings_); //Verify consistency @@ -80,7 +80,7 @@ void TrackletEventProcessor::init(Settings const& theSettings) { sector_ = make_unique(*settings_, globals_.get()); - if (settings_->extended()) { + if (settings_->extended() || settings_->reduced()) { ifstream inmem(settings_->memoryModulesFile().c_str()); assert(inmem.good()); @@ -93,7 +93,7 @@ void TrackletEventProcessor::init(Settings const& theSettings) { configure(inwire, inmem, inproc); } else { - TrackletConfigBuilder config(*settings_); + TrackletConfigBuilder config(*settings_, setup); //Write configurations to file. if (settings_->writeConfig()) { @@ -173,7 +173,9 @@ void TrackletEventProcessor::configure(istream& inwire, istream& inmem, istream& } } -void TrackletEventProcessor::event(SLHCEvent& ev) { +void TrackletEventProcessor::event(SLHCEvent& ev, + vector>& streamsTrackRaw, + vector>& streamsStubRaw) { globals_->event() = &ev; tracks_.clear(); @@ -279,44 +281,47 @@ void TrackletEventProcessor::event(SLHCEvent& ev) { sector_->executeTC(); TCTimer_.stop(); - int nTP = globals_->event()->nsimtracks(); - for (int iTP = 0; iTP < nTP; iTP++) { - L1SimTrack simtrk = globals_->event()->simtrack(iTP); - if (simtrk.pt() < 2.0) - continue; - if (std::abs(simtrk.vz()) > 15.0) - continue; - if (hypot(simtrk.vx(), simtrk.vy()) > 0.1) - continue; - bool electron = (abs(simtrk.type()) == 11); - bool muon = (abs(simtrk.type()) == 13); - bool pion = (abs(simtrk.type()) == 211); - bool kaon = (abs(simtrk.type()) == 321); - bool proton = (abs(simtrk.type()) == 2212); - if (!(electron || muon || pion || kaon || proton)) - continue; - int nlayers = 0; - int ndisks = 0; - int simtrackid = simtrk.trackid(); - unsigned int hitmask = ev.layersHit(simtrackid, nlayers, ndisks); - if (nlayers + ndisks < 4) - continue; - - if (settings_->writeMonitorData("HitEff")) { - static ofstream outhit("hiteff.txt"); - outhit << simtrk.eta() << " " << (hitmask & 1) << " " << (hitmask & 2) << " " << (hitmask & 4) << " " - << (hitmask & 8) << " " << (hitmask & 16) << " " << (hitmask & 32) << " " << (hitmask & 64) << " " - << (hitmask & 128) << " " << (hitmask & 256) << " " << (hitmask & 512) << " " << (hitmask & 1024) - << endl; - } + if (settings_->writeMonitorData("HitEff") || settings_->bookHistos()) { + int nTP = globals_->event()->nsimtracks(); + for (int iTP = 0; iTP < nTP; iTP++) { + L1SimTrack simtrk = globals_->event()->simtrack(iTP); + if (simtrk.pt() < 2.0) + continue; + if (std::abs(simtrk.vz()) > 15.0) + continue; + if (hypot(simtrk.vx(), simtrk.vy()) > 0.1) + continue; + bool electron = (abs(simtrk.type()) == 11); + bool muon = (abs(simtrk.type()) == 13); + bool pion = (abs(simtrk.type()) == 211); + bool kaon = (abs(simtrk.type()) == 321); + bool proton = (abs(simtrk.type()) == 2212); + if (!(electron || muon || pion || kaon || proton)) + continue; + int nlayers = 0; + int ndisks = 0; + int simtrackid = simtrk.trackid(); + unsigned int hitmask = 0; + hitmask = ev.layersHit(simtrackid, nlayers, ndisks); // FIX CPU use. + if (nlayers + ndisks < 4) + continue; + + if (settings_->writeMonitorData("HitEff")) { + static ofstream outhit("hiteff.txt"); + outhit << simtrk.eta() << " " << (hitmask & 1) << " " << (hitmask & 2) << " " << (hitmask & 4) << " " + << (hitmask & 8) << " " << (hitmask & 16) << " " << (hitmask & 32) << " " << (hitmask & 64) << " " + << (hitmask & 128) << " " << (hitmask & 256) << " " << (hitmask & 512) << " " << (hitmask & 1024) + << endl; + } - std::unordered_set matchseed; - std::unordered_set matchseedtmp = sector_->seedMatch(iTP); - matchseed.insert(matchseedtmp.begin(), matchseedtmp.end()); - if (settings_->bookHistos()) { - for (int iseed = 0; iseed < 8; iseed++) { - bool eff = matchseed.find(iseed) != matchseed.end(); - globals_->histograms()->fillSeedEff(iseed, simtrk.eta(), eff); + std::unordered_set matchseed; + std::unordered_set matchseedtmp = sector_->seedMatch(iTP); + matchseed.insert(matchseedtmp.begin(), matchseedtmp.end()); + if (settings_->bookHistos()) { + for (int iseed = 0; iseed < 8; iseed++) { + bool eff = matchseed.find(iseed) != matchseed.end(); + globals_->histograms()->fillSeedEff(iseed, simtrk.eta(), eff); + } } } } @@ -326,6 +331,11 @@ void TrackletEventProcessor::event(SLHCEvent& ev) { sector_->executeTCD(); TCDTimer_.stop(); + // tracklet processor displaced + TPDTimer_.start(); + sector_->executeTPD(); + TPDTimer_.stop(); + if (settings_->writeMem() && k == settings_->writememsect()) { sector_->writeTPAR(first); sector_->writeTPROJ(first); @@ -364,7 +374,7 @@ void TrackletEventProcessor::event(SLHCEvent& ev) { // fit track FTTimer_.start(); - sector_->executeFT(); + sector_->executeFT(streamsTrackRaw, streamsStubRaw); if ((settings_->writeMem() || settings_->writeMonitorData("IFit")) && k == settings_->writememsect()) { sector_->writeTF(first); } @@ -420,7 +430,11 @@ void TrackletEventProcessor::printSummary() { << TRETimer_.tottime() << "\n" << "TrackletCalculatorDisplaced" << setw(10) << TCDTimer_.ntimes() << setw(20) << setprecision(3) << TCDTimer_.avgtime() * 1000.0 << setw(20) << setprecision(3) - << TCDTimer_.tottime(); + << TCDTimer_.tottime() << "\n" + << TCDTimer_.tottime() << "\n" + << "TrackletProcessorDisplaced" << setw(10) << TPDTimer_.ntimes() << setw(20) + << setprecision(3) << TPDTimer_.avgtime() * 1000.0 << setw(20) << setprecision(3) + << TPDTimer_.tottime(); } edm::LogVerbatim("Tracklet") << "TrackletCalculator " << setw(10) << TCTimer_.ntimes() << setw(20) << setprecision(3) << TCTimer_.avgtime() * 1000.0 << setw(20) << setprecision(3) diff --git a/L1Trigger/TrackFindingTracklet/src/TrackletLUT.cc b/L1Trigger/TrackFindingTracklet/src/TrackletLUT.cc index 2db66885daac8..4f969a2e80cd2 100644 --- a/L1Trigger/TrackFindingTracklet/src/TrackletLUT.cc +++ b/L1Trigger/TrackFindingTracklet/src/TrackletLUT.cc @@ -125,7 +125,7 @@ void TrackletLUT::initTPlut(bool fillInner, } else { rinner = settings_.rmean(layerdisk1); } - double rinv1 = rinv(0.0, -dphi[i2], rinner, router[i3]); + double rinv1 = (rinner < router[i3]) ? rinv(0.0, -dphi[i2], rinner, router[i3]) : 20.0; double pitchinner = (rinner < settings_.rcrit()) ? settings_.stripPitch(true) : settings_.stripPitch(false); double pitchouter = (router[i3] < settings_.rcrit()) ? settings_.stripPitch(true) : settings_.stripPitch(false); @@ -313,7 +313,7 @@ void TrackletLUT::initteptlut(bool fillInner, } else { rinner = settings_.rmean(layerdisk1); } - double rinv1 = -rinv(phiinner[i1], phiouter[i2], rinner, router[i3]); + double rinv1 = (rinner < router[i3]) ? -rinv(phiinner[i1], phiouter[i2], rinner, router[i3]) : -20.0; double pitchinner = (rinner < settings_.rcrit()) ? settings_.stripPitch(true) : settings_.stripPitch(false); double pitchouter = @@ -423,11 +423,13 @@ void TrackletLUT::initProjectionBend(double k_phider, double stripPitch = (rproj < settings_.rcrit()) ? settings_.stripPitch(true) : settings_.stripPitch(false); double bendproj = bendstrip(rproj, rinv, stripPitch); - int ibendproj = 2.0 * bendproj + 15.5; + static double maxbend = (1 << NRINVBITS) - 1; + + int ibendproj = 2.0 * bendproj + 0.5 * maxbend; if (ibendproj < 0) ibendproj = 0; - if (ibendproj > 31) - ibendproj = 31; + if (ibendproj > maxbend) + ibendproj = maxbend; table_.push_back(ibendproj); } @@ -630,7 +632,8 @@ void TrackletLUT::initVMRTable(unsigned int layerdisk, VMRTableType type, int re } else { if (type == VMRTableType::me) { //This if a hack where the same memory is used in both ME and TE modules - if (layerdisk == 1 || layerdisk == 2 || layerdisk == 3 || layerdisk == 4) { + if (layerdisk == LayerDisk::L2 || layerdisk == LayerDisk::L3 || layerdisk == LayerDisk::L4 || + layerdisk == LayerDisk::L6) { positive_ = false; name_ = "VMTableOuter" + TrackletConfigBuilder::LayerName(layerdisk) + ".tab"; writeTable(); diff --git a/L1Trigger/TrackFindingTracklet/src/TrackletParametersMemory.cc b/L1Trigger/TrackFindingTracklet/src/TrackletParametersMemory.cc index 7667f26038a97..7368391eeff70 100644 --- a/L1Trigger/TrackFindingTracklet/src/TrackletParametersMemory.cc +++ b/L1Trigger/TrackFindingTracklet/src/TrackletParametersMemory.cc @@ -33,10 +33,7 @@ void TrackletParametersMemory::writeTPAR(bool first, unsigned int iSector) { for (unsigned int j = 0; j < tracklets_.size(); j++) { string tpar = tracklets_[j]->trackletparstr(); - out_ << "0x"; - out_ << std::setfill('0') << std::setw(2); - out_ << hex << j << dec; - out_ << " " << tpar << " " << trklet::hexFormat(tpar) << endl; + out_ << hexstr(j) << " " << tpar << " " << trklet::hexFormat(tpar) << endl; } out_.close(); diff --git a/L1Trigger/TrackFindingTracklet/src/TrackletProcessorDisplaced.cc b/L1Trigger/TrackFindingTracklet/src/TrackletProcessorDisplaced.cc new file mode 100644 index 0000000000000..18a2bacf3f517 --- /dev/null +++ b/L1Trigger/TrackFindingTracklet/src/TrackletProcessorDisplaced.cc @@ -0,0 +1,688 @@ +#include "L1Trigger/TrackFindingTracklet/interface/TrackletProcessorDisplaced.h" +#include "L1Trigger/TrackFindingTracklet/interface/Settings.h" +#include "L1Trigger/TrackFindingTracklet/interface/Globals.h" +#include "L1Trigger/TrackFindingTracklet/interface/AllStubsMemory.h" +#include "L1Trigger/TrackFindingTracklet/interface/AllInnerStubsMemory.h" +#include "L1Trigger/TrackFindingTracklet/interface/StubPairsMemory.h" +#include "L1Trigger/TrackFindingTracklet/interface/Tracklet.h" +#include "L1Trigger/TrackFindingTracklet/interface/Util.h" +#include "L1Trigger/TrackFindingTracklet/interface/IMATH_TrackletCalculator.h" + +#include "FWCore/MessageLogger/interface/MessageLogger.h" +#include "FWCore/Utilities/interface/Exception.h" +#include "DataFormats/Math/interface/deltaPhi.h" + +#include +#include + +using namespace std; +using namespace trklet; + +TrackletProcessorDisplaced::TrackletProcessorDisplaced(string name, Settings const& settings, Globals* globals) + : TrackletCalculatorDisplaced(name, settings, globals), + innerTable_(settings), + innerOverlapTable_(settings), + innerThirdTable_(settings) { + innerallstubs_.clear(); + middleallstubs_.clear(); + outerallstubs_.clear(); + stubpairs_.clear(); + innervmstubs_.clear(); + outervmstubs_.clear(); + + const unsigned layerdiskPosInName = 4; + const unsigned regionPosInName1 = 9; + + // iAllStub_ = -1; + layerdisk_ = initLayerDisk(layerdiskPosInName); + + unsigned int region = name.substr(1)[regionPosInName1] - 'A'; + // assert(region < settings_.nallstubs(layerdisk_)); + + if (layerdisk_ == LayerDisk::L1 || layerdisk_ == LayerDisk::L2 || layerdisk_ == LayerDisk::L3 || + layerdisk_ == LayerDisk::L5 || layerdisk_ == LayerDisk::D1 || layerdisk_ == LayerDisk::D3) { + innerTable_.initVMRTable(layerdisk_, TrackletLUT::VMRTableType::inner, region); //projection to next layer/disk + } + + if (layerdisk_ == LayerDisk::L1 || layerdisk_ == LayerDisk::L2) { + innerOverlapTable_.initVMRTable( + layerdisk_, TrackletLUT::VMRTableType::inneroverlap, region); //projection to disk from layer + } + + if (layerdisk_ == LayerDisk::L2 || layerdisk_ == LayerDisk::L3 || layerdisk_ == LayerDisk::L5 || + layerdisk_ == LayerDisk::D1) { + innerThirdTable_.initVMRTable( + layerdisk_, TrackletLUT::VMRTableType::innerthird, region); //projection to third layer/disk + } + + nbitszfinebintable_ = settings_.vmrlutzbits(layerdisk_); + nbitsrfinebintable_ = settings_.vmrlutrbits(layerdisk_); + + for (unsigned int ilayer = 0; ilayer < N_LAYER; ilayer++) { + vector tmp(settings_.nallstubs(ilayer), nullptr); + trackletprojlayers_.push_back(tmp); + } + + for (unsigned int idisk = 0; idisk < N_DISK; idisk++) { + vector tmp(settings_.nallstubs(idisk + N_LAYER), nullptr); + trackletprojdisks_.push_back(tmp); + } + + // initLayerDisksandISeed(layerdisk1_, layerdisk2_, iSeed_); + + layer_ = 0; + disk_ = 0; + layer1_ = 0; + layer2_ = 0; + layer3_ = 0; + disk1_ = 0; + disk2_ = 0; + disk3_ = 0; + + const unsigned layerPosInName1 = 4; + const unsigned diskPosInName1 = 4; + const unsigned layer1PosInName1 = 4; + const unsigned disk1PosInName1 = 4; + const unsigned layer2PosInName1 = 6; + const unsigned disk2PosInName1 = 6; + + string name1 = name.substr(1); //this is to correct for "TPD" having one more letter then "TP" + if (name1[3] == 'L') + layer_ = name1[layerPosInName1] - '0'; + if (name1[3] == 'D') + disk_ = name1[diskPosInName1] - '0'; + + if (name1[3] == 'L') + layer1_ = name1[layer1PosInName1] - '0'; + if (name1[3] == 'D') + disk1_ = name1[disk1PosInName1] - '0'; + if (name1[5] == 'L') + layer2_ = name1[layer2PosInName1] - '0'; + if (name1[5] == 'D') + disk2_ = name1[disk2PosInName1] - '0'; + + // set TC index + iSeed_ = 0; + + int iTC = name1[regionPosInName1] - 'A'; + + if (name1.substr(3, 6) == "L3L4L2") { + iSeed_ = 8; + layer3_ = 2; + } else if (name1.substr(3, 6) == "L5L6L4") { + iSeed_ = 9; + layer3_ = 4; + } else if (name1.substr(3, 6) == "L2L3D1") { + iSeed_ = 10; + disk3_ = 1; + } else if (name1.substr(3, 6) == "D1D2L2") { + iSeed_ = 11; + layer3_ = 2; + } + assert(iSeed_ != 0); + + const int TCIndexMin = 128; + const int TCIndexMax = 191; + + TCIndex_ = (iSeed_ << 4) + iTC; + assert(TCIndex_ >= TCIndexMin && TCIndex_ < TCIndexMax); + + assert((layer_ != 0) || (disk_ != 0)); +} + +void TrackletProcessorDisplaced::addOutputProjection(TrackletProjectionsMemory*& outputProj, MemoryBase* memory) { + outputProj = dynamic_cast(memory); + assert(outputProj != nullptr); +} + +void TrackletProcessorDisplaced::addOutput(MemoryBase* memory, string output) { + if (settings_.writetrace()) { + edm::LogVerbatim("Tracklet") << "In " << name_ << " adding output to " << memory->getName() << " to output " + << output; + } + + if (output == "trackpar") { + auto* tmp = dynamic_cast(memory); + assert(tmp != nullptr); + trackletpars_ = tmp; + return; + } + + if (output.substr(0, 7) == "projout") { + //output is on the form 'projoutL2PHIC' or 'projoutD3PHIB' + auto* tmp = dynamic_cast(memory); + assert(tmp != nullptr); + + const unsigned layerdiskPosInprojout = 8; + const unsigned phiPosInprojout = 12; + + unsigned int layerdisk = output[layerdiskPosInprojout] - '1'; //layer or disk counting from 0 + unsigned int phiregion = output[phiPosInprojout] - 'A'; //phiregion counting from 0 + + if (output[7] == 'L') { + assert(layerdisk < N_LAYER); + assert(phiregion < trackletprojlayers_[layerdisk].size()); + //check that phiregion not already initialized + assert(trackletprojlayers_[layerdisk][phiregion] == nullptr); + trackletprojlayers_[layerdisk][phiregion] = tmp; + return; + } + + if (output[7] == 'D') { + assert(layerdisk < N_DISK); + assert(phiregion < trackletprojdisks_[layerdisk].size()); + //check that phiregion not already initialized + assert(trackletprojdisks_[layerdisk][phiregion] == nullptr); + trackletprojdisks_[layerdisk][phiregion] = tmp; + return; + } + } + + throw cms::Exception("BadConfig") << __FILE__ << " " << __LINE__ << " Could not find output : " << output; +} + +void TrackletProcessorDisplaced::addInput(MemoryBase* memory, string input) { + if (settings_.writetrace()) { + edm::LogVerbatim("Tracklet") << "In " << name_ << " adding input from " << memory->getName() << " to input " + << input; + } + + if (input == "thirdallstubin") { + auto* tmp = dynamic_cast(memory); + assert(tmp != nullptr); + innerallstubs_.push_back(tmp); + return; + } + if (input == "firstallstubin") { + auto* tmp = dynamic_cast(memory); + assert(tmp != nullptr); + middleallstubs_.push_back(tmp); + return; + } + if (input == "secondallstubin") { + auto* tmp = dynamic_cast(memory); + assert(tmp != nullptr); + outerallstubs_.push_back(tmp); + return; + } + if (input.substr(0, 8) == "stubpair") { + auto* tmp = dynamic_cast(memory); + assert(tmp != nullptr); + stubpairs_.push_back(tmp); + return; + } + + if (input == "thirdvmstubin") { + auto* tmp = dynamic_cast(memory); + assert(tmp != nullptr); + innervmstubs_.push_back(tmp); + return; + } + if (input == "secondvmstubin") { + auto* tmp = dynamic_cast(memory); + assert(tmp != nullptr); + // outervmstubs_ = tmp; + outervmstubs_.push_back(tmp); + return; + } + + throw cms::Exception("BadConfig") << __FILE__ << " " << __LINE__ << " Could not find input : " << input; +} + +void TrackletProcessorDisplaced::execute(unsigned int iSector, double phimin, double phimax) { + unsigned int countall = 0; + unsigned int countall_ = 0; + unsigned int countsel = 0; + unsigned int countpass = 0; + unsigned int countpass_ = 0; + // unsigned int nThirdStubs = 0; + unsigned int nInnerStubs = 0; + // unsigned int nOuterStubs = 0; + count_ = 0; + + phimin_ = phimin; + phimax_ = phimax; + iSector_ = iSector; + + for (unsigned int iInnerMem = 0; iInnerMem < middleallstubs_.size(); + nInnerStubs += middleallstubs_.at(iInnerMem)->nStubs(), iInnerMem++) + ; + + assert(!innerallstubs_.empty()); + assert(!middleallstubs_.empty()); + assert(!outerallstubs_.empty()); + assert(!innervmstubs_.empty()); + assert(!outervmstubs_.empty()); + assert(stubpairs_.empty()); + + for (auto& iInnerMem : middleallstubs_) { + assert(iInnerMem->nStubs() == iInnerMem->nStubs()); + for (unsigned int j = 0; j < iInnerMem->nStubs(); j++) { + const Stub* firstallstub = iInnerMem->getStub(j); + + if (settings_.debugTracklet()) { + edm::LogVerbatim("Tracklet") << "In " << getName() << " have first stub\n"; + } + + int inner = 0; + bool negdisk = (firstallstub->disk().value() < 0); + int indexz = (((1 << (firstallstub->z().nbits() - 1)) + firstallstub->z().value()) >> + (firstallstub->z().nbits() - nbitszfinebintable_)); + int indexr = -1; + if (layerdisk_ > (N_LAYER - 1)) { + if (negdisk) { + indexz = (1 << nbitszfinebintable_) - indexz; + } + indexr = firstallstub->r().value(); + if (firstallstub->isPSmodule()) { + indexr = firstallstub->r().value() >> (firstallstub->r().nbits() - nbitsrfinebintable_); + } + } else { + //Take the top nbitsfinebintable_ bits of the z coordinate. The & is to handle the negative z values. + indexr = (((1 << (firstallstub->r().nbits() - 1)) + firstallstub->r().value()) >> + (firstallstub->r().nbits() - nbitsrfinebintable_)); + } + + assert(indexz >= 0); + assert(indexr >= 0); + assert(indexz < (1 << nbitszfinebintable_)); + assert(indexr < (1 << nbitsrfinebintable_)); + + // int melut = meTable_.lookup((indexz << nbitsrfinebintable_) + indexr); + // assert(melut >= 0); + + unsigned int lutwidth = settings_.lutwidthtab(inner, iSeed_); + if (settings_.extended()) { + lutwidth = settings_.lutwidthtabextended(inner, iSeed_); + } + + int lutval = -999; + + if (iSeed_ < Seed::L1D1 || iSeed_ > Seed::L2D1) { + lutval = innerTable_.lookup((indexz << nbitsrfinebintable_) + indexr); + } else { + lutval = innerOverlapTable_.lookup((indexz << nbitsrfinebintable_) + indexr); + } + + if (lutval == -1) + continue; + if (settings_.extended() && + (iSeed_ == Seed::L2L3L4 || iSeed_ == Seed::L4L5L6 || iSeed_ == Seed::D1D2L2 || iSeed_ == Seed::L2L3D1)) { + int lutval2 = innerThirdTable_.lookup((indexz << nbitsrfinebintable_) + indexr); + if (lutval2 != -1) + lutval += (lutval2 << 10); + } + + assert(lutval >= 0); + // assert(lutwidth > 0); + + FPGAWord binlookup(lutval, lutwidth, true, __LINE__, __FILE__); + FPGAWord finephi = + firstallstub->iphivmFineBins(settings_.nphireg(inner, iSeed_), settings_.nfinephi(inner, iSeed_)); + + if ((layer1_ == 3 && layer2_ == 4) || (layer1_ == 5 && layer2_ == 6)) { + if (settings_.debugTracklet()) { + edm::LogVerbatim("Tracklet") << getName() << " Layer-layer pair\n"; + } + + const int andlookupbits = 1023; + const int shiftzdiffmax = 7; + const int andnewbin = 127; + const int divbin = 8; + const int andzbinfirst = 7; + const int shiftstart = 1; + const int andlast = 1; + const int maxlast = 8; + + int lookupbits = binlookup.value() & andlookupbits; + int zdiffmax = (lookupbits >> shiftzdiffmax); + int newbin = (lookupbits & andnewbin); + int bin = newbin / divbin; + + int zbinfirst = newbin & andzbinfirst; + + int start = (bin >> shiftstart); + int last = start + (bin & andlast); + + assert(last < maxlast); + + if (settings_.debugTracklet()) { + edm::LogVerbatim("Tracklet") << "Will look in zbins " << start << " to " << last << endl; + } + + for (int ibin = start; ibin <= last; ibin++) { + for (unsigned int m = 0; m < outervmstubs_.size(); m++) { + for (unsigned int j = 0; j < outervmstubs_.at(m)->nVMStubsBinned(ibin); j++) { + if (settings_.debugTracklet()) { + edm::LogVerbatim("Tracklet") + << "In " << getName() << " have second stub(1) " << ibin << " " << j << endl; + } + + const VMStubTE& secondvmstub = outervmstubs_.at(m)->getVMStubTEBinned(ibin, j); + + int zbin = (secondvmstub.vmbits().value() & 7); + if (start != ibin) + zbin += 8; + if (zbin < zbinfirst || zbin - zbinfirst > zdiffmax) { + if (settings_.debugTracklet()) { + edm::LogVerbatim("Tracklet") << "Stubpair rejected because of wrong zbin"; + } + continue; + } + + countpass++; + + if ((layer2_ == 4 && layer3_ == 2) || (layer2_ == 6 && layer3_ == 4)) { + const int vmbitshift = 10; + const int andlookupbits_ = 1023; + const int andnewbin_ = 127; + const int divbin_ = 8; + const int shiftstart_ = 1; + const int andlast_ = 1; + + int lookupbits_ = (int)((binlookup.value() >> vmbitshift) & andlookupbits_); + int newbin_ = (lookupbits_ & andnewbin_); + int bin_ = newbin_ / divbin_; + + int start_ = (bin_ >> shiftstart_); + int last_ = start_ + (bin_ & andlast_); + + if (settings_.debugTracklet()) { + edm::LogVerbatim("Tracklet") + << "Will look in zbins for third stub" << start_ << " to " << last_ << endl; + } + + for (int ibin_ = start_; ibin_ <= last_; ibin_++) { + for (unsigned int k = 0; k < innervmstubs_.size(); k++) { + for (unsigned int l = 0; l < innervmstubs_.at(k)->nVMStubsBinned(ibin_); l++) { + if (settings_.debugTracklet()) { + edm::LogVerbatim("Tracklet") << "In " << getName() << " have third stub\n"; + } + + countall_++; + + const VMStubTE& thirdvmstub = innervmstubs_.at(k)->getVMStubTEBinned(ibin_, l); + + countpass_++; + + const Stub* innerFPGAStub = firstallstub; + const Stub* middleFPGAStub = secondvmstub.stub(); + const Stub* outerFPGAStub = thirdvmstub.stub(); + + const L1TStub* innerStub = innerFPGAStub->l1tstub(); + const L1TStub* middleStub = middleFPGAStub->l1tstub(); + const L1TStub* outerStub = outerFPGAStub->l1tstub(); + + if (settings_.debugTracklet()) { + edm::LogVerbatim("Tracklet") + << "LLL seeding\n" + << innerFPGAStub->strbare() << middleFPGAStub->strbare() << outerFPGAStub->strbare() + << innerStub->stubword() << middleStub->stubword() << outerStub->stubword() + << innerFPGAStub->layerdisk() << middleFPGAStub->layerdisk() << outerFPGAStub->layerdisk(); + } + + if (settings_.debugTracklet()) { + edm::LogVerbatim("Tracklet") + << "TrackletCalculatorDisplaced execute " << getName() << "[" << iSector_ << "]"; + } + + if (innerFPGAStub->layerdisk() < N_LAYER && middleFPGAStub->layerdisk() < N_LAYER && + outerFPGAStub->layerdisk() < N_LAYER) { + bool accept = + LLLSeeding(outerFPGAStub, outerStub, innerFPGAStub, innerStub, middleFPGAStub, middleStub); + + if (accept) + countsel++; + } else if (innerFPGAStub->layerdisk() >= N_LAYER && middleFPGAStub->layerdisk() >= N_LAYER && + outerFPGAStub->layerdisk() >= N_LAYER) { + throw cms::Exception("LogicError") << __FILE__ << " " << __LINE__ << " Invalid seeding!"; + } + + if (settings_.debugTracklet()) { + edm::LogVerbatim("Tracklet") << "TrackletCalculatorDisplaced execute done"; + } + } + } + } + } + } + } + } + + } else if (layer1_ == 2 && layer2_ == 3) { + if (settings_.debugTracklet()) { + edm::LogVerbatim("Tracklet") << getName() << " Layer-layer pair"; + } + + const int andlookupbits = 1023; + const int shiftzdiffmax = 7; + const int andnewbin = 127; + const int divbin = 8; + const int andzbinfirst = 7; + const int shiftstart = 1; + const int andlast = 1; + const int maxlast = 8; + + int lookupbits = binlookup.value() & andlookupbits; + int zdiffmax = (lookupbits >> shiftzdiffmax); + int newbin = (lookupbits & andnewbin); + int bin = newbin / divbin; + + int zbinfirst = newbin & andzbinfirst; + + int start = (bin >> shiftstart); + int last = start + (bin & andlast); + + assert(last < maxlast); + + if (settings_.debugTracklet()) { + edm::LogVerbatim("Tracklet") << "Will look in zbins " << start << " to " << last; + } + + for (int ibin = start; ibin <= last; ibin++) { + for (unsigned int m = 0; m < outervmstubs_.size(); m++) { + for (unsigned int j = 0; j < outervmstubs_.at(m)->nVMStubsBinned(ibin); j++) { + if (settings_.debugTracklet()) { + edm::LogVerbatim("Tracklet") << "In " << getName() << " have second stub(1) " << ibin << " " << j; + } + + countall++; + const VMStubTE& secondvmstub = outervmstubs_.at(m)->getVMStubTEBinned(ibin, j); + + int zbin = (secondvmstub.vmbits().value() & 7); + if (start != ibin) + zbin += 8; + if (zbin < zbinfirst || zbin - zbinfirst > zdiffmax) { + if (settings_.debugTracklet()) { + edm::LogVerbatim("Tracklet") << "Stubpair rejected because of wrong zbin"; + } + continue; + } + + if (layer2_ == 3 && disk3_ == 1) { + const int vmbitshift = 10; + const int andlookupbits_ = 1023; + const int andnewbin_ = 127; + const int divbin_ = 8; + const int shiftstart_ = 1; + const int andlast_ = 1; + + int lookupbits_ = (int)((binlookup.value() >> vmbitshift) & andlookupbits_); + int newbin_ = (lookupbits_ & andnewbin_); + int bin_ = newbin_ / divbin_; + + int start_ = (bin_ >> shiftstart_); + int last_ = start_ + (bin_ & andlast_); + + for (int ibin_ = start_; ibin_ <= last_; ibin_++) { + for (unsigned int k = 0; k < innervmstubs_.size(); k++) { + for (unsigned int l = 0; l < innervmstubs_.at(k)->nVMStubsBinned(ibin_); l++) { + if (settings_.debugTracklet()) { + edm::LogVerbatim("Tracklet") << "In " << getName() << " have third stub"; + } + + countall_++; + + const VMStubTE& thirdvmstub = innervmstubs_.at(k)->getVMStubTEBinned(ibin_, l); + + countpass_++; + + const Stub* innerFPGAStub = firstallstub; + const Stub* middleFPGAStub = secondvmstub.stub(); + const Stub* outerFPGAStub = thirdvmstub.stub(); + + const L1TStub* innerStub = innerFPGAStub->l1tstub(); + const L1TStub* middleStub = middleFPGAStub->l1tstub(); + const L1TStub* outerStub = outerFPGAStub->l1tstub(); + + if (settings_.debugTracklet()) { + edm::LogVerbatim("Tracklet") + << "LLD seeding\n" + << innerFPGAStub->strbare() << middleFPGAStub->strbare() << outerFPGAStub->strbare() + << innerStub->stubword() << middleStub->stubword() << outerStub->stubword() + << innerFPGAStub->layerdisk() << middleFPGAStub->layerdisk() << outerFPGAStub->layerdisk(); + } + + if (settings_.debugTracklet()) { + edm::LogVerbatim("Tracklet") + << "TrackletCalculatorDisplaced execute " << getName() << "[" << iSector_ << "]"; + } + + bool accept = + LLDSeeding(outerFPGAStub, outerStub, innerFPGAStub, innerStub, middleFPGAStub, middleStub); + + if (accept) + countsel++; + + if (settings_.debugTracklet()) { + edm::LogVerbatim("Tracklet") << "TrackletCalculatorDisplaced execute done"; + } + } + } + } + } + } + } + } + + } else if (disk1_ == 1 && disk2_ == 2) { + if (settings_.debugTracklet()) + edm::LogVerbatim("Tracklet") << getName() << " Disk-disk pair"; + + const int andlookupbits = 511; + const int shiftrdiffmax = 6; + const int andnewbin = 63; + const int divbin = 8; + const int andrbinfirst = 7; + const int shiftstart = 1; + const int andlast = 1; + const int maxlast = 8; + + int lookupbits = binlookup.value() & andlookupbits; + bool negdisk = firstallstub->disk().value() < 0; + int rdiffmax = (lookupbits >> shiftrdiffmax); + int newbin = (lookupbits & andnewbin); + int bin = newbin / divbin; + + int rbinfirst = newbin & andrbinfirst; + + int start = (bin >> shiftstart); + if (negdisk) + start += 4; + int last = start + (bin & andlast); + assert(last < maxlast); + + for (int ibin = start; ibin <= last; ibin++) { + for (unsigned int m = 0; m < outervmstubs_.size(); m++) { + if (settings_.debugTracklet()) { + edm::LogVerbatim("Tracklet") + << getName() << " looking for matching stub in " << outervmstubs_.at(m)->getName() + << " in bin = " << ibin << " with " << outervmstubs_.at(m)->nVMStubsBinned(ibin) << " stubs"; + } + + for (unsigned int j = 0; j < outervmstubs_.at(m)->nVMStubsBinned(ibin); j++) { + countall++; + + const VMStubTE& secondvmstub = outervmstubs_.at(m)->getVMStubTEBinned(ibin, j); + int rbin = (secondvmstub.vmbits().value() & 7); + if (start != ibin) + rbin += 8; + if (rbin < rbinfirst) + continue; + if (rbin - rbinfirst > rdiffmax) + continue; + + if (disk2_ == 2 && layer3_ == 2) { + const int vmbitshift = 10; + const int andlookupbits_ = 1023; + const int andnewbin_ = 127; + const int divbin_ = 8; + const int shiftstart_ = 1; + const int andlast_ = 1; + + int lookupbits_ = (int)((binlookup.value() >> vmbitshift) & andlookupbits_); + int newbin_ = (lookupbits_ & andnewbin_); + int bin_ = newbin_ / divbin_; + + int start_ = (bin_ >> shiftstart_); + int last_ = start_ + (bin_ & andlast_); + + if (firstallstub->disk().value() < 0) { //TODO - negative disk should come from memory + start_ = settings_.NLONGVMBINS() - last_ - 1; + last_ = settings_.NLONGVMBINS() - start_ - 1; + } + + for (int ibin_ = start_; ibin_ <= last_; ibin_++) { + for (unsigned int k = 0; k < innervmstubs_.size(); k++) { + for (unsigned int l = 0; l < innervmstubs_.at(k)->nVMStubsBinned(ibin_); l++) { + if (settings_.debugTracklet()) { + edm::LogVerbatim("Tracklet") << "In " << getName() << " have third stub"; + } + + countall_++; + + const VMStubTE& thirdvmstub = innervmstubs_.at(k)->getVMStubTEBinned(ibin_, l); + + countpass_++; + + const Stub* innerFPGAStub = firstallstub; + const Stub* middleFPGAStub = secondvmstub.stub(); + const Stub* outerFPGAStub = thirdvmstub.stub(); + + const L1TStub* innerStub = innerFPGAStub->l1tstub(); + const L1TStub* middleStub = middleFPGAStub->l1tstub(); + const L1TStub* outerStub = outerFPGAStub->l1tstub(); + + if (settings_.debugTracklet()) { + edm::LogVerbatim("Tracklet") + << "DDL seeding\n" + << innerFPGAStub->strbare() << middleFPGAStub->strbare() << outerFPGAStub->strbare() + << innerStub->stubword() << middleStub->stubword() << outerStub->stubword() + << innerFPGAStub->layerdisk() << middleFPGAStub->layerdisk() << outerFPGAStub->layerdisk(); + } + + if (settings_.debugTracklet()) { + edm::LogVerbatim("Tracklet") + << "TrackletCalculatorDisplaced execute " << getName() << "[" << iSector_ << "]"; + } + + bool accept = + DDLSeeding(outerFPGAStub, outerStub, innerFPGAStub, innerStub, middleFPGAStub, middleStub); + + if (accept) + countsel++; + + if (settings_.debugTracklet()) { + edm::LogVerbatim("Tracklet") << "TrackletCalculatorDisplaced execute done"; + } + } + } + } + } + } + } + } + } + } + } +} diff --git a/L1Trigger/TrackFindingTracklet/src/TrackletProjectionsMemory.cc b/L1Trigger/TrackFindingTracklet/src/TrackletProjectionsMemory.cc index b1861fdc64dab..2cde8759a71e8 100644 --- a/L1Trigger/TrackFindingTracklet/src/TrackletProjectionsMemory.cc +++ b/L1Trigger/TrackFindingTracklet/src/TrackletProjectionsMemory.cc @@ -12,6 +12,7 @@ TrackletProjectionsMemory::TrackletProjectionsMemory(string name, Settings const size_t pos = find_nth(name, 0, "_", 1); assert(pos != string::npos); initLayerDisk(pos + 1, layer_, disk_); + hasProj_ = false; } void TrackletProjectionsMemory::addProj(Tracklet* tracklet) { @@ -29,6 +30,7 @@ void TrackletProjectionsMemory::addProj(Tracklet* tracklet) { assert(itracklet != tracklet); } + hasProj_ = true; tracklets_.push_back(tracklet); } @@ -50,10 +52,7 @@ void TrackletProjectionsMemory::writeTPROJ(bool first, unsigned int iSector) { for (unsigned int j = 0; j < tracklets_.size(); j++) { string proj = (layer_ > 0 && tracklets_[j]->validProj(layer_ - 1)) ? tracklets_[j]->trackletprojstrlayer(layer_) : tracklets_[j]->trackletprojstrdisk(disk_); - out_ << "0x"; - out_ << std::setfill('0') << std::setw(2); - out_ << hex << j << dec; - out_ << " " << proj << " " << trklet::hexFormat(proj) << endl; + out_ << hexstr(j) << " " << proj << " " << trklet::hexFormat(proj) << endl; } out_.close(); diff --git a/L1Trigger/TrackFindingTracklet/src/VMProjectionsMemory.cc b/L1Trigger/TrackFindingTracklet/src/VMProjectionsMemory.cc index 3541d9ce522f6..007f865f73db3 100644 --- a/L1Trigger/TrackFindingTracklet/src/VMProjectionsMemory.cc +++ b/L1Trigger/TrackFindingTracklet/src/VMProjectionsMemory.cc @@ -41,10 +41,7 @@ void VMProjectionsMemory::writeVMPROJ(bool first, unsigned int iSector) { for (unsigned int j = 0; j < tracklets_.size(); j++) { string vmproj = (layer_ > 0) ? tracklets_[j].first->vmstrlayer(layer_, tracklets_[j].second) : tracklets_[j].first->vmstrdisk(disk_, tracklets_[j].second); - out_ << "0x"; - out_ << std::setfill('0') << std::setw(2); - out_ << hex << j << dec; - out_ << " " << vmproj << " " << trklet::hexFormat(vmproj) << endl; + out_ << hexstr(j) << " " << vmproj << " " << trklet::hexFormat(vmproj) << endl; } out_.close(); diff --git a/L1Trigger/TrackFindingTracklet/src/VMRouter.cc b/L1Trigger/TrackFindingTracklet/src/VMRouter.cc index bef76f3ac5e41..8ba7cf4c39770 100644 --- a/L1Trigger/TrackFindingTracklet/src/VMRouter.cc +++ b/L1Trigger/TrackFindingTracklet/src/VMRouter.cc @@ -272,15 +272,16 @@ void VMRouter::execute() { FPGAWord(stub->bend().value(), nbendbits, true, __LINE__, __FILE__), allStubIndex); - assert(vmstubsMEPHI_[ivmPlus] != nullptr); - vmstubsMEPHI_[ivmPlus]->addStub(vmstub, vmbin); + if (!(settings_.reduced())) + assert(vmstubsMEPHI_[ivmPlus] != nullptr); + if (vmstubsMEPHI_[ivmPlus] != nullptr) + vmstubsMEPHI_[ivmPlus]->addStub(vmstub, vmbin); if (settings_.debugTracklet()) { edm::LogVerbatim("Tracklet") << getName() << " adding stub to " << vmstubsMEPHI_[ivmPlus]->getName() << " ivmPlus" << ivmPlus << " bin=" << vmbin; } - if (ivmMinus != ivmPlus) { - assert(vmstubsMEPHI_[ivmMinus] != nullptr); + if (ivmMinus != ivmPlus && vmstubsMEPHI_[ivmMinus] != nullptr) { vmstubsMEPHI_[ivmMinus]->addStub(vmstub, vmbin); if (settings_.debugTracklet()) { edm::LogVerbatim("Tracklet") << getName() << " adding stub to " << vmstubsMEPHI_[ivmMinus]->getName() @@ -363,7 +364,8 @@ void VMRouter::execute() { unsigned int nmem = ivmstubTEPHI.vmstubmem[ivmte].size(); - assert(nmem > 0); + if (!(settings_.reduced())) + assert(nmem > 0); for (unsigned int l = 0; l < nmem; l++) { if (settings_.debugTracklet()) { diff --git a/L1Trigger/TrackFindingTracklet/src/VMRouterCM.cc b/L1Trigger/TrackFindingTracklet/src/VMRouterCM.cc index 751c75398a692..cb0e99e4ca667 100644 --- a/L1Trigger/TrackFindingTracklet/src/VMRouterCM.cc +++ b/L1Trigger/TrackFindingTracklet/src/VMRouterCM.cc @@ -121,9 +121,12 @@ void VMRouterCM::addInput(MemoryBase* memory, string input) { throw cms::Exception("BadConfig") << __FILE__ << " " << __LINE__ << " Could not find input : " << input; } -void VMRouterCM::execute() { +void VMRouterCM::execute(unsigned int) { unsigned int allStubCounter = 0; + //bool print = getName() == "VMR_D1PHIB" && iSector == 3; + //print = false; + //Loop over the input stubs for (auto& stubinput : stubinputs_) { for (unsigned int i = 0; i < stubinput->nStubs(); i++) { diff --git a/L1Trigger/TrackFindingTracklet/src/VMStubsMEMemory.cc b/L1Trigger/TrackFindingTracklet/src/VMStubsMEMemory.cc index 9ac11723a6fcf..60d437ad2f39f 100644 --- a/L1Trigger/TrackFindingTracklet/src/VMStubsMEMemory.cc +++ b/L1Trigger/TrackFindingTracklet/src/VMStubsMEMemory.cc @@ -43,7 +43,7 @@ void VMStubsMEMemory::writeStubs(bool first, unsigned int iSector) { stub += "|" + finephipos.str(); FPGAWord finepos = binnedstubs_[i][j].finerz(); stub += "|" + finepos.str(); - out_ << hex << i << " " << j << dec << " " << stub << " " << trklet::hexFormat(stub) << endl; + out_ << hexstr(i) << " " << hexstr(j) << " " << stub << " " << trklet::hexFormat(stub) << endl; } } out_.close(); diff --git a/L1Trigger/TrackFindingTracklet/src/VMStubsTEMemory.cc b/L1Trigger/TrackFindingTracklet/src/VMStubsTEMemory.cc index 48e05ece0eaae..77f0a9437840b 100644 --- a/L1Trigger/TrackFindingTracklet/src/VMStubsTEMemory.cc +++ b/L1Trigger/TrackFindingTracklet/src/VMStubsTEMemory.cc @@ -227,17 +227,14 @@ void VMStubsTEMemory::writeStubs(bool first, unsigned int iSector) { if (isinner_) { // inner VM for TE purpose for (unsigned int j = 0; j < stubsvm_.size(); j++) { - out_ << "0x"; - out_ << std::setfill('0') << std::setw(2); - out_ << hex << j << dec; string stub = stubsvm_[j].str(); - out_ << " " << stub << " " << trklet::hexFormat(stub) << endl; + out_ << hexstr(j) << " " << stub << " " << trklet::hexFormat(stub) << endl; } } else { // outer VM for TE purpose for (unsigned int i = 0; i < stubsbinnedvm_.size(); i++) { for (unsigned int j = 0; j < stubsbinnedvm_[i].size(); j++) { string stub = stubsbinnedvm_[i][j].str(); - out_ << hex << i << " " << j << dec << " " << stub << " " << trklet::hexFormat(stub) << endl; + out_ << hexstr(i) << " " << hexstr(j) << " " << stub << " " << trklet::hexFormat(stub) << endl; } } } diff --git a/L1Trigger/TrackFindingTracklet/src/imath_calculate.cc b/L1Trigger/TrackFindingTracklet/src/imath_calculate.cc index 8fce358b261e6..f608c8eae4721 100644 --- a/L1Trigger/TrackFindingTracklet/src/imath_calculate.cc +++ b/L1Trigger/TrackFindingTracklet/src/imath_calculate.cc @@ -15,15 +15,13 @@ bool VarBase::calculate(int debug_level) { if (p3_) ok3 = p3_->calculate(debug_level); + bool all_ok = debug_level && ok1 && ok2 && ok3; long int ival_prev = ival_; + local_calculate(); - bool all_ok = ok1 && ok2 && ok3 && debug_level; + val_ = ival_ * K_; - if (fval_ > maxval_) - maxval_ = fval_; - if (fval_ < minval_) - minval_ = fval_; #ifdef IMATH_ROOT if (globals_->use_root) { if (h_ == 0) { @@ -43,6 +41,18 @@ bool VarBase::calculate(int debug_level) { } #endif + if (debug_level) + calcDebug(debug_level, ival_prev, all_ok); + + return all_ok; +} + +void VarBase::calcDebug(int debug_level, long int ival_prev, bool &all_ok) { + if (fval_ > maxval_) + maxval_ = fval_; + if (fval_ < minval_) + minval_ = fval_; + bool todump = false; int nmax = sizeof(long int) * 8; int ns = nmax - nbits_; @@ -57,7 +67,6 @@ bool VarBase::calculate(int debug_level) { all_ok = false; } - val_ = ival_ * K_; float ftest = val_; float tolerance = 0.1 * std::abs(fval_); if (tolerance < 2 * K_) @@ -71,11 +80,8 @@ bool VarBase::calculate(int debug_level) { } all_ok = false; } - if (todump) edm::LogVerbatim("Tracklet") << dump(); - - return all_ok; } void VarFlag::calculate_step() { diff --git a/L1Trigger/TrackFindingTracklet/test/AnalyzerDemonstrator.cc b/L1Trigger/TrackFindingTracklet/test/AnalyzerDemonstrator.cc new file mode 100644 index 0000000000000..8d0e22eb1e089 --- /dev/null +++ b/L1Trigger/TrackFindingTracklet/test/AnalyzerDemonstrator.cc @@ -0,0 +1,193 @@ +#include "FWCore/Framework/interface/one/EDAnalyzer.h" +#include "FWCore/Framework/interface/Run.h" +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/EventSetup.h" +#include "FWCore/Framework/interface/MakerMacros.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/Utilities/interface/EDGetToken.h" +#include "FWCore/Utilities/interface/ESGetToken.h" +#include "FWCore/Utilities/interface/InputTag.h" +#include "FWCore/Utilities/interface/Exception.h" +#include "DataFormats/Common/interface/Handle.h" + +#include "L1Trigger/TrackerTFP/interface/Demonstrator.h" +#include "L1Trigger/TrackFindingTracklet/interface/ChannelAssignment.h" + +#include +#include +#include + +using namespace std; +using namespace edm; +using namespace tt; +using namespace trackerTFP; + +namespace trklet { + + /*! \class trklet::AnalyzerDemonstrator + * \brief Class to demontrate correctness of track trigger emulators + * by comparing FW with SW + * \author Thomas Schuh + * \date 2022, March + */ + class AnalyzerDemonstrator : public one::EDAnalyzer { + public: + AnalyzerDemonstrator(const ParameterSet& iConfig); + void beginJob() override {} + void beginRun(const Run& iEvent, const EventSetup& iSetup) override; + void analyze(const Event& iEvent, const EventSetup& iSetup) override; + void endRun(const Run& iEvent, const EventSetup& iSetup) override {} + void endJob() override; + + private: + // + void convert(const Event& iEvent, + const EDGetTokenT& tokenTracks, + const EDGetTokenT& tokenStubs, + vector>& bits, + bool tbOut) const; + // + template + void convert(const T& collection, vector>& bits) const; + // ED input token of Tracks + EDGetTokenT edGetTokenStubsIn_; + EDGetTokenT edGetTokenStubsOut_; + // ED input token of Stubs + EDGetTokenT edGetTokenTracksIn_; + EDGetTokenT edGetTokenTracksOut_; + // Setup token + ESGetToken esGetTokenSetup_; + // ChannelAssignment token + ESGetToken esGetTokenChannelAssignment_; + // Demonstrator token + ESGetToken esGetTokenDemonstrator_; + // + const Setup* setup_; + // + const ChannelAssignment* channelAssignment_; + // + const Demonstrator* demonstrator_; + // + int nEvents_; + // + int nEventsSuccessful_; + // + pair tbOuts_; + }; + + AnalyzerDemonstrator::AnalyzerDemonstrator(const ParameterSet& iConfig) { + // book in- and output ED products + const string& labelIn = iConfig.getParameter("LabelIn"); + const string& labelOut = iConfig.getParameter("LabelOut"); + const string& branchStubs = iConfig.getParameter("BranchAcceptedStubs"); + const string& branchTracks = iConfig.getParameter("BranchAcceptedTracks"); + edGetTokenStubsIn_ = consumes(InputTag(labelIn, branchStubs)); + if (labelOut != "TrackFindingTrackletProducerKFout") + edGetTokenStubsOut_ = consumes(InputTag(labelOut, branchStubs)); + if (labelIn != "TrackFindingTrackletProducerIRin") + edGetTokenTracksIn_ = consumes(InputTag(labelIn, branchTracks)); + if (labelOut != "TrackFindingTrackletProducerIRin") + edGetTokenTracksOut_ = consumes(InputTag(labelOut, branchTracks)); + tbOuts_ = {labelIn == "TrackFindingTrackletProducerTBout", labelOut == "TrackFindingTrackletProducerTBout"}; + // book ES products + esGetTokenSetup_ = esConsumes(); + esGetTokenChannelAssignment_ = esConsumes(); + esGetTokenDemonstrator_ = esConsumes(); + // initial ES product + setup_ = nullptr; + channelAssignment_ = nullptr; + demonstrator_ = nullptr; + nEvents_ = 0; + nEventsSuccessful_ = 0; + } + + void AnalyzerDemonstrator::beginRun(const Run& iEvent, const EventSetup& iSetup) { + // + setup_ = &iSetup.getData(esGetTokenSetup_); + // + channelAssignment_ = &iSetup.getData(esGetTokenChannelAssignment_); + // + demonstrator_ = &iSetup.getData(esGetTokenDemonstrator_); + } + + void AnalyzerDemonstrator::analyze(const Event& iEvent, const EventSetup& iSetup) { + nEvents_++; + vector> input; + vector> output; + convert(iEvent, edGetTokenTracksIn_, edGetTokenStubsIn_, input, tbOuts_.first); + convert(iEvent, edGetTokenTracksOut_, edGetTokenStubsOut_, output, tbOuts_.second); + if (demonstrator_->analyze(input, output)) + nEventsSuccessful_++; + else + cout << "BitError" << endl; + } + + // + void AnalyzerDemonstrator::convert(const Event& iEvent, + const EDGetTokenT& tokenTracks, + const EDGetTokenT& tokenStubs, + vector>& bits, + bool tbOut) const { + const bool tracks = !tokenTracks.isUninitialized(); + const bool stubs = !tokenStubs.isUninitialized(); + Handle handleStubs; + Handle handleTracks; + int numChannelTracks(0); + if (tracks) { + iEvent.getByToken(tokenTracks, handleTracks); + numChannelTracks = handleTracks->size(); + } + numChannelTracks /= setup_->numRegions(); + int numChannelStubs(0); + vector numChannelsStubs(numChannelTracks, 0); + if (stubs) { + iEvent.getByToken(tokenStubs, handleStubs); + numChannelStubs = handleStubs->size() / setup_->numRegions(); + if (tbOut) { + for (int seed = 0; seed < channelAssignment_->numChannelsTrack(); seed++) + numChannelsStubs[seed] = channelAssignment_->numProjectionLayers(seed); + } else { + const int numChannel = tracks ? numChannelStubs / numChannelTracks : numChannelStubs; + numChannelsStubs = vector(numChannelTracks, numChannel); + } + } + bits.reserve(numChannelTracks + numChannelStubs); + for (int region = 0; region < setup_->numRegions(); region++) { + if (tracks) { + const int offsetTracks = region * numChannelTracks; + for (int channelTracks = 0; channelTracks < numChannelTracks; channelTracks++) { + const int offsetStubs = + region * numChannelStubs + + accumulate(numChannelsStubs.begin(), next(numChannelsStubs.begin(), channelTracks), 0); + convert(handleTracks->at(offsetTracks + channelTracks), bits); + if (stubs) { + for (int channelStubs = 0; channelStubs < numChannelsStubs[channelTracks]; channelStubs++) + convert(handleStubs->at(offsetStubs + channelStubs), bits); + } + } + } else { + const int offsetStubs = region * numChannelStubs; + for (int channelStubs = 0; channelStubs < numChannelStubs; channelStubs++) + convert(handleStubs->at(offsetStubs + channelStubs), bits); + } + } + } + + // + template + void AnalyzerDemonstrator::convert(const T& collection, vector>& bits) const { + bits.emplace_back(); + vector& bvs = bits.back(); + bvs.reserve(collection.size()); + transform(collection.begin(), collection.end(), back_inserter(bvs), [](const auto& frame) { return frame.second; }); + } + + void AnalyzerDemonstrator::endJob() { + stringstream log; + log << "Successrate: " << nEventsSuccessful_ << " / " << nEvents_ << " = " << nEventsSuccessful_ / (double)nEvents_; + LogPrint("L1Trigger/TrackerTFP") << log.str(); + } + +} // namespace trklet + +DEFINE_FWK_MODULE(trklet::AnalyzerDemonstrator); \ No newline at end of file diff --git a/L1Trigger/TrackFindingTracklet/test/AnalyzerKFin.cc b/L1Trigger/TrackFindingTracklet/test/AnalyzerKFin.cc new file mode 100644 index 0000000000000..9b6cd9525a24e --- /dev/null +++ b/L1Trigger/TrackFindingTracklet/test/AnalyzerKFin.cc @@ -0,0 +1,327 @@ +#include "FWCore/Framework/interface/one/EDAnalyzer.h" +#include "FWCore/Framework/interface/Run.h" +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/EventSetup.h" +#include "FWCore/Framework/interface/MakerMacros.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/ServiceRegistry/interface/Service.h" +#include "FWCore/MessageLogger/interface/MessageLogger.h" +#include "FWCore/Utilities/interface/EDGetToken.h" +#include "FWCore/Utilities/interface/InputTag.h" +#include "FWCore/Utilities/interface/Exception.h" +#include "CommonTools/UtilAlgos/interface/TFileService.h" +#include "DataFormats/Common/interface/Handle.h" + +#include "SimTracker/TrackTriggerAssociation/interface/StubAssociation.h" +#include "L1Trigger/TrackTrigger/interface/Setup.h" +#include "L1Trigger/TrackerTFP/interface/DataFormats.h" +#include "L1Trigger/TrackFindingTracklet/interface/ChannelAssignment.h" + +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace edm; +using namespace trackerTFP; +using namespace tt; + +namespace trklet { + + /*! \class trklet::AnalyzerKFin + * \brief Class to analyze hardware like structured TTStub Collection generated by Tracklet + * \author Thomas Schuh + * \date 2020, Nov + */ + class AnalyzerKFin : public one::EDAnalyzer { + public: + AnalyzerKFin(const ParameterSet& iConfig); + void beginJob() override {} + void beginRun(const Run& iEvent, const EventSetup& iSetup) override; + void analyze(const Event& iEvent, const EventSetup& iSetup) override; + void endRun(const Run& iEvent, const EventSetup& iSetup) override {} + void endJob() override; + + private: + // + void formTracks(const StreamsTrack& streamsTrack, + const StreamsStub& streamsStubs, + vector>& tracks, + int channel) const; + // + void associate(const vector>& tracks, + const StubAssociation* ass, + set& tps, + int& sum, + bool perfect = false) const; + + // ED input token of stubs + EDGetTokenT edGetTokenAcceptedStubs_; + // ED input token of tracks + EDGetTokenT edGetTokenAcceptedTracks_; + // ED input token of lost stubs + EDGetTokenT edGetTokenLostStubs_; + // ED input token of lost tracks + EDGetTokenT edGetTokenLostTracks_; + // ED input token of TTStubRef to TPPtr association for tracking efficiency + EDGetTokenT edGetTokenSelection_; + // ED input token of TTStubRef to recontructable TPPtr association + EDGetTokenT edGetTokenReconstructable_; + // Setup token + ESGetToken esGetTokenSetup_; + // DataFormats token + ESGetToken esGetTokenDataFormats_; + // ChannelAssignment token + ESGetToken esGetTokenChannelAssignment_; + // stores, calculates and provides run-time constants + const Setup* setup_; + // helper class to extract structured data from tt::Frames + const DataFormats* dataFormats_; + // helper class to assign tracklet track to channel + const ChannelAssignment* channelAssignment_; + // enables analyze of TPs + bool useMCTruth_; + // + int nEvents_; + + // Histograms + + TProfile* prof_; + TProfile* profChannel_; + TH1F* hisChannel_; + + // printout + stringstream log_; + }; + + AnalyzerKFin::AnalyzerKFin(const ParameterSet& iConfig) + : useMCTruth_(iConfig.getParameter("UseMCTruth")), nEvents_(0) { + usesResource("TFileService"); + // book in- and output ED products + const string& label = iConfig.getParameter("LabelKFin"); + const string& branchAcceptedStubs = iConfig.getParameter("BranchAcceptedStubs"); + const string& branchAcceptedTracks = iConfig.getParameter("BranchAcceptedTracks"); + const string& branchLostStubs = iConfig.getParameter("BranchLostStubs"); + const string& branchLostTracks = iConfig.getParameter("BranchLostTracks"); + edGetTokenAcceptedStubs_ = consumes(InputTag(label, branchAcceptedStubs)); + edGetTokenAcceptedTracks_ = consumes(InputTag(label, branchAcceptedTracks)); + edGetTokenLostStubs_ = consumes(InputTag(label, branchLostStubs)); + edGetTokenLostTracks_ = consumes(InputTag(label, branchLostTracks)); + if (useMCTruth_) { + const auto& inputTagSelecttion = iConfig.getParameter("InputTagSelection"); + const auto& inputTagReconstructable = iConfig.getParameter("InputTagReconstructable"); + edGetTokenSelection_ = consumes(inputTagSelecttion); + edGetTokenReconstructable_ = consumes(inputTagReconstructable); + } + // book ES products + esGetTokenSetup_ = esConsumes(); + esGetTokenDataFormats_ = esConsumes(); + esGetTokenChannelAssignment_ = esConsumes(); + // initial ES products + setup_ = nullptr; + dataFormats_ = nullptr; + channelAssignment_ = nullptr; + // log config + log_.setf(ios::fixed, ios::floatfield); + log_.precision(4); + } + + void AnalyzerKFin::beginRun(const Run& iEvent, const EventSetup& iSetup) { + // helper class to store configurations + setup_ = &iSetup.getData(esGetTokenSetup_); + // helper class to extract structured data from tt::Frames + dataFormats_ = &iSetup.getData(esGetTokenDataFormats_); + // helper class to assign tracklet track to channel + channelAssignment_ = &iSetup.getData(esGetTokenChannelAssignment_); + // book histograms + Service fs; + TFileDirectory dir; + dir = fs->mkdir("KFin"); + prof_ = dir.make("Counts", ";", 10, 0.5, 10.5); + prof_->GetXaxis()->SetBinLabel(1, "Stubs"); + prof_->GetXaxis()->SetBinLabel(2, "Tracks"); + prof_->GetXaxis()->SetBinLabel(3, "Lost Tracks"); + prof_->GetXaxis()->SetBinLabel(4, "Matched Tracks"); + prof_->GetXaxis()->SetBinLabel(5, "All Tracks"); + prof_->GetXaxis()->SetBinLabel(6, "Found TPs"); + prof_->GetXaxis()->SetBinLabel(7, "Found selected TPs"); + prof_->GetXaxis()->SetBinLabel(8, "Lost TPs"); + prof_->GetXaxis()->SetBinLabel(9, "All TPs"); + prof_->GetXaxis()->SetBinLabel(10, "Perfect TPs"); + // channel occupancy + constexpr int maxOcc = 180; + const int numChannels = channelAssignment_->numChannelsTrack() * setup_->numLayers() * setup_->numRegions(); + hisChannel_ = dir.make("His Channel Occupancy", ";", maxOcc, -.5, maxOcc - .5); + profChannel_ = dir.make("Prof Channel Occupancy", ";", numChannels, -.5, numChannels - .5); + } + + void AnalyzerKFin::analyze(const Event& iEvent, const EventSetup& iSetup) { + // read in ht products + Handle handleAcceptedStubs; + iEvent.getByToken(edGetTokenAcceptedStubs_, handleAcceptedStubs); + const StreamsStub& acceptedStubs = *handleAcceptedStubs; + Handle handleAcceptedTracks; + iEvent.getByToken(edGetTokenAcceptedTracks_, handleAcceptedTracks); + const StreamsTrack& acceptedTracks = *handleAcceptedTracks; + Handle handleLostStubs; + iEvent.getByToken(edGetTokenLostStubs_, handleLostStubs); + const StreamsStub& lostStubs = *handleLostStubs; + Handle handleLostTracks; + iEvent.getByToken(edGetTokenLostTracks_, handleLostTracks); + const StreamsTrack& lostTracks = *handleLostTracks; + // read in MCTruth + const StubAssociation* selection = nullptr; + const StubAssociation* reconstructable = nullptr; + if (useMCTruth_) { + Handle handleSelection; + iEvent.getByToken(edGetTokenSelection_, handleSelection); + selection = handleSelection.product(); + prof_->Fill(9, selection->numTPs()); + Handle handleReconstructable; + iEvent.getByToken(edGetTokenReconstructable_, handleReconstructable); + reconstructable = handleReconstructable.product(); + } + // analyze ht products and associate found tracks with reconstrucable TrackingParticles + set tpPtrs; + set tpPtrsSelection; + set tpPtrsPerfect; + set tpPtrsLost; + int allMatched(0); + int allTracks(0); + for (int region = 0; region < setup_->numRegions(); region++) { + const int offset = region * channelAssignment_->numChannelsTrack(); + int nStubs(0); + int nTracks(0); + int nLost(0); + for (int channel = 0; channel < channelAssignment_->numChannelsTrack(); channel++) { + vector> tracks; + formTracks(acceptedTracks, acceptedStubs, tracks, offset + channel); + vector> lost; + formTracks(lostTracks, lostStubs, lost, offset + channel); + nTracks += tracks.size(); + nStubs += accumulate(tracks.begin(), tracks.end(), 0, [](int& sum, const vector& track) { + return sum += (int)track.size(); + }); + nLost += lost.size(); + allTracks += tracks.size(); + if (!useMCTruth_) + continue; + int tmp(0); + associate(tracks, selection, tpPtrsSelection, tmp); + associate(tracks, selection, tpPtrsPerfect, tmp, true); + associate(lost, selection, tpPtrsLost, tmp); + associate(tracks, reconstructable, tpPtrs, allMatched); + } + prof_->Fill(1, nStubs); + prof_->Fill(2, nTracks); + prof_->Fill(3, nLost); + } + vector recovered; + recovered.reserve(tpPtrsLost.size()); + set_intersection(tpPtrsLost.begin(), tpPtrsLost.end(), tpPtrs.begin(), tpPtrs.end(), back_inserter(recovered)); + for (const TPPtr& tpPtr : recovered) + tpPtrsLost.erase(tpPtr); + prof_->Fill(4, allMatched); + prof_->Fill(5, allTracks); + prof_->Fill(6, tpPtrs.size()); + prof_->Fill(7, tpPtrsSelection.size()); + prof_->Fill(8, tpPtrsLost.size()); + prof_->Fill(10, tpPtrsPerfect.size()); + nEvents_++; + } + + void AnalyzerKFin::endJob() { + if (nEvents_ == 0) + return; + // printout SF summary + const double totalTPs = prof_->GetBinContent(9); + const double numStubs = prof_->GetBinContent(1); + const double numTracks = prof_->GetBinContent(2); + const double numTracksLost = prof_->GetBinContent(3); + const double totalTracks = prof_->GetBinContent(5); + const double numTracksMatched = prof_->GetBinContent(4); + const double numTPsAll = prof_->GetBinContent(6); + const double numTPsEff = prof_->GetBinContent(7); + const double numTPsLost = prof_->GetBinContent(8); + const double numTPsEffPerfect = prof_->GetBinContent(10); + const double errStubs = prof_->GetBinError(1); + const double errTracks = prof_->GetBinError(2); + const double errTracksLost = prof_->GetBinError(3); + const double fracFake = (totalTracks - numTracksMatched) / totalTracks; + const double fracDup = (numTracksMatched - numTPsAll) / totalTracks; + const double eff = numTPsEff / totalTPs; + const double errEff = sqrt(eff * (1. - eff) / totalTPs / nEvents_); + const double effLoss = numTPsLost / totalTPs; + const double errEffLoss = sqrt(effLoss * (1. - effLoss) / totalTPs / nEvents_); + const double effPerfect = numTPsEffPerfect / totalTPs; + const double errEffPerfect = sqrt(effPerfect * (1. - effPerfect) / totalTPs / nEvents_); + const vector nums = {numStubs, numTracks, numTracksLost}; + const vector errs = {errStubs, errTracks, errTracksLost}; + const int wNums = ceil(log10(*max_element(nums.begin(), nums.end()))) + 5; + const int wErrs = ceil(log10(*max_element(errs.begin(), errs.end()))) + 5; + log_ << " KFin SUMMARY " << endl; + log_ << "number of stubs per TFP = " << setw(wNums) << numStubs << " +- " << setw(wErrs) << errStubs << endl; + log_ << "number of tracks per TFP = " << setw(wNums) << numTracks << " +- " << setw(wErrs) << errTracks + << endl; + log_ << "number of lost tracks per TFP = " << setw(wNums) << numTracksLost << " +- " << setw(wErrs) << errTracksLost + << endl; + log_ << " current tracking efficiency = " << setw(wNums) << effPerfect << " +- " << setw(wErrs) << errEffPerfect + << endl; + log_ << " max tracking efficiency = " << setw(wNums) << eff << " +- " << setw(wErrs) << errEff << endl; + log_ << " lost tracking efficiency = " << setw(wNums) << effLoss << " +- " << setw(wErrs) << errEffLoss << endl; + log_ << " fake rate = " << setw(wNums) << fracFake << endl; + log_ << " duplicate rate = " << setw(wNums) << fracDup << endl; + log_ << "============================================================="; + LogPrint("L1Trigger/TrackerTFP") << log_.str(); + } + + // + void AnalyzerKFin::formTracks(const StreamsTrack& streamsTrack, + const StreamsStub& streamsStubs, + vector>& tracks, + int channel) const { + const int offset = channel * setup_->numLayers(); + const StreamTrack& streamTrack = streamsTrack[channel]; + const int numTracks = accumulate(streamTrack.begin(), streamTrack.end(), 0, [](int& sum, const FrameTrack& frame) { + return sum += (frame.first.isNonnull() ? 1 : 0); + }); + tracks.reserve(numTracks); + for (int frame = 0; frame < (int)streamTrack.size(); frame++) { + const FrameTrack& frameTrack = streamTrack[frame]; + if (frameTrack.first.isNull()) + continue; + vector ttStubRefs; + ttStubRefs.reserve(setup_->numLayers()); + for (int layer = 0; layer < setup_->numLayers(); layer++) { + const FrameStub& stub = streamsStubs[offset + layer][frame]; + if (stub.first.isNonnull()) + ttStubRefs.push_back(stub.first); + } + tracks.push_back(ttStubRefs); + } + } + + // + void AnalyzerKFin::associate(const vector>& tracks, + const StubAssociation* ass, + set& tps, + int& sum, + bool perfect) const { + for (const vector& ttStubRefs : tracks) { + const vector& tpPtrs = perfect ? ass->associateFinal(ttStubRefs) : ass->associate(ttStubRefs); + if (tpPtrs.empty()) + continue; + sum++; + copy(tpPtrs.begin(), tpPtrs.end(), inserter(tps, tps.begin())); + } + } + +} // namespace trklet + +DEFINE_FWK_MODULE(trklet::AnalyzerKFin); \ No newline at end of file diff --git a/L1Trigger/TrackFindingTracklet/test/AnalyzerKFout.cc b/L1Trigger/TrackFindingTracklet/test/AnalyzerKFout.cc new file mode 100644 index 0000000000000..b56cdb3f43c80 --- /dev/null +++ b/L1Trigger/TrackFindingTracklet/test/AnalyzerKFout.cc @@ -0,0 +1,257 @@ +#include "FWCore/Framework/interface/one/EDAnalyzer.h" +#include "FWCore/Framework/interface/Run.h" +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/EventSetup.h" +#include "FWCore/Framework/interface/MakerMacros.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/ServiceRegistry/interface/Service.h" +#include "FWCore/MessageLogger/interface/MessageLogger.h" +#include "FWCore/Utilities/interface/EDGetToken.h" +#include "FWCore/Utilities/interface/InputTag.h" +#include "FWCore/Utilities/interface/Exception.h" +#include "CommonTools/UtilAlgos/interface/TFileService.h" +#include "DataFormats/Common/interface/Handle.h" + +#include "SimTracker/TrackTriggerAssociation/interface/StubAssociation.h" +#include "L1Trigger/TrackTrigger/interface/Setup.h" +#include "L1Trigger/TrackerTFP/interface/DataFormats.h" +#include "L1Trigger/TrackerTFP/interface/LayerEncoding.h" +#include "L1Trigger/TrackerTFP/interface/KalmanFilterFormats.h" + +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace edm; +using namespace tt; +using namespace trackerTFP; + +namespace trklet { + + /*! \class trklet::AnalyzerKFout + * \brief Class to analyze hardware like structured Track Collection generated by Kalman Filter output module + * \author Thomas Schuh + * \date 2021, Aug + */ + class AnalyzerKFout : public one::EDAnalyzer { + public: + AnalyzerKFout(const ParameterSet& iConfig); + void beginJob() override {} + void beginRun(const Run& iEvent, const EventSetup& iSetup) override; + void analyze(const Event& iEvent, const EventSetup& iSetup) override; + void endRun(const Run& iEvent, const EventSetup& iSetup) override {} + void endJob() override; + + private: + // + void associate(const set& ttTracks, const StubAssociation* ass, set& tps, int& sum) const; + + // ED input token of accepted Stubs + EDGetTokenT edGetTokenAccepted_; + // ED input token of lost Tracks + EDGetTokenT edGetTokenLost_; + // ED input token of TTStubRef to TPPtr association for tracking efficiency + EDGetTokenT edGetTokenSelection_; + // ED input token of TTStubRef to recontructable TPPtr association + EDGetTokenT edGetTokenReconstructable_; + // Setup token + ESGetToken esGetTokenSetup_; + // DataFormats token + ESGetToken esGetTokenDataFormats_; + // stores, calculates and provides run-time constants + const Setup* setup_; + // enables analyze of TPs + bool useMCTruth_; + // + int nEvents_; + + // Histograms + + TProfile* prof_; + TProfile* profChannel_; + TH1F* hisChannel_; + + // printout + stringstream log_; + }; + + AnalyzerKFout::AnalyzerKFout(const ParameterSet& iConfig) + : useMCTruth_(iConfig.getParameter("UseMCTruth")), nEvents_(0) { + usesResource("TFileService"); + // book in- and output ED products + const string& label = iConfig.getParameter("LabelKFout"); + const string& branchAccepted = iConfig.getParameter("BranchAcceptedTracks"); + const string& branchLost = iConfig.getParameter("BranchLostTracks"); + edGetTokenAccepted_ = consumes(InputTag(label, branchAccepted)); + edGetTokenLost_ = consumes(InputTag(label, branchLost)); + if (useMCTruth_) { + const auto& inputTagSelecttion = iConfig.getParameter("InputTagSelection"); + const auto& inputTagReconstructable = iConfig.getParameter("InputTagReconstructable"); + edGetTokenSelection_ = consumes(inputTagSelecttion); + edGetTokenReconstructable_ = consumes(inputTagReconstructable); + } + // book ES products + esGetTokenSetup_ = esConsumes(); + // initial ES products + setup_ = nullptr; + // log config + log_.setf(ios::fixed, ios::floatfield); + log_.precision(4); + } + + void AnalyzerKFout::beginRun(const Run& iEvent, const EventSetup& iSetup) { + // helper class to store configurations + setup_ = &iSetup.getData(esGetTokenSetup_); + // book histograms + Service fs; + TFileDirectory dir; + dir = fs->mkdir("KFout"); + prof_ = dir.make("Counts", ";", 9, 0.5, 9.5); + prof_->GetXaxis()->SetBinLabel(1, "Stubs"); + prof_->GetXaxis()->SetBinLabel(2, "Tracks"); + prof_->GetXaxis()->SetBinLabel(3, "Lost Tracks"); + prof_->GetXaxis()->SetBinLabel(4, "Matched Tracks"); + prof_->GetXaxis()->SetBinLabel(5, "All Tracks"); + prof_->GetXaxis()->SetBinLabel(6, "Found TPs"); + prof_->GetXaxis()->SetBinLabel(7, "Found selected TPs"); + prof_->GetXaxis()->SetBinLabel(8, "Lost TPs"); + prof_->GetXaxis()->SetBinLabel(9, "All TPs"); + // channel occupancy + constexpr int maxOcc = 180; + const int numChannels = setup_->tfpNumChannel(); + hisChannel_ = dir.make("His Channel Occupancy", ";", maxOcc, -.5, maxOcc - .5); + profChannel_ = dir.make("Prof Channel Occupancy", ";", numChannels, -.5, numChannels - .5); + } + + void AnalyzerKFout::analyze(const Event& iEvent, const EventSetup& iSetup) { + // read in kf products + Handle handleAccepted; + iEvent.getByToken(edGetTokenAccepted_, handleAccepted); + Handle handleLost; + iEvent.getByToken(edGetTokenLost_, handleLost); + // read in MCTruth + const StubAssociation* selection = nullptr; + const StubAssociation* reconstructable = nullptr; + if (useMCTruth_) { + Handle handleSelection; + iEvent.getByToken(edGetTokenSelection_, handleSelection); + selection = handleSelection.product(); + prof_->Fill(9, selection->numTPs()); + Handle handleReconstructable; + iEvent.getByToken(edGetTokenReconstructable_, handleReconstructable); + reconstructable = handleReconstructable.product(); + } + // analyze kfout products and associate found tracks with reconstrucable TrackingParticles + set tpPtrs; + set tpPtrsSelection; + set tpPtrsLost; + int allMatched(0); + int allTracks(0); + for (int region = 0; region < setup_->numRegions(); region++) { + int nStubsRegion(0); + int nTracksRegion(0); + int nLostRegion(0); + for (int channel = 0; channel < setup_->tfpNumChannel(); channel++) { + const int index = region * setup_->tfpNumChannel() + channel; + const StreamTrack& accepted = handleAccepted->at(index); + const StreamTrack& lost = handleLost->at(index); + hisChannel_->Fill(accepted.size()); + profChannel_->Fill(channel, accepted.size()); + set tracks; + for (const FrameTrack& frame : accepted) + if (frame.first.isNonnull()) + tracks.insert(frame.first); + nTracksRegion += tracks.size(); + nStubsRegion += accumulate(tracks.begin(), tracks.end(), 0, [](int& sum, const TTTrackRef& ttTrackRef) { + return sum += (int)ttTrackRef->getStubRefs().size(); + }); + set tracksLost; + for (const FrameTrack& frame : lost) + if (frame.first.isNonnull()) + tracksLost.insert(frame.first); + nLostRegion += tracksLost.size(); + allTracks += tracks.size(); + int tmp(0); + associate(tracks, selection, tpPtrsSelection, tmp); + associate(tracksLost, selection, tpPtrsLost, tmp); + associate(tracks, reconstructable, tpPtrs, allMatched); + } + prof_->Fill(1, nStubsRegion); + prof_->Fill(2, nTracksRegion); + prof_->Fill(3, nLostRegion); + } + deque tpPtrsRealLost; + set_difference(tpPtrsLost.begin(), tpPtrsLost.end(), tpPtrs.begin(), tpPtrs.end(), back_inserter(tpPtrsRealLost)); + prof_->Fill(4, allMatched); + prof_->Fill(5, allTracks); + prof_->Fill(6, tpPtrs.size()); + prof_->Fill(7, tpPtrsSelection.size()); + prof_->Fill(8, tpPtrsRealLost.size()); + nEvents_++; + } + + void AnalyzerKFout::endJob() { + if (nEvents_ == 0) + return; + // printout SF summary + const double totalTPs = prof_->GetBinContent(9); + const double numStubs = prof_->GetBinContent(1); + const double numTracks = prof_->GetBinContent(2); + const double numTracksLost = prof_->GetBinContent(3); + const double totalTracks = prof_->GetBinContent(5); + const double numTracksMatched = prof_->GetBinContent(4); + const double numTPsAll = prof_->GetBinContent(6); + const double numTPsEff = prof_->GetBinContent(7); + const double numTPsLost = prof_->GetBinContent(8); + const double errStubs = prof_->GetBinError(1); + const double errTracks = prof_->GetBinError(2); + const double errTracksLost = prof_->GetBinError(3); + const double fracFake = (totalTracks - numTracksMatched) / totalTracks; + const double fracDup = (numTracksMatched - numTPsAll) / totalTracks; + const double eff = numTPsEff / totalTPs; + const double errEff = sqrt(eff * (1. - eff) / totalTPs / nEvents_); + const double effLoss = numTPsLost / totalTPs; + const double errEffLoss = sqrt(effLoss * (1. - effLoss) / totalTPs / nEvents_); + const vector nums = {numStubs, numTracks, numTracksLost}; + const vector errs = {errStubs, errTracks, errTracksLost}; + const int wNums = ceil(log10(*max_element(nums.begin(), nums.end()))) + 5; + const int wErrs = ceil(log10(*max_element(errs.begin(), errs.end()))) + 5; + log_ << " KFout SUMMARY " << endl; + //log_ << "number of stubs per TFP = " << setw(wNums) << numStubs << " +- " << setw(wErrs) << errStubs << endl; + log_ << "number of tracks per TFP = " << setw(wNums) << numTracks << " +- " << setw(wErrs) << errTracks + << endl; + log_ << "number of lost tracks per TFP = " << setw(wNums) << numTracksLost << " +- " << setw(wErrs) << errTracksLost + << endl; + log_ << " tracking efficiency = " << setw(wNums) << eff << " +- " << setw(wErrs) << errEff << endl; + log_ << " lost tracking efficiency = " << setw(wNums) << effLoss << " +- " << setw(wErrs) << errEffLoss << endl; + log_ << " fake rate = " << setw(wNums) << fracFake << endl; + log_ << " duplicate rate = " << setw(wNums) << fracDup << endl; + log_ << "============================================================="; + LogPrint("L1Trigger/TrackerTFP") << log_.str(); + } + + // + void AnalyzerKFout::associate(const set& ttTracks, + const StubAssociation* ass, + set& tps, + int& sum) const { + for (const TTTrackRef& ttTrack : ttTracks) { + const vector& ttStubRefs = ttTrack->getStubRefs(); + const vector& tpPtrs = ass->associate(ttStubRefs); + if (tpPtrs.empty()) + continue; + sum++; + copy(tpPtrs.begin(), tpPtrs.end(), inserter(tps, tps.begin())); + } + } + +} // namespace trklet + +DEFINE_FWK_MODULE(trklet::AnalyzerKFout); \ No newline at end of file diff --git a/L1Trigger/TrackFindingTracklet/test/AnalyzerTBout.cc b/L1Trigger/TrackFindingTracklet/test/AnalyzerTBout.cc new file mode 100644 index 0000000000000..c7510f6599973 --- /dev/null +++ b/L1Trigger/TrackFindingTracklet/test/AnalyzerTBout.cc @@ -0,0 +1,451 @@ +#include "FWCore/Framework/interface/one/EDAnalyzer.h" +#include "FWCore/Framework/interface/Run.h" +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/EventSetup.h" +#include "FWCore/Framework/interface/MakerMacros.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/ServiceRegistry/interface/Service.h" +#include "FWCore/MessageLogger/interface/MessageLogger.h" +#include "FWCore/Utilities/interface/EDGetToken.h" +#include "FWCore/Utilities/interface/InputTag.h" +#include "FWCore/Utilities/interface/Exception.h" +#include "CommonTools/UtilAlgos/interface/TFileService.h" +#include "DataFormats/Common/interface/Handle.h" + +#include "SimTracker/TrackTriggerAssociation/interface/StubAssociation.h" +#include "L1Trigger/TrackTrigger/interface/Setup.h" +#include "L1Trigger/TrackerTFP/interface/DataFormats.h" +#include "L1Trigger/TrackFindingTracklet/interface/ChannelAssignment.h" +#include "L1Trigger/TrackFindingTracklet/interface/Settings.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace edm; +using namespace trackerTFP; +using namespace tt; + +namespace trklet { + + // stub resolution plots helper + enum Resolution { Phi, Z, NumResolution }; + constexpr initializer_list AllResolution = {Phi, Z}; + constexpr auto NameResolution = {"Phi", "Z"}; + inline string name(Resolution r) { return string(*(NameResolution.begin() + r)); } + + /*! \class trklet::AnalyzerTBout + * \brief Class to analyze hardware like structured TTStub Collection generated by Tracklet + * \author Thomas Schuh + * \date 2021, Nov + */ + class AnalyzerTBout : public one::EDAnalyzer { + public: + AnalyzerTBout(const ParameterSet& iConfig); + void beginJob() override {} + void beginRun(const Run& iEvent, const EventSetup& iSetup) override; + void analyze(const Event& iEvent, const EventSetup& iSetup) override; + void endRun(const Run& iEvent, const EventSetup& iSetup) override {} + void endJob() override; + + private: + // + void formTracks(const StreamsTrack& streamsTrack, + const StreamsStub& streamsStubs, + vector>& tracks, + int channel); + // + void associate(const vector>& tracks, const StubAssociation* ass, set& tps, int& sum) const; + // + void fill(const FrameTrack& frameTrack, const FrameStub& frameStub); + + // ED input token of dtc stubs + EDGetTokenT edGetTokenTTDTC_; + // ED input token of stubs + EDGetTokenT edGetTokenAcceptedStubs_; + // ED input token of tracks + EDGetTokenT edGetTokenAcceptedTracks_; + // ED input token of lost stubs + EDGetTokenT edGetTokenLostStubs_; + // ED input token of lost tracks + EDGetTokenT edGetTokenLostTracks_; + // ED input token of TTStubRef to TPPtr association for tracking efficiency + EDGetTokenT edGetTokenSelection_; + // ED input token of TTStubRef to recontructable TPPtr association + EDGetTokenT edGetTokenReconstructable_; + // Setup token + ESGetToken esGetTokenSetup_; + // DataFormats token + ESGetToken esGetTokenDataFormats_; + // ChannelAssignment token + ESGetToken esGetTokenChannelAssignment_; + // stores, calculates and provides run-time constants + const Setup* setup_; + // + const Settings settings_; + // helper class to extract structured data from tt::Frames + const DataFormats* dataFormats_; + // helper class to assign tracklet track to channel + const ChannelAssignment* channelAssignment_; + // enables analyze of TPs + bool useMCTruth_; + // + int nEvents_; + // + vector> regionStubs_; + // + int region_; + // + vector nOverflows_; + + // Histograms + + TProfile* prof_; + TProfile* profChannel_; + TH1F* hisChannel_; + vector hisResolution_; + vector profResolution_; + vector hisResolutionMe_; + vector hisResolutionThey_; + vector his2Resolution_; + + // printout + stringstream log_; + }; + + AnalyzerTBout::AnalyzerTBout(const ParameterSet& iConfig) + : settings_(), useMCTruth_(iConfig.getParameter("UseMCTruth")), nEvents_(0) { + usesResource("TFileService"); + // book in- and output ED products + const InputTag& inputTag = iConfig.getParameter("InputTagDTC"); + const string& label = iConfig.getParameter("LabelTBout"); + const string& branchAcceptedStubs = iConfig.getParameter("BranchAcceptedStubs"); + const string& branchAcceptedTracks = iConfig.getParameter("BranchAcceptedTracks"); + const string& branchLostStubs = iConfig.getParameter("BranchLostStubs"); + const string& branchLostTracks = iConfig.getParameter("BranchLostTracks"); + edGetTokenTTDTC_ = consumes(inputTag); + edGetTokenAcceptedStubs_ = consumes(InputTag(label, branchAcceptedStubs)); + edGetTokenAcceptedTracks_ = consumes(InputTag(label, branchAcceptedTracks)); + edGetTokenLostStubs_ = consumes(InputTag(label, branchLostStubs)); + edGetTokenLostTracks_ = consumes(InputTag(label, branchLostTracks)); + if (useMCTruth_) { + const auto& inputTagSelecttion = iConfig.getParameter("InputTagSelection"); + const auto& inputTagReconstructable = iConfig.getParameter("InputTagReconstructable"); + edGetTokenSelection_ = consumes(inputTagSelecttion); + edGetTokenReconstructable_ = consumes(inputTagReconstructable); + } + // book ES products + esGetTokenSetup_ = esConsumes(); + esGetTokenDataFormats_ = esConsumes(); + esGetTokenChannelAssignment_ = esConsumes(); + // initial ES products + setup_ = nullptr; + dataFormats_ = nullptr; + channelAssignment_ = nullptr; + // + nOverflows_ = vector(2, 0); + // log config + log_.setf(ios::fixed, ios::floatfield); + log_.precision(4); + } + + void AnalyzerTBout::beginRun(const Run& iEvent, const EventSetup& iSetup) { + // helper class to store configurations + setup_ = &iSetup.getData(esGetTokenSetup_); + // helper class to extract structured data from tt::Frames + dataFormats_ = &iSetup.getData(esGetTokenDataFormats_); + // helper class to assign tracklet track to channel + channelAssignment_ = &iSetup.getData(esGetTokenChannelAssignment_); + // book histograms + Service fs; + TFileDirectory dir; + dir = fs->mkdir("TBout"); + prof_ = dir.make("Counts", ";", 9, 0.5, 9.5); + prof_->GetXaxis()->SetBinLabel(1, "Stubs"); + prof_->GetXaxis()->SetBinLabel(2, "Tracks"); + prof_->GetXaxis()->SetBinLabel(3, "Lost Tracks"); + prof_->GetXaxis()->SetBinLabel(4, "Matched Tracks"); + prof_->GetXaxis()->SetBinLabel(5, "All Tracks"); + prof_->GetXaxis()->SetBinLabel(6, "Found TPs"); + prof_->GetXaxis()->SetBinLabel(7, "Found selected TPs"); + prof_->GetXaxis()->SetBinLabel(8, "Lost TPs"); + prof_->GetXaxis()->SetBinLabel(9, "All TPs"); + // channel occupancy + constexpr int maxOcc = 180; + const int numChannels = channelAssignment_->numChannelsStub() * setup_->numRegions(); + hisChannel_ = dir.make("His Channel Occupancy", ";", maxOcc, -.5, maxOcc - .5); + profChannel_ = dir.make("Prof Channel Occupancy", ";", numChannels, -.5, numChannels - .5); + // stub parameter resolutions + constexpr int bins = 400; + constexpr int binsHis = 100; + constexpr double maxZ = 300.; + constexpr double maxR = 120.; + constexpr array ranges{{.01, 5.}}; + hisResolution_.reserve(NumResolution); + profResolution_.reserve(NumResolution); + for (Resolution r : AllResolution) { + hisResolution_.emplace_back(dir.make(("HisRes" + name(r)).c_str(), ";", binsHis, -ranges[r], ranges[r])); + profResolution_.emplace_back( + dir.make(("ProfRes" + name(r)).c_str(), ";;", bins, -maxZ, maxZ, bins, 0., maxR)); + hisResolutionMe_.emplace_back( + dir.make(("HisResMe" + name(r)).c_str(), ";", binsHis, -ranges[r], ranges[r])); + hisResolutionThey_.emplace_back( + dir.make(("HisResThey" + name(r)).c_str(), ";", binsHis, -ranges[r], ranges[r])); + his2Resolution_.emplace_back( + dir.make(("His2" + name(r)).c_str(), ";;", bins, -ranges[r], ranges[r], bins, -ranges[r], ranges[r])); + } + regionStubs_ = vector>(setup_->numRegions()); + } + + void AnalyzerTBout::analyze(const Event& iEvent, const EventSetup& iSetup) { + // read in TTDTC + Handle handleTTDTC; + iEvent.getByToken(edGetTokenTTDTC_, handleTTDTC); + const TTDTC& ttDTC = *handleTTDTC; + for (deque& region : regionStubs_) + region.clear(); + for (int r : ttDTC.tfpRegions()) { + for (int c : ttDTC.tfpChannels()) { + const StreamStub& s = ttDTC.stream(r, c); + copy_if( + s.begin(), s.end(), back_inserter(regionStubs_[r]), [](const FrameStub& f) { return f.first.isNonnull(); }); + } + } + // read in TBout products + Handle handleAcceptedStubs; + iEvent.getByToken(edGetTokenAcceptedStubs_, handleAcceptedStubs); + const StreamsStub& acceptedStubs = *handleAcceptedStubs; + Handle handleAcceptedTracks; + iEvent.getByToken(edGetTokenAcceptedTracks_, handleAcceptedTracks); + const StreamsTrack& acceptedTracks = *handleAcceptedTracks; + Handle handleLostStubs; + iEvent.getByToken(edGetTokenLostStubs_, handleLostStubs); + const StreamsStub& lostStubs = *handleLostStubs; + Handle handleLostTracks; + iEvent.getByToken(edGetTokenLostTracks_, handleLostTracks); + const StreamsTrack& lostTracks = *handleLostTracks; + // read in MCTruth + const StubAssociation* selection = nullptr; + const StubAssociation* reconstructable = nullptr; + if (useMCTruth_) { + Handle handleSelection; + iEvent.getByToken(edGetTokenSelection_, handleSelection); + selection = handleSelection.product(); + prof_->Fill(9, selection->numTPs()); + Handle handleReconstructable; + iEvent.getByToken(edGetTokenReconstructable_, handleReconstructable); + reconstructable = handleReconstructable.product(); + } + // analyze ht products and associate found tracks with reconstrucable TrackingParticles + set tpPtrs; + set tpPtrsSelection; + set tpPtrsLost; + int allMatched(0); + int allTracks(0); + for (region_ = 0; region_ < setup_->numRegions(); region_++) { + const int offset = region_ * channelAssignment_->numChannelsTrack(); + int nStubs(0); + int nTracks(0); + int nLost(0); + for (int channel = 0; channel < channelAssignment_->numChannelsTrack(); channel++) { + vector> tracks; + formTracks(acceptedTracks, acceptedStubs, tracks, offset + channel); + vector> lost; + formTracks(lostTracks, lostStubs, lost, offset + channel); + nTracks += tracks.size(); + nStubs += + accumulate(tracks.begin(), tracks.end(), 0, [](int& sum, const auto& v) { return sum += (int)v.size(); }); + nLost += lost.size(); + allTracks += tracks.size(); + if (!useMCTruth_) + continue; + int tmp(0); + associate(tracks, selection, tpPtrsSelection, tmp); + associate(lost, selection, tpPtrsLost, tmp); + associate(tracks, reconstructable, tpPtrs, allMatched); + } + prof_->Fill(1, nStubs); + prof_->Fill(2, nTracks); + prof_->Fill(3, nLost); + } + vector recovered; + recovered.reserve(tpPtrsLost.size()); + set_intersection(tpPtrsLost.begin(), tpPtrsLost.end(), tpPtrs.begin(), tpPtrs.end(), back_inserter(recovered)); + for (const TPPtr& tpPtr : recovered) + tpPtrsLost.erase(tpPtr); + prof_->Fill(4, allMatched); + prof_->Fill(5, allTracks); + prof_->Fill(6, tpPtrs.size()); + prof_->Fill(7, tpPtrsSelection.size()); + prof_->Fill(8, tpPtrsLost.size()); + nEvents_++; + } + + void AnalyzerTBout::endJob() { + if (nEvents_ == 0) + return; + // printout TBout summary + const double totalTPs = prof_->GetBinContent(9); + const double numStubs = prof_->GetBinContent(1); + const double numTracks = prof_->GetBinContent(2); + const double numTracksLost = prof_->GetBinContent(3); + const double totalTracks = prof_->GetBinContent(5); + const double numTracksMatched = prof_->GetBinContent(4); + const double numTPsAll = prof_->GetBinContent(6); + const double numTPsEff = prof_->GetBinContent(7); + const double numTPsLost = prof_->GetBinContent(8); + const double errStubs = prof_->GetBinError(1); + const double errTracks = prof_->GetBinError(2); + const double errTracksLost = prof_->GetBinError(3); + const double fracFake = (totalTracks - numTracksMatched) / totalTracks; + const double fracDup = (numTracksMatched - numTPsAll) / totalTracks; + const double eff = numTPsEff / totalTPs; + const double errEff = sqrt(eff * (1. - eff) / totalTPs / nEvents_); + const double effLoss = numTPsLost / totalTPs; + const double errEffLoss = sqrt(effLoss * (1. - effLoss) / totalTPs / nEvents_); + const vector nums = {numStubs, numTracks, numTracksLost}; + const vector errs = {errStubs, errTracks, errTracksLost}; + const int wNums = ceil(log10(*max_element(nums.begin(), nums.end()))) + 5; + const int wErrs = ceil(log10(*max_element(errs.begin(), errs.end()))) + 5; + log_ << " TBout SUMMARY " << endl; + log_ << "number of stubs per TFP = " << setw(wNums) << numStubs << " +- " << setw(wErrs) << errStubs << endl; + log_ << "number of tracks per TFP = " << setw(wNums) << numTracks << " +- " << setw(wErrs) << errTracks + << endl; + log_ << "number of lost tracks per TFP = " << setw(wNums) << numTracksLost << " +- " << setw(wErrs) << errTracksLost + << endl; + log_ << " max tracking efficiency = " << setw(wNums) << eff << " +- " << setw(wErrs) << errEff << endl; + log_ << " lost tracking efficiency = " << setw(wNums) << effLoss << " +- " << setw(wErrs) << errEffLoss << endl; + log_ << " fake rate = " << setw(wNums) << fracFake << endl; + log_ << " duplicate rate = " << setw(wNums) << fracDup << endl; + log_ << "number of overflowed phi residuals: " << nOverflows_[0] << " and z: " << nOverflows_[1] << endl; + log_ << "============================================================="; + LogPrint("L1Trigger/TrackerTFP") << log_.str(); + } + + // + void AnalyzerTBout::formTracks(const StreamsTrack& streamsTrack, + const StreamsStub& streamsStubs, + vector>& tracks, + int channel) { + const int seedType = channel % channelAssignment_->numChannelsTrack(); + const int offset = channelAssignment_->offsetStub(channel); + const StreamTrack& streamTrack = streamsTrack[channel]; + const int numTracks = accumulate(streamTrack.begin(), streamTrack.end(), 0, [](int& sum, const FrameTrack& frame) { + return sum += (frame.first.isNonnull() ? 1 : 0); + }); + tracks.reserve(numTracks); + for (int frame = 0; frame < (int)streamTrack.size(); frame++) { + const FrameTrack& frameTrack = streamTrack[frame]; + if (frameTrack.first.isNull()) + continue; + vector ttStubRefs; + ttStubRefs.reserve(channelAssignment_->numProjectionLayers(seedType) + + channelAssignment_->seedingLayers(seedType).size()); + for (int layer = 0; layer < channelAssignment_->numProjectionLayers(seedType); layer++) { + const FrameStub& stub = streamsStubs[offset + layer][frame]; + if (stub.first.isNonnull()) { + this->fill(frameTrack, stub); + ttStubRefs.push_back(stub.first); + } + } + for (const TTStubRef& ttStubRef : frameTrack.first->getStubRefs()) { + int layer(0); + if (!channelAssignment_->layerId(seedType, ttStubRef, layer)) + ttStubRefs.push_back(ttStubRef); + } + tracks.push_back(ttStubRefs); + } + } + + // + void AnalyzerTBout::associate(const vector>& tracks, + const StubAssociation* ass, + set& tps, + int& sum) const { + for (const vector& ttStubRefs : tracks) { + const vector& tpPtrs = ass->associate(ttStubRefs); + if (tpPtrs.empty()) + continue; + sum++; + copy(tpPtrs.begin(), tpPtrs.end(), inserter(tps, tps.begin())); + } + } + + // + void AnalyzerTBout::fill(const FrameTrack& frameTrack, const FrameStub& frameStub) { + // get dtc stub frame + const deque& region = regionStubs_[region_]; + const auto it = + find_if(region.begin(), region.end(), [&frameStub](const FrameStub& f) { return f.first == frameStub.first; }); + if (it == region.end()) + throw cms::Exception("LgociError.") << "Stub on track was not in DTC collection."; + const GlobalPoint ttPos = setup_->stubPos(frameStub.first); + const GlobalPoint pos = setup_->stubPos(true, *it, region_); + static constexpr int widthPhi = 12; + static constexpr int widthZ = 9; + static constexpr int widthR = 7; + const bool barrel = setup_->barrel(frameStub.first); + const int layerIdTracklet = channelAssignment_->trackletLayerId(frameStub.first); + static const double baseR = settings_.kz(); + const double basePhi = barrel ? settings_.kphi1() : settings_.kphi(layerIdTracklet); + const double baseZ = settings_.kz(layerIdTracklet); + static const double baseInvR = settings_.kphi1() / settings_.kr() * pow(2, settings_.rinv_shift()); + static const double basePhi0 = settings_.kphi1() * pow(2, settings_.phi0_shift()); + static const double baseZ0 = settings_.kz() * pow(2, settings_.z0_shift()); + static const double baseTanL = settings_.kz() / settings_.kr() * pow(2, settings_.t_shift()); + const int widthRZ = barrel ? widthZ : widthR; + const double baseRZ = barrel ? baseZ : baseR; + // calc residuals + const double rInv = (frameTrack.first->rInv() / baseInvR + .5) * baseInvR; + const double phi0 = (frameTrack.first->phi() / basePhi0 + .5) * basePhi0; + const double z0 = (frameTrack.first->z0() / baseZ0 + .5) * baseZ0; + const double tanL = (frameTrack.first->tanL() / baseTanL + .5) * baseTanL; + const double phi = deltaPhi(pos.phi() - (phi0 - rInv * pos.perp() / 2.)); + const double r = pos.perp() - (pos.z() - z0) / tanL; + const double z = pos.z() - (z0 + tanL * pos.perp()); + const double rz = barrel ? z : r; + const int phii = floor(phi / basePhi); + const int rzi = floor(rz / baseRZ); + const double phid = (phii + .5) * basePhi; + const double rzd = (rzi + .5) * baseRZ; + // parse residuals + TTBV hw(frameStub.second); + const TTBV hwRZ(hw, widthRZ, 0, true); + hw >>= widthRZ; + const TTBV hwPhi(hw, widthPhi, 0, true); + bool overflowPhi = abs(phii - hwPhi.val()) > pow(2, widthPhi) * 7. / 8.; + bool overflowZ = abs(rzi - hwRZ.val()) > pow(2, widthRZ) * 7. / 8.; + const double hwPhid = hwPhi.val(basePhi); + const double hwRZd = hwRZ.val(baseRZ); + const vector resolutions = {phid - hwPhid, rzd - hwRZd}; + const vector overflows = {overflowPhi, overflowZ}; + for (Resolution r : AllResolution) { + if (overflows[r]) { + cout << rzi << " " << hwRZ.val() << " " << barrel << " " << setup_->psModule(frameStub.first) << " " + << frameStub.second << endl; + nOverflows_[r]++; + continue; + } + hisResolution_[r]->Fill(resolutions[r]); + profResolution_[r]->Fill(ttPos.z(), ttPos.perp(), abs(resolutions[r])); + } + hisResolutionMe_[0]->Fill(phid); + hisResolutionMe_[1]->Fill(rzd); + hisResolutionThey_[0]->Fill(hwPhid); + hisResolutionThey_[1]->Fill(hwRZd); + his2Resolution_[0]->Fill(phid, hwPhid); + his2Resolution_[1]->Fill(rzd, hwRZd); + } + +} // namespace trklet + +DEFINE_FWK_MODULE(trklet::AnalyzerTBout); \ No newline at end of file diff --git a/L1Trigger/TrackFindingTracklet/test/AnalyzerTT.cc b/L1Trigger/TrackFindingTracklet/test/AnalyzerTT.cc new file mode 100644 index 0000000000000..12720a7ef23fb --- /dev/null +++ b/L1Trigger/TrackFindingTracklet/test/AnalyzerTT.cc @@ -0,0 +1,152 @@ +#include "FWCore/Framework/interface/one/EDAnalyzer.h" +#include "FWCore/Framework/interface/Run.h" +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/EventSetup.h" +#include "FWCore/Framework/interface/MakerMacros.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/ServiceRegistry/interface/Service.h" +#include "CommonTools/UtilAlgos/interface/TFileService.h" +#include "FWCore/Utilities/interface/EDGetToken.h" +#include "FWCore/Utilities/interface/InputTag.h" +#include "FWCore/Utilities/interface/Exception.h" +#include "DataFormats/Common/interface/Handle.h" + +#include "SimTracker/TrackTriggerAssociation/interface/StubAssociation.h" +#include "L1Trigger/TrackTrigger/interface/Setup.h" + +#include +#include + +using namespace std; +using namespace edm; +using namespace tt; + +namespace trklet { + + /*! \class trklet::AnalyzerTT + * \brief Class to analyze TTTracks + * \author Thomas Schuh + * \date 2020, Oct + */ + class AnalyzerTT : public one::EDAnalyzer { + public: + AnalyzerTT(const ParameterSet& iConfig); + void beginJob() override {} + void beginRun(const Run& iEvent, const EventSetup& iSetup) override; + void analyze(const Event& iEvent, const EventSetup& iSetup) override; + void endRun(const Run& iEvent, const EventSetup& iSetup) override {} + void endJob() override {} + + private: + // ED input token of TTTrackRefMap + EDGetTokenT edGetTokenTTTrackMap_; + // ED input token of TTStubRef to TPPtr association for tracking efficiency + EDGetTokenT edGetTokenStubAssociation_; + // Setup token + ESGetToken esGetTokenSetup_; + // stores, calculates and provides run-time constants + const Setup* setup_; + + // histos + + TH1F* hisQoverPt_; + TH1F* hisPhi0_; + TH1F* hisEta_; + TH1F* hisZ0_; + TProfile* profResQoverPtOverEta_; + TProfile* profResPhi0OverEta_; + TProfile* profResEtaOverEta_; + TProfile* profResZ0OverEta_; + }; + + AnalyzerTT::AnalyzerTT(const ParameterSet& iConfig) { + usesResource("TFileService"); + // book in- and output ED products + const auto& label = iConfig.getParameter("LabelAS"); + const auto& branch = iConfig.getParameter("BranchAcceptedTracks"); + const auto& inputTag = iConfig.getParameter("InputTagSelection"); + edGetTokenTTTrackMap_ = consumes(InputTag(label, branch)); + edGetTokenStubAssociation_ = consumes(inputTag); + // book ES products + esGetTokenSetup_ = esConsumes(); + // initial ES products + setup_ = nullptr; + } + + void AnalyzerTT::beginRun(const Run& iEvent, const EventSetup& iSetup) { + // helper class to store configurations + setup_ = &iSetup.getData(esGetTokenSetup_); + // book histograms + Service fs; + TFileDirectory dir; + dir = fs->mkdir("TT"); + hisQoverPt_ = dir.make("His qOverPt", ";", 100, -1., 1.); + hisPhi0_ = dir.make("His phi0", ";", 100, -M_PI, M_PI); + hisEta_ = dir.make("His eta", ";", 100, -2.5, 2.5); + hisZ0_ = dir.make("His z0", ";", 100, -20., 20.); + profResQoverPtOverEta_ = dir.make("Prof Res qOverPt over |eta|", ";", 100, 0., 2.5); + profResPhi0OverEta_ = dir.make("Prof Res phi0 over |eta|", ";", 100, 0., 2.5); + profResEtaOverEta_ = dir.make("Prof Res eta over |eta|", ";", 100, 0., 2.5); + profResZ0OverEta_ = dir.make("Prof Res z0 over |eta|", ";", 100, 0., 2.5); + } + + void AnalyzerTT::analyze(const Event& iEvent, const EventSetup& iSetup) { + Handle handleTTTrackMap; + iEvent.getByToken(edGetTokenTTTrackMap_, handleTTTrackMap); + Handle handleStubAssociation; + iEvent.getByToken(edGetTokenStubAssociation_, handleStubAssociation); + for (const pair& p : *handleTTTrackMap) { + const TTTrackRef& ttTrackRef = p.first; + //const TTTrackRef& ttTrackRef = p.second; + const vector& ttStubRefs = ttTrackRef->getStubRefs(); + const vector& tpPtrs = handleStubAssociation->associate(ttStubRefs); + if (tpPtrs.empty()) + continue; + const TPPtr& tpPtr = tpPtrs.front(); + const math::XYZPointD& v = tpPtr->vertex(); + const double qOverPtTT = ttTrackRef->rInv() / setup_->invPtToDphi() / 2.0; + const double qOverPtTP = tpPtr->charge() / tpPtr->pt(); + const double qOverPtDiff = qOverPtTP - qOverPtTT; + const double phi0TT = deltaPhi(ttTrackRef->phi() + ttTrackRef->phiSector() * setup_->baseRegion()); + //const double phi0TT = ttTrackRef->phi(); + const double phi0TP = tpPtr->phi(); + const double phi0Diff = phi0TP - phi0TT; + const double etaTT = asinh(ttTrackRef->tanL()); + const double etaTP = tpPtr->eta(); + const double etaDiff = etaTP - etaTT; + const double z0TT = ttTrackRef->z0(); + const double z0TP = v.z() - sinh(tpPtr->eta()) * (v.x() * cos(tpPtr->phi()) + v.y() * sin(tpPtr->phi())); + const double z0Diff = z0TP - z0TT; + hisQoverPt_->Fill(qOverPtTT); + hisPhi0_->Fill(phi0TT); + hisEta_->Fill(etaTT); + hisZ0_->Fill(z0TT); + profResQoverPtOverEta_->Fill(abs(etaTP), abs(qOverPtDiff)); + profResPhi0OverEta_->Fill(abs(etaTP), abs(phi0Diff)); + profResEtaOverEta_->Fill(abs(etaTP), abs(etaDiff)); + profResZ0OverEta_->Fill(abs(etaTP), abs(z0Diff)); + /*cout << etaTT << " " << etaTP << " " << etaDiff << " " << ttTrackRef->etaSector() << endl; + cout << "m0TT = " << -.5 * ttTrackRef->rInv() << endl; + cout << "m0TP = " << -qOverPtTP * setup_->invPtToDphi() << endl; + cout << "c0TT = " << phi0TT << endl; + cout << "c0TP = " << phi0TP << endl; + cout << "m1TT = " << ttTrackRef->tanL() << endl; + cout << "m1TP = " << sinh(tpPtr->eta()) << endl; + cout << "c1TT = " << z0TT << endl; + cout << "c1TP = " << z0TP << endl; + const vector& ttStubRefsTP = handleStubAssociation->findTTStubRefs(tpPtr); + for (const TTStubRef stub : ttStubRefs) { + const GlobalPoint& gp = setup_->stubPos(stub); + cout << gp.perp() << " " << gp.phi() << " " << gp.z() << endl; + } + cout << endl; + for (const TTStubRef stub : ttStubRefsTP) { + const GlobalPoint& gp = setup_->stubPos(stub); + cout << gp.perp() << " " << gp.phi() << " " << gp.z() << " " << setup_->dPhi(stub, 0.5*ttTrackRef->rInv()) << " " << setup_->dZ(stub, ttTrackRef->tanL()) << endl; + }*/ + } + } + +} // namespace trklet + +DEFINE_FWK_MODULE(trklet::AnalyzerTT); \ No newline at end of file diff --git a/L1Trigger/TrackFindingTracklet/test/AnalyzerTracklet.cc b/L1Trigger/TrackFindingTracklet/test/AnalyzerTracklet.cc new file mode 100644 index 0000000000000..cb0a90b6eb259 --- /dev/null +++ b/L1Trigger/TrackFindingTracklet/test/AnalyzerTracklet.cc @@ -0,0 +1,277 @@ +#include "FWCore/Framework/interface/one/EDAnalyzer.h" +#include "FWCore/Framework/interface/Run.h" +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/EventSetup.h" +#include "FWCore/Framework/interface/MakerMacros.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/ServiceRegistry/interface/Service.h" +#include "FWCore/MessageLogger/interface/MessageLogger.h" +#include "FWCore/Utilities/interface/EDGetToken.h" +#include "FWCore/Utilities/interface/InputTag.h" +#include "FWCore/Utilities/interface/Exception.h" +#include "CommonTools/UtilAlgos/interface/TFileService.h" +#include "DataFormats/Common/interface/Handle.h" + +#include "SimTracker/TrackTriggerAssociation/interface/StubAssociation.h" +#include "L1Trigger/TrackTrigger/interface/Setup.h" +#include "L1Trigger/TrackerTFP/interface/DataFormats.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace edm; +using namespace trackerTFP; +using namespace tt; + +namespace trklet { + + /*! \class trklet::AnalyzerTracklet + * \brief Class to analyze TTTracks found by tracklet pattern recognition + * \author Thomas Schuh + * \date 2020, Oct + */ + class AnalyzerTracklet : public one::EDAnalyzer { + public: + AnalyzerTracklet(const ParameterSet& iConfig); + void beginJob() override {} + void beginRun(const Run& iEvent, const EventSetup& iSetup) override; + void analyze(const Event& iEvent, const EventSetup& iSetup) override; + void endRun(const Run& iEvent, const EventSetup& iSetup) override {} + void endJob() override; + + private: + // gets all TPs associated too any of the tracks & number of tracks matching at least one TP + void associate(const vector>& tracks, + const StubAssociation* ass, + set& tps, + int& nMatchTrk, + bool perfect = false) const; + + // ED input token of tracks + EDGetTokenT edGetToken_; + // ED input token of TTStubRef to TPPtr association for tracking efficiency + EDGetTokenT edGetTokenSelection_; + // ED input token of TTStubRef to recontructable TPPtr association + EDGetTokenT edGetTokenReconstructable_; + // Setup token + ESGetToken esGetTokenSetup_; + // DataFormats token + ESGetToken esGetTokenDataFormats_; + // stores, calculates and provides run-time constants + const Setup* setup_; + // helper class to extract structured data from tt::Frames + const DataFormats* dataFormats_; + // enables analyze of TPs + bool useMCTruth_; + // + int nEvents_; + + // Histograms + + // counts per TFP (processing nonant and event) + TProfile* prof_; + // no. of tracks per nonant + TProfile* profChannel_; + TH1F* hisChannel_; + TH1F* hisEff_; + TH1F* hisEffTotal_; + TEfficiency* eff_; + + // printout + stringstream log_; + }; + + AnalyzerTracklet::AnalyzerTracklet(const ParameterSet& iConfig) + : useMCTruth_(iConfig.getParameter("UseMCTruth")), nEvents_(0) { + usesResource("TFileService"); + // book in- and output ED products + const InputTag& inputTag = iConfig.getParameter("InputTag"); + edGetToken_ = consumes(inputTag); + if (useMCTruth_) { + const auto& inputTagSelecttion = iConfig.getParameter("InputTagSelection"); + const auto& inputTagReconstructable = iConfig.getParameter("InputTagReconstructable"); + edGetTokenSelection_ = consumes(inputTagSelecttion); + edGetTokenReconstructable_ = consumes(inputTagReconstructable); + } + // book ES products + esGetTokenSetup_ = esConsumes(); + esGetTokenDataFormats_ = esConsumes(); + // initial ES products + setup_ = nullptr; + dataFormats_ = nullptr; + // log config + log_.setf(ios::fixed, ios::floatfield); + log_.precision(4); + } + + void AnalyzerTracklet::beginRun(const Run& iEvent, const EventSetup& iSetup) { + // helper class to store configurations + setup_ = &iSetup.getData(esGetTokenSetup_); + // helper class to extract structured data from tt::Frames + dataFormats_ = &iSetup.getData(esGetTokenDataFormats_); + // book histograms + Service fs; + TFileDirectory dir; + dir = fs->mkdir("Tracklet"); + prof_ = dir.make("Counts", ";", 10, 0.5, 10.5); + prof_->GetXaxis()->SetBinLabel(1, "Stubs"); + prof_->GetXaxis()->SetBinLabel(2, "Tracks"); + prof_->GetXaxis()->SetBinLabel(3, "Lost Tracks"); + prof_->GetXaxis()->SetBinLabel(4, "Matched Tracks"); + prof_->GetXaxis()->SetBinLabel(5, "All Tracks"); + prof_->GetXaxis()->SetBinLabel(6, "Found TPs"); + prof_->GetXaxis()->SetBinLabel(7, "Found selected TPs"); + prof_->GetXaxis()->SetBinLabel(8, "Lost TPs"); + prof_->GetXaxis()->SetBinLabel(9, "All TPs"); + prof_->GetXaxis()->SetBinLabel(10, "Perfectly Found selected TPs"); + // channel occupancy + constexpr int maxOcc = 180; + const int numChannels = setup_->numRegions(); + hisChannel_ = dir.make("His Channel Occupancy", ";", maxOcc, -.5, maxOcc - .5); + profChannel_ = dir.make("Prof Channel Occupancy", ";", numChannels, -.5, numChannels - .5); + // Efficiencies + hisEffTotal_ = dir.make("HisTPEtaTotal", ";", 128, -2.5, 2.5); + hisEff_ = dir.make("HisTPEta", ";", 128, -2.5, 2.5); + eff_ = dir.make("EffEta", ";", 128, -2.5, 2.5); + } + + void AnalyzerTracklet::analyze(const Event& iEvent, const EventSetup& iSetup) { + auto fill = [this](const TPPtr& tpPtr, TH1F* his) { his->Fill(tpPtr->eta()); }; + // read in tracklet products + Handle handle; + iEvent.getByToken(edGetToken_, handle); + // read in MCTruth + const StubAssociation* selection = nullptr; + const StubAssociation* reconstructable = nullptr; + if (useMCTruth_) { + Handle handleSelection; + iEvent.getByToken(edGetTokenSelection_, handleSelection); + selection = handleSelection.product(); + prof_->Fill(9, selection->numTPs()); + Handle handleReconstructable; + iEvent.getByToken(edGetTokenReconstructable_, handleReconstructable); + reconstructable = handleReconstructable.product(); + for (const auto& p : selection->getTrackingParticleToTTStubsMap()) + fill(p.first, hisEffTotal_); + } + // + const TTTracks& ttTracks = *handle.product(); + vector> ttTrackRefsRegions(setup_->numRegions()); + vector nTTTracksRegions(setup_->numRegions(), 0); + for (const TTTrack& ttTrack : ttTracks) + nTTTracksRegions[ttTrack.phiSector()]++; + for (int region = 0; region < setup_->numRegions(); region++) + ttTrackRefsRegions[region].reserve(nTTTracksRegions[region]); + int i(0); + for (const TTTrack& ttTrack : ttTracks) + ttTrackRefsRegions[ttTrack.phiSector()].emplace_back(TTTrackRef(handle, i++)); + for (int region = 0; region < setup_->numRegions(); region++) { + const vector& ttTrackRefs = ttTrackRefsRegions[region]; + const int nStubs = + accumulate(ttTrackRefs.begin(), ttTrackRefs.end(), 0, [](int& sum, const TTTrackRef& ttTrackRef) { + return sum += ttTrackRef->getStubRefs().size(); + }); + const int nTracks = ttTrackRefs.size(); + hisChannel_->Fill(nTracks); + profChannel_->Fill(region, nTracks); + prof_->Fill(1, nStubs); + prof_->Fill(2, nTracks); + // no access to lost tracks + prof_->Fill(3, 0); + } + // analyze tracklet products and associate found tracks with reconstrucable TrackingParticles + set tpPtrs; + set tpPtrsSelection; + set tpPtrsPerfect; + int nAllMatched(0); + // convert vector of tracks to vector of vector of associated stubs + vector> tracks; + tracks.reserve(ttTracks.size()); + transform( + ttTracks.begin(), ttTracks.end(), back_inserter(tracks), [](const TTTrack& ttTrack) { + return ttTrack.getStubRefs(); + }); + if (useMCTruth_) { + int tmp(0); + associate(tracks, selection, tpPtrsSelection, tmp); + associate(tracks, selection, tpPtrsPerfect, tmp, true); + associate(tracks, reconstructable, tpPtrs, nAllMatched); + } + for (const TPPtr& tpPtr : tpPtrsSelection) + fill(tpPtr, hisEff_); + prof_->Fill(4, nAllMatched); + prof_->Fill(5, ttTracks.size()); + prof_->Fill(6, tpPtrs.size()); + prof_->Fill(7, tpPtrsSelection.size()); + // no access to lost tp + prof_->Fill(8, 0); + prof_->Fill(10, tpPtrsPerfect.size()); + nEvents_++; + } + + void AnalyzerTracklet::endJob() { + if (nEvents_ == 0) + return; + // effi + eff_->SetPassedHistogram(*hisEff_, "f"); + eff_->SetTotalHistogram(*hisEffTotal_, "f"); + // printout SF summary + const double totalTPs = prof_->GetBinContent(9); + const double numStubs = prof_->GetBinContent(1); + const double numTracks = prof_->GetBinContent(2); + const double totalTracks = prof_->GetBinContent(5); + const double numTracksMatched = prof_->GetBinContent(4); + const double numTPsAll = prof_->GetBinContent(6); + const double numTPsEff = prof_->GetBinContent(7); + const double numTPsEffPerfect = prof_->GetBinContent(10); + const double errStubs = prof_->GetBinError(1); + const double errTracks = prof_->GetBinError(2); + const double fracFake = (totalTracks - numTracksMatched) / totalTracks; + const double fracDup = (numTracksMatched - numTPsAll) / totalTracks; + const double eff = numTPsEff / totalTPs; + const double errEff = sqrt(eff * (1. - eff) / totalTPs / nEvents_); + const double effPerfect = numTPsEffPerfect / totalTPs; + const double errEffPerfect = sqrt(effPerfect * (1. - effPerfect) / totalTPs / nEvents_); + const vector nums = {numStubs, numTracks}; + const vector errs = {errStubs, errTracks}; + const int wNums = ceil(log10(*max_element(nums.begin(), nums.end()))) + 5; + const int wErrs = ceil(log10(*max_element(errs.begin(), errs.end()))) + 5; + log_ << " Tracklet SUMMARY " << endl; + log_ << "number of stubs per TFP = " << setw(wNums) << numStubs << " +- " << setw(wErrs) << errStubs << endl; + log_ << "number of tracks per TFP = " << setw(wNums) << numTracks << " +- " << setw(wErrs) << errTracks << endl; + log_ << "current tracking efficiency = " << setw(wNums) << effPerfect << " +- " << setw(wErrs) << errEffPerfect + << endl; + log_ << "max tracking efficiency = " << setw(wNums) << eff << " +- " << setw(wErrs) << errEff << endl; + log_ << " fake rate = " << setw(wNums) << fracFake << endl; + log_ << " duplicate rate = " << setw(wNums) << fracDup << endl; + log_ << "============================================================="; + LogPrint("L1Trigger/TrackFindingTracklet") << log_.str(); + } + + // gets all TPs associated too any of the tracks & number of tracks matching at least one TP + void AnalyzerTracklet::associate(const vector>& tracks, + const StubAssociation* ass, + set& tps, + int& nMatchTrk, + bool perfect) const { + for (const vector& ttStubRefs : tracks) { + const vector& tpPtrs = perfect ? ass->associateFinal(ttStubRefs) : ass->associate(ttStubRefs); + if (tpPtrs.empty()) + continue; + nMatchTrk++; + copy(tpPtrs.begin(), tpPtrs.end(), inserter(tps, tps.begin())); + } + } + +} // namespace trklet + +DEFINE_FWK_MODULE(trklet::AnalyzerTracklet); \ No newline at end of file diff --git a/L1Trigger/TrackFindingTracklet/test/BuildFile.xml b/L1Trigger/TrackFindingTracklet/test/BuildFile.xml index e4d0fb04bb751..94d63baf35cbd 100644 --- a/L1Trigger/TrackFindingTracklet/test/BuildFile.xml +++ b/L1Trigger/TrackFindingTracklet/test/BuildFile.xml @@ -7,9 +7,15 @@ + + + + - + + + @@ -18,10 +24,21 @@ - - + + + + + + + + + + + + + diff --git a/L1Trigger/TrackFindingTracklet/test/HybridTracksNewKF_cfg.py b/L1Trigger/TrackFindingTracklet/test/HybridTracksNewKF_cfg.py new file mode 100644 index 0000000000000..5f63520975198 --- /dev/null +++ b/L1Trigger/TrackFindingTracklet/test/HybridTracksNewKF_cfg.py @@ -0,0 +1,115 @@ +################################################################################################ +# This script runs DTC + prompt tracklet + KF interface + new KF emulator with analyzer for each step +# allowing to identify problems quickly during developement. +# This script is a specialized and light-weight version of L1TrackNtupleMaker_cfg.py +# To run execute do +# cmsRun L1Trigger/TrackFindingTracklet/test/HybridTracksNewKF_cfg.py +# where the arguments take default values if you don't specify them. You can change defaults below. +################################################################################################# + +import FWCore.ParameterSet.Config as cms + +process = cms.Process( "Demo" ) +process.load( 'FWCore.MessageService.MessageLogger_cfi' ) +process.load( 'Configuration.EventContent.EventContent_cff' ) +process.load( 'Configuration.Geometry.GeometryExtended2026D76Reco_cff' ) +process.load( 'Configuration.Geometry.GeometryExtended2026D76_cff' ) +process.load( 'Configuration.StandardSequences.MagneticField_cff' ) +process.load( 'Configuration.StandardSequences.FrontierConditions_GlobalTag_cff' ) +process.load( 'L1Trigger.TrackTrigger.TrackTrigger_cff' ) + +from Configuration.AlCa.GlobalTag import GlobalTag +process.GlobalTag = GlobalTag(process.GlobalTag, 'auto:phase2_realistic', '') + +# load code that associates stubs with mctruth +process.load( 'SimTracker.TrackTriggerAssociation.StubAssociator_cff' ) +# load code that produces DTCStubs +process.load( 'L1Trigger.TrackerDTC.ProducerED_cff' ) +# load code that analyzes DTCStubs +process.load( 'L1Trigger.TrackerDTC.Analyzer_cff' ) +# L1 tracking => hybrid emulation +process.load("L1Trigger.TrackFindingTracklet.L1HybridEmulationTracks_cff") +from L1Trigger.TrackFindingTracklet.Customize_cff import * +fwConfig( process ) +#--- Load code that analyzes hybrid emulation +process.load( 'L1Trigger.TrackFindingTracklet.Analyzer_cff' ) +# load code that fits hybrid tracks +process.load( 'L1Trigger.TrackFindingTracklet.Producer_cff' ) + +# load and configure TrackTriggerAssociation +process.load( 'SimTracker.TrackTriggerAssociation.TrackTriggerAssociator_cff' ) +process.TTTrackAssociatorFromPixelDigis.TTTracks = cms.VInputTag( cms.InputTag( + process.TrackFindingTrackletProducer_params.LabelTT.value(), + process.TrackFindingTrackletProducer_params.BranchAcceptedTracks.value() +) ) + +# build schedule +process.mc = cms.Sequence( process.StubAssociator ) +process.dtc = cms.Sequence( process.TrackerDTCProducer + process.TrackerDTCAnalyzer ) +process.tracklet = cms.Sequence( process.L1HybridTracks + process.TrackFindingTrackletAnalyzerTracklet ) +process.TBout = cms.Sequence( process.TrackFindingTrackletProducerTBout + process.TrackFindingTrackletAnalyzerTBout ) +process.interIn = cms.Sequence( process.TrackFindingTrackletProducerKFin + process.TrackFindingTrackletAnalyzerKFin ) +process.kf = cms.Sequence( process.TrackFindingTrackletProducerKF + process.TrackFindingTrackletAnalyzerKF ) +process.TTTracks = cms.Sequence( process.TrackFindingTrackletProducerTT + process.TrackFindingTrackletProducerAS + process.TrackTriggerAssociatorTracks ) +process.interOut = cms.Sequence( process.TrackFindingTrackletProducerKFout + process.TrackFindingTrackletAnalyzerKFout ) +process.tt = cms.Path( process.mc + process.dtc + process.tracklet + process.TBout + process.interIn + process.kf + process.TTTracks + process.interOut ) +process.schedule = cms.Schedule( process.tt ) + +# create options +import FWCore.ParameterSet.VarParsing as VarParsing +options = VarParsing.VarParsing( 'analysis' ) +# specify input MC +#from MCsamples.Scripts.getCMSdata_cfi import * +#from MCsamples.Scripts.getCMSlocaldata_cfi import * +#from MCsamples.RelVal_1130_D76.PU200_TTbar_14TeV_cfi import * +#inputMC = getCMSdataFromCards() +inputMC = [ + #'/store/relval/CMSSW_11_3_0_pre6/RelValSingleMuFlatPt2To100/GEN-SIM-DIGI-RAW/113X_mcRun4_realistic_v6_2026D76noPU-v1/10000/05f802b7-b0b3-4cca-8b70-754682c3bb4c.root', + #'/store/relval/CMSSW_11_3_0_pre6/RelValSingleMuFlatPt2To100/GEN-SIM-DIGI-RAW/113X_mcRun4_realistic_v6_2026D76noPU-v1/10000/0b69ed0a-66e9-403a-88f0-fb3115615461.root', + #'/store/relval/CMSSW_11_3_0_pre6/RelValSingleMuFlatPt2To100/GEN-SIM-DIGI-RAW/113X_mcRun4_realistic_v6_2026D76noPU-v1/10000/0f4dea68-7574-43bb-97c3-5382d68a2704.root', + #'/store/relval/CMSSW_11_3_0_pre6/RelValSingleMuFlatPt2To100/GEN-SIM-DIGI-RAW/113X_mcRun4_realistic_v6_2026D76noPU-v1/10000/156b3ca6-c74a-4f46-ae5e-03d9b01acd4c.root', + #'/store/relval/CMSSW_11_3_0_pre6/RelValSingleMuFlatPt2To100/GEN-SIM-DIGI-RAW/113X_mcRun4_realistic_v6_2026D76noPU-v1/10000/16727f1d-2922-4e0a-8239-82e1ffecd43b.root', + #'/store/relval/CMSSW_11_3_0_pre6/RelValSingleMuFlatPt2To100/GEN-SIM-DIGI-RAW/113X_mcRun4_realistic_v6_2026D76noPU-v1/10000/1af620bf-1f6d-4d5a-8170-4135ac798581.root', + #'/store/relval/CMSSW_11_3_0_pre6/RelValSingleMuFlatPt2To100/GEN-SIM-DIGI-RAW/113X_mcRun4_realistic_v6_2026D76noPU-v1/10000/1dc513d9-75fc-44c0-b8e0-e2925323416b.root', + #'/store/relval/CMSSW_11_3_0_pre6/RelValSingleMuFlatPt2To100/GEN-SIM-DIGI-RAW/113X_mcRun4_realistic_v6_2026D76noPU-v1/10000/2010f402-2133-4c3a-851b-1ae68fe23eb3.root', + #'/store/relval/CMSSW_11_3_0_pre6/RelValSingleMuFlatPt2To100/GEN-SIM-DIGI-RAW/113X_mcRun4_realistic_v6_2026D76noPU-v1/10000/228dfbba-3d5c-42b9-b827-cfa8f11a2f38.root', + #'/store/relval/CMSSW_11_3_0_pre6/RelValSingleMuFlatPt2To100/GEN-SIM-DIGI-RAW/113X_mcRun4_realistic_v6_2026D76noPU-v1/10000/27d006b1-d023-4775-8430-382e6962149c.root' + #'/store/relval/CMSSW_11_3_0_pre6/RelValDisplacedMuPt2To100Dxy100/GEN-SIM-DIGI-RAW/113X_mcRun4_realistic_v6_2026D76noPU-v1/00000/011da61a-9524-4a96-b91f-03e8690af3bd.root' + '/store/relval/CMSSW_11_3_0_pre6/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/00000/00026541-6200-4eed-b6f8-d3a1fd720e9c.root', + '/store/relval/CMSSW_11_3_0_pre6/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/00000/013d0125-8f6e-496b-8335-614398c9210d.root', + '/store/relval/CMSSW_11_3_0_pre6/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/00000/058bd134-86de-47e1-bcde-379ed9b79e1b.root', + '/store/relval/CMSSW_11_3_0_pre6/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/00000/0915d66c-cbd4-4ef6-9971-7dd59e198b56.root', + '/store/relval/CMSSW_11_3_0_pre6/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/00000/09823c8d-e443-4066-8347-8c704929cb2b.root', + '/store/relval/CMSSW_11_3_0_pre6/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/00000/0c39a1aa-93ee-41c1-8543-6d90c09114a7.root', + '/store/relval/CMSSW_11_3_0_pre6/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/00000/0fcdcc53-fb9f-4f0b-8529-a4d60d914c14.root', + '/store/relval/CMSSW_11_3_0_pre6/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/00000/16760a5c-9cd2-41c3-82e5-399bb962d537.root', + '/store/relval/CMSSW_11_3_0_pre6/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/00000/1752640f-2001-4d14-9276-063ec07cea92.root', + '/store/relval/CMSSW_11_3_0_pre6/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/00000/180712c9-31a5-4f2a-bf92-a7fbee4dabad.root' +] +options.register( 'inputMC', inputMC, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.string, "Files to be processed" ) +# specify number of events to process. +options.register( 'Events',100,VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.int, "Number of Events to analyze" ) +options.parseArguments() + +process.options = cms.untracked.PSet( wantSummary = cms.untracked.bool(False) ) +process.maxEvents = cms.untracked.PSet( input = cms.untracked.int32(options.Events) ) +process.source = cms.Source( + "PoolSource", + fileNames = cms.untracked.vstring( options.inputMC ), + #skipEvents = cms.untracked.uint32( 250 ), + secondaryFileNames = cms.untracked.vstring(), + duplicateCheckMode = cms.untracked.string( 'noDuplicateCheck' ) +) +process.Timing = cms.Service( "Timing", summaryOnly = cms.untracked.bool( True ) ) +process.MessageLogger.cerr.enableStatistics = False +process.TFileService = cms.Service( "TFileService", fileName = cms.string( "Hist.root" ) ) + +if ( False ): + process.out = cms.OutputModule ( + "PoolOutputModule", + fileName = cms.untracked.string("L1Tracks.root"), + fastCloning = cms.untracked.bool( False ), + outputCommands = cms.untracked.vstring('drop *', 'keep *_TTTrack*_*_*', 'keep *_TTStub*_*_*' ) + ) + process.FEVToutput_step = cms.EndPath( process.out ) + process.schedule.append( process.FEVToutput_step ) \ No newline at end of file diff --git a/L1Trigger/TrackFindingTracklet/test/HybridTracks_cfg.py b/L1Trigger/TrackFindingTracklet/test/HybridTracks_cfg.py index cae42a3e840a8..0b50e7cded947 100644 --- a/L1Trigger/TrackFindingTracklet/test/HybridTracks_cfg.py +++ b/L1Trigger/TrackFindingTracklet/test/HybridTracks_cfg.py @@ -41,7 +41,6 @@ # ---------------------------------------------------------------------------------- process.load( 'L1Trigger.TrackerDTC.ProducerED_cff' ) -process.load( 'L1Trigger.TrackerDTC.ProducerES_cff' ) process.dtc = cms.Path( process.TrackerDTCProducer ) # ---------------------------------------------------------------------------------- diff --git a/L1Trigger/TrackFindingTracklet/test/L1TrackNtupleMaker.cc b/L1Trigger/TrackFindingTracklet/test/L1TrackNtupleMaker.cc index a795c2afd2200..dea1f5092cf78 100644 --- a/L1Trigger/TrackFindingTracklet/test/L1TrackNtupleMaker.cc +++ b/L1Trigger/TrackFindingTracklet/test/L1TrackNtupleMaker.cc @@ -8,7 +8,8 @@ // FRAMEWORK HEADERS #include "FWCore/PluginManager/interface/ModuleDef.h" #include "FWCore/Framework/interface/MakerMacros.h" -#include "FWCore/Framework/interface/EDAnalyzer.h" +#include "FWCore/Framework/interface/one/EDAnalyzer.h" +#include "FWCore/Framework/interface/Run.h" #include "FWCore/Framework/interface/Event.h" #include "FWCore/Framework/interface/ESHandle.h" #include "FWCore/Framework/interface/EventSetup.h" @@ -55,6 +56,7 @@ //////////////// // PHYSICS TOOLS +#include "L1Trigger/TrackTrigger/interface/HitPatternHelper.h" #include "CommonTools/UtilAlgos/interface/TFileService.h" #include "CLHEP/Units/PhysicalConstants.h" @@ -85,7 +87,7 @@ using namespace edm; // // ////////////////////////////// -class L1TrackNtupleMaker : public edm::EDAnalyzer { +class L1TrackNtupleMaker : public one::EDAnalyzer { public: // Constructor/destructor explicit L1TrackNtupleMaker(const edm::ParameterSet& iConfig); @@ -95,6 +97,8 @@ class L1TrackNtupleMaker : public edm::EDAnalyzer { void beginJob() override; void endJob() override; void analyze(const edm::Event& iEvent, const edm::EventSetup& iSetup) override; + void beginRun(const Run& iEvent, const EventSetup& iSetup) override {} + void endRun(const Run& iEvent, const EventSetup& iSetup) override {} protected: private: @@ -138,6 +142,10 @@ class L1TrackNtupleMaker : public edm::EDAnalyzer { edm::EDGetTokenT > GenJetToken_; + edm::ESGetToken getTokenTrackerGeom_; + edm::ESGetToken getTokenTrackerTopo_; + edm::ESGetToken getTokenBField_; + edm::ESGetToken getTokenHPHSetup_; //----------------------------------------------------------------------------------------------- // tree & branches for mini-ntuple @@ -160,7 +168,16 @@ class L1TrackNtupleMaker : public edm::EDAnalyzer { std::vector* m_trk_dhits; std::vector* m_trk_seed; std::vector* m_trk_hitpattern; + std::vector* m_trk_lhits_hitpattern; // 6-digit hit mask (barrel layer only) dervied from hitpattern + std::vector* m_trk_dhits_hitpattern; // disk only + std::vector* m_trk_nPSstub_hitpattern; + std::vector* m_trk_n2Sstub_hitpattern; + std::vector* m_trk_nLostPSstub_hitpattern; + std::vector* m_trk_nLost2Sstub_hitpattern; + std::vector* m_trk_nLoststub_V1_hitpattern; // Same as the definiton of "nlaymiss_interior" in TrackQuality.cc + std::vector* m_trk_nLoststub_V2_hitpattern; // A tighter version of "nlaymiss_interior" std::vector* m_trk_phiSector; + std::vector* m_trk_etaSector; std::vector* m_trk_genuine; std::vector* m_trk_loose; std::vector* m_trk_unknown; @@ -256,6 +273,7 @@ class L1TrackNtupleMaker : public edm::EDAnalyzer { ////////////// // CONSTRUCTOR L1TrackNtupleMaker::L1TrackNtupleMaker(edm::ParameterSet const& iConfig) : config(iConfig) { + usesResource("TFileService"); MyProcess = iConfig.getParameter("MyProcess"); DebugMode = iConfig.getParameter("DebugMode"); SaveAllTracks = iConfig.getParameter("SaveAllTracks"); @@ -288,6 +306,11 @@ L1TrackNtupleMaker::L1TrackNtupleMaker(edm::ParameterSet const& iConfig) : confi TrackingParticleToken_ = consumes >(TrackingParticleInputTag); TrackingVertexToken_ = consumes >(TrackingVertexInputTag); GenJetToken_ = consumes >(GenJetInputTag); + + getTokenTrackerGeom_ = esConsumes(); + getTokenTrackerTopo_ = esConsumes(); + getTokenBField_ = esConsumes(); + getTokenHPHSetup_ = esConsumes(); } ///////////// @@ -329,7 +352,16 @@ void L1TrackNtupleMaker::beginJob() { m_trk_dhits = new std::vector; m_trk_seed = new std::vector; m_trk_hitpattern = new std::vector; + m_trk_lhits_hitpattern = new std::vector; + m_trk_dhits_hitpattern = new std::vector; + m_trk_nPSstub_hitpattern = new std::vector; + m_trk_n2Sstub_hitpattern = new std::vector; + m_trk_nLostPSstub_hitpattern = new std::vector; + m_trk_nLost2Sstub_hitpattern = new std::vector; + m_trk_nLoststub_V1_hitpattern = new std::vector; + m_trk_nLoststub_V2_hitpattern = new std::vector; m_trk_phiSector = new std::vector; + m_trk_etaSector = new std::vector; m_trk_genuine = new std::vector; m_trk_loose = new std::vector; m_trk_unknown = new std::vector; @@ -427,7 +459,16 @@ void L1TrackNtupleMaker::beginJob() { eventTree->Branch("trk_dhits", &m_trk_dhits); eventTree->Branch("trk_seed", &m_trk_seed); eventTree->Branch("trk_hitpattern", &m_trk_hitpattern); + eventTree->Branch("trk_lhits_hitpattern", &m_trk_lhits_hitpattern); + eventTree->Branch("trk_dhits_hitpattern", &m_trk_dhits_hitpattern); + eventTree->Branch("trk_nPSstub_hitpattern", &m_trk_nPSstub_hitpattern); + eventTree->Branch("trk_n2Sstub_hitpattern", &m_trk_n2Sstub_hitpattern); + eventTree->Branch("trk_nLostPSstub_hitpattern", &m_trk_nLostPSstub_hitpattern); + eventTree->Branch("trk_nLost2Sstub_hitpattern", &m_trk_nLost2Sstub_hitpattern); + eventTree->Branch("trk_nLoststub_V1_hitpattern", &m_trk_nLoststub_V1_hitpattern); + eventTree->Branch("trk_nLoststub_V2_hitpattern", &m_trk_nLoststub_V2_hitpattern); eventTree->Branch("trk_phiSector", &m_trk_phiSector); + eventTree->Branch("trk_etaSector", &m_trk_etaSector); eventTree->Branch("trk_genuine", &m_trk_genuine); eventTree->Branch("trk_loose", &m_trk_loose); eventTree->Branch("trk_unknown", &m_trk_unknown); @@ -554,7 +595,16 @@ void L1TrackNtupleMaker::analyze(const edm::Event& iEvent, const edm::EventSetup m_trk_dhits->clear(); m_trk_seed->clear(); m_trk_hitpattern->clear(); + m_trk_lhits_hitpattern->clear(); + m_trk_dhits_hitpattern->clear(); + m_trk_nPSstub_hitpattern->clear(); + m_trk_n2Sstub_hitpattern->clear(); + m_trk_nLostPSstub_hitpattern->clear(); + m_trk_nLost2Sstub_hitpattern->clear(); + m_trk_nLoststub_V1_hitpattern->clear(); + m_trk_nLoststub_V2_hitpattern->clear(); m_trk_phiSector->clear(); + m_trk_etaSector->clear(); m_trk_genuine->clear(); m_trk_loose->clear(); m_trk_unknown->clear(); @@ -663,24 +713,21 @@ void L1TrackNtupleMaker::analyze(const edm::Event& iEvent, const edm::EventSetup edm::Handle > TrackingParticleHandle; edm::Handle > TrackingVertexHandle; iEvent.getByToken(TrackingParticleToken_, TrackingParticleHandle); - iEvent.getByToken(TrackingVertexToken_, TrackingVertexHandle); + //iEvent.getByToken(TrackingVertexToken_, TrackingVertexHandle); // ----------------------------------------------------------------------------------------------- // more for TTStubs - edm::ESHandle geometryHandle; - iSetup.get().get(geometryHandle); + edm::ESHandle tGeomHandle = iSetup.getHandle(getTokenTrackerGeom_); - edm::ESHandle tTopoHandle; - iSetup.get().get(tTopoHandle); + edm::ESHandle tTopoHandle = iSetup.getHandle(getTokenTrackerTopo_); - edm::ESHandle tGeomHandle; - iSetup.get().get(tGeomHandle); + edm::ESHandle bFieldHandle = iSetup.getHandle(getTokenBField_); - edm::ESHandle magneticFieldHandle; - iSetup.get().get(magneticFieldHandle); + edm::ESHandle hphHandle = iSetup.getHandle(getTokenHPHSetup_); const TrackerTopology* const tTopo = tTopoHandle.product(); const TrackerGeometry* const theTrackerGeom = tGeomHandle.product(); + const hph::Setup* hphSetup = hphHandle.product(); // ---------------------------------------------------------------------------------------------- // loop over L1 stubs @@ -864,6 +911,29 @@ void L1TrackNtupleMaker::analyze(const edm::Event& iEvent, const edm::EventSetup float tmp_trk_eta = iterL1Track->momentum().eta(); float tmp_trk_phi = iterL1Track->momentum().phi(); float tmp_trk_z0 = iterL1Track->z0(); //cm + float tmp_trk_tanL = iterL1Track->tanL(); + + int tmp_trk_hitpattern = 0; + tmp_trk_hitpattern = (int)iterL1Track->hitPattern(); + hph::HitPatternHelper hph(hphSetup, tmp_trk_hitpattern, tmp_trk_tanL, tmp_trk_z0); + std::vector hitpattern_expanded_binary = hph.binary(); + int tmp_trk_lhits_hitpattern = 0; + int tmp_trk_dhits_hitpattern = 0; + for (int i = 0; i < (int)hitpattern_expanded_binary.size(); i++) { + if (hitpattern_expanded_binary[i]) { + if (i < 6) { + tmp_trk_lhits_hitpattern += pow(10, i); + } else { + tmp_trk_dhits_hitpattern += pow(10, i - 6); + } + } + } + int tmp_trk_nPSstub_hitpattern = hph.numPS(); + int tmp_trk_n2Sstub_hitpattern = hph.num2S(); + int tmp_trk_nLostPSstub_hitpattern = hph.numMissingPS(); + int tmp_trk_nLost2Sstub_hitpattern = hph.numMissing2S(); + int tmp_trk_nLoststub_V1_hitpattern = hph.numMissingInterior1(); + int tmp_trk_nLoststub_V2_hitpattern = hph.numMissingInterior2(); float tmp_trk_d0 = -999; if (L1Tk_nPar == 5) { @@ -885,10 +955,8 @@ void L1TrackNtupleMaker::analyze(const edm::Event& iEvent, const edm::EventSetup int tmp_trk_seed = 0; tmp_trk_seed = (int)iterL1Track->trackSeedType(); - int tmp_trk_hitpattern = 0; - tmp_trk_hitpattern = (int)iterL1Track->hitPattern(); - unsigned int tmp_trk_phiSector = iterL1Track->phiSector(); + int tmp_trk_etaSector = hph.etaSector(); // ---------------------------------------------------------------------------------------------- // loop over stubs on tracks @@ -975,7 +1043,16 @@ void L1TrackNtupleMaker::analyze(const edm::Event& iEvent, const edm::EventSetup m_trk_lhits->push_back(tmp_trk_lhits); m_trk_seed->push_back(tmp_trk_seed); m_trk_hitpattern->push_back(tmp_trk_hitpattern); + m_trk_lhits_hitpattern->push_back(tmp_trk_lhits_hitpattern); + m_trk_dhits_hitpattern->push_back(tmp_trk_dhits_hitpattern); + m_trk_nPSstub_hitpattern->push_back(tmp_trk_nPSstub_hitpattern); + m_trk_n2Sstub_hitpattern->push_back(tmp_trk_n2Sstub_hitpattern); + m_trk_nLostPSstub_hitpattern->push_back(tmp_trk_nLostPSstub_hitpattern); + m_trk_nLost2Sstub_hitpattern->push_back(tmp_trk_nLost2Sstub_hitpattern); + m_trk_nLoststub_V1_hitpattern->push_back(tmp_trk_nLoststub_V1_hitpattern); + m_trk_nLoststub_V2_hitpattern->push_back(tmp_trk_nLoststub_V2_hitpattern); m_trk_phiSector->push_back(tmp_trk_phiSector); + m_trk_etaSector->push_back(tmp_trk_etaSector); m_trk_genuine->push_back(tmp_trk_genuine); m_trk_loose->push_back(tmp_trk_loose); m_trk_unknown->push_back(tmp_trk_unknown); @@ -1020,12 +1097,12 @@ void L1TrackNtupleMaker::analyze(const edm::Event& iEvent, const edm::EventSetup // ---------------------------------------------------------------------------------------------- // get d0/z0 propagated back to the IP - float tmp_matchtp_t = tan(2.0 * atan(1.0) - 2.0 * atan(exp(-tmp_matchtp_eta))); + float tmp_matchtp_t = 1.0 / tan(2.0 * atan(exp(-tmp_matchtp_eta))); float delx = -tmp_matchtp_vx; float dely = -tmp_matchtp_vy; - float b_field = magneticFieldHandle.product()->inTesla(GlobalPoint(0, 0, 0)).z(); + float b_field = bFieldHandle.product()->inTesla(GlobalPoint(0, 0, 0)).z(); float c_converted = CLHEP::c_light / 1.0E5; float r2_inv = my_tp->charge() * c_converted * b_field / tmp_matchtp_pt / 2.0; @@ -1119,7 +1196,16 @@ void L1TrackNtupleMaker::analyze(const edm::Event& iEvent, const edm::EventSetup continue; //only care about tracking particles from the primary interaction (except for MyProcess==1, i.e. looking at all TPs) float tmp_tp_pt = iterTP->pt(); + float tmp_tp_charge = iterTP->charge(); float tmp_tp_eta = iterTP->eta(); + + if (tmp_tp_pt < TP_minPt) // Save CPU by applying these cuts here. + continue; + if (tmp_tp_charge == 0.) + continue; + if (std::abs(tmp_tp_eta) > TP_maxEta) + continue; + float tmp_tp_phi = iterTP->phi(); float tmp_tp_vz = iterTP->vz(); float tmp_tp_vx = iterTP->vx(); @@ -1131,13 +1217,12 @@ void L1TrackNtupleMaker::analyze(const edm::Event& iEvent, const edm::EventSetup // ---------------------------------------------------------------------------------------------- // get d0/z0 propagated back to the IP - float tmp_tp_t = tan(2.0 * atan(1.0) - 2.0 * atan(exp(-tmp_tp_eta))); - float tmp_tp_charge = iterTP->charge(); + float tmp_tp_t = 1.0 / tan(2.0 * atan(exp(-tmp_tp_eta))); float delx = -tmp_tp_vx; float dely = -tmp_tp_vy; - float b_field = magneticFieldHandle.product()->inTesla(GlobalPoint(0, 0, 0)).z(); + float b_field = bFieldHandle.product()->inTesla(GlobalPoint(0, 0, 0)).z(); float c_converted = CLHEP::c_light / 1.0E5; float r2_inv = tmp_tp_charge * c_converted * b_field / tmp_tp_pt / 2.0; @@ -1162,10 +1247,6 @@ void L1TrackNtupleMaker::analyze(const edm::Event& iEvent, const edm::EventSetup if ((MyProcess == 6 || MyProcess == 15 || MyProcess == 211) && abs(tmp_tp_pdgid) != 211) continue; - if (tmp_tp_pt < TP_minPt) - continue; - if (std::abs(tmp_tp_eta) > TP_maxEta) - continue; if (std::abs(tmp_tp_z0) > TP_maxZ0) continue; diff --git a/L1Trigger/TrackFindingTracklet/test/L1TrackNtupleMaker_cfg.py b/L1Trigger/TrackFindingTracklet/test/L1TrackNtupleMaker_cfg.py index 17a89466a4c2f..7bf733e0277c3 100644 --- a/L1Trigger/TrackFindingTracklet/test/L1TrackNtupleMaker_cfg.py +++ b/L1Trigger/TrackFindingTracklet/test/L1TrackNtupleMaker_cfg.py @@ -11,11 +11,13 @@ # edit options here ############################################################ -GEOMETRY = "D49" -# Set L1 tracking algorithm: -# 'HYBRID' (baseline, 4par fit) or 'HYBRID_DISPLACED' (extended, 5par fit). +GEOMETRY = "D76" +# Set L1 tracking algorithm: +# 'HYBRID' (baseline, 4par fit) or 'HYBRID_DISPLACED' (extended, 5par fit). +# 'HYBRID_NEWKF' (baseline, 4par fit, with bit-accurate KF emulation), +# 'HYBRID_REDUCED' to use the "Summer Chain" configuration with reduced inputs. # (Or legacy algos 'TMTT' or 'TRACKLET'). -L1TRKALGO = 'HYBRID' +L1TRKALGO = 'HYBRID' WRITE_DATA = False @@ -30,17 +32,18 @@ process.load('FWCore.MessageService.MessageLogger_cfi') process.MessageLogger.L1track = dict(limit = -1) process.MessageLogger.Tracklet = dict(limit = -1) +process.MessageLogger.TrackTriggerHPH = dict(limit = -1) -if GEOMETRY == "D49": - print "using geometry " + GEOMETRY + " (tilted)" +if GEOMETRY == "D49": + print("using geometry " + GEOMETRY + " (tilted)") process.load('Configuration.Geometry.GeometryExtended2026D49Reco_cff') process.load('Configuration.Geometry.GeometryExtended2026D49_cff') -elif GEOMETRY == "D76": - print "using geometry " + GEOMETRY + " (tilted)" +elif GEOMETRY == "D76": + print("using geometry " + GEOMETRY + " (tilted)") process.load('Configuration.Geometry.GeometryExtended2026D76Reco_cff') process.load('Configuration.Geometry.GeometryExtended2026D76_cff') else: - print "this is not a valid geometry!!!" + print("this is not a valid geometry!!!") process.load('Configuration.StandardSequences.EndOfProcess_cff') process.load('Configuration.StandardSequences.FrontierConditions_GlobalTag_cff') @@ -55,15 +58,18 @@ process.maxEvents = cms.untracked.PSet(input = cms.untracked.int32(10)) -#--- To use MCsamples scripts, defining functions get*data*(), -#--- follow instructions https://cernbox.cern.ch/index.php/s/enCnnfUZ4cpK7mT +#--- To use MCsamples scripts, defining functions get*data*() for easy MC access, +#--- follow instructions in https://github.com/cms-L1TK/MCsamples #from MCsamples.Scripts.getCMSdata_cfi import * #from MCsamples.Scripts.getCMSlocaldata_cfi import * if GEOMETRY == "D49": + inputMC = ["/store/relval/CMSSW_11_3_0_pre3/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v3_2026D49PU200_rsb-v1/00000/00260a30-734a-4a3a-a4b0-f836ce5502c6.root"] + +elif GEOMETRY == "D76": # Read data from card files (defines getCMSdataFromCards()): - #from MCsamples.RelVal_1120.PU200_TTbar_14TeV_cfi import * + #from MCsamples.RelVal_1130_D76.PU200_TTbar_14TeV_cfi import * #inputMC = getCMSdataFromCards() # Or read .root files from directory on local computer: @@ -71,18 +77,19 @@ #inputMC=getCMSlocaldata(dirName) # Or read specified dataset (accesses CMS DB, so use this method only occasionally): - #dataName="/RelValTTbar_14TeV/CMSSW_11_2_0_pre5-PU25ns_110X_mcRun4_realistic_v3_2026D49PU200-v1/GEN-SIM-DIGI-RAW" + #dataName="/RelValTTbar_14TeV/CMSSW_11_3_0_pre6-PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/GEN-SIM-DIGI-RAW" #inputMC=getCMSdata(dataName) # Or read specified .root file: - inputMC = ["/store/relval/CMSSW_11_3_0_pre3/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v3_2026D49PU200_rsb-v1/00000/00260a30-734a-4a3a-a4b0-f836ce5502c6.root"] - -elif GEOMETRY == "D76": inputMC = ["/store/relval/CMSSW_11_3_0_pre6/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/00000/00026541-6200-4eed-b6f8-d3a1fd720e9c.root"] + else: - print "this is not a valid geometry!!!" - + + print("this is not a valid geometry!!!") + process.source = cms.Source("PoolSource", fileNames = cms.untracked.vstring(*inputMC)) +# Use skipEvents to select particular single events for test vectors +#process.source = cms.Source("PoolSource", fileNames = cms.untracked.vstring(*inputMC), skipEvents = cms.untracked.uint32(11)) process.TFileService = cms.Service("TFileService", fileName = cms.string('TTbar_PU200_'+GEOMETRY+'.root'), closeFileFast = cms.untracked.bool(True)) process.Timing = cms.Service("Timing", summaryOnly = cms.untracked.bool(True)) @@ -94,7 +101,7 @@ process.load('L1Trigger.TrackTrigger.TrackTrigger_cff') -# remake stubs? +# remake stubs? #from L1Trigger.TrackTrigger.TTStubAlgorithmRegister_cfi import * #process.load("SimTracker.TrackTriggerAssociation.TrackTriggerAssociator_cff") @@ -102,11 +109,10 @@ #TTClusterAssociatorFromPixelDigis.digiSimLinks = cms.InputTag("simSiPixelDigis","Tracker") #process.TTClusterStub = cms.Path(process.TrackTriggerClustersStubs) -#process.TTClusterStubTruth = cms.Path(process.TrackTriggerAssociatorClustersStubs) +#process.TTClusterStubTruth = cms.Path(process.TrackTriggerAssociatorClustersStubs) # DTC emulation -process.load('L1Trigger.TrackerDTC.ProducerES_cff') process.load('L1Trigger.TrackerDTC.ProducerED_cff') # load code that analyzes DTCStubs @@ -142,8 +148,29 @@ L1TRK_NAME = "l1tTTTracksFromExtendedTrackletEmulation" L1TRK_LABEL = "Level1TTTracks" L1TRUTH_NAME = "TTTrackAssociatorFromPixelDigisExtended" - -# LEGACY ALGORITHM (EXPERTS ONLY): TRACKLET + +# HYBRID_NEWKF: prompt tracking or reduced +elif (L1TRKALGO == 'HYBRID_NEWKF' or L1TRKALGO == 'HYBRID_REDUCED'): + process.load( 'L1Trigger.TrackFindingTracklet.Producer_cff' ) + NHELIXPAR = 4 + L1TRK_NAME = process.TrackFindingTrackletProducer_params.LabelTT.value() + L1TRK_LABEL = process.TrackFindingTrackletProducer_params.BranchAcceptedTracks.value() + L1TRUTH_NAME = "TTTrackAssociatorFromPixelDigis" + process.TTTrackAssociatorFromPixelDigis.TTTracks = cms.VInputTag( cms.InputTag(L1TRK_NAME, L1TRK_LABEL) ) + process.HybridNewKF = cms.Sequence(process.L1HybridTracks + process.TrackFindingTrackletProducerTBout + process.TrackFindingTrackletProducerKFin + process.TrackFindingTrackletProducerKF + process.TrackFindingTrackletProducerTT + process.TrackFindingTrackletProducerAS + process.TrackFindingTrackletProducerKFout) + process.TTTracksEmulation = cms.Path(process.HybridNewKF) + #process.TTTracksEmulationWithTruth = cms.Path(process.HybridNewKF + process.TrackTriggerAssociatorTracks) + # Optionally include code producing performance plots & end-of-job summary. + process.load( 'SimTracker.TrackTriggerAssociation.StubAssociator_cff' ) + process.load( 'L1Trigger.TrackFindingTracklet.Analyzer_cff' ) + process.TTTracksEmulationWithTruth = cms.Path(process.HybridNewKF + process.TrackTriggerAssociatorTracks + process.StubAssociator + process.TrackFindingTrackletAnalyzerTracklet + process.TrackFindingTrackletAnalyzerTBout + process.TrackFindingTrackletAnalyzerKFin + process.TrackFindingTrackletAnalyzerKF + process.TrackFindingTrackletAnalyzerKFout) + from L1Trigger.TrackFindingTracklet.Customize_cff import * + if (L1TRKALGO == 'HYBRID_NEWKF'): + fwConfig( process ) + if (L1TRKALGO == 'HYBRID_REDUCED'): + reducedConfig( process ) + +# LEGACY ALGORITHM (EXPERTS ONLY): TRACKLET elif (L1TRKALGO == 'TRACKLET'): print "\n WARNING: This is not the baseline algorithm! Prefer HYBRID or HYBRID_DISPLACED!" print "\n To run the Tracklet-only algorithm, ensure you have commented out 'CXXFLAGS=-DUSEHYBRID' in BuildFile.xml & recompiled! \n" @@ -154,9 +181,9 @@ L1TRK_LABEL = "Level1TTTracks" L1TRUTH_NAME = "TTTrackAssociatorFromPixelDigis" -# LEGACY ALGORITHM (EXPERTS ONLY): TMTT +# LEGACY ALGORITHM (EXPERTS ONLY): TMTT elif (L1TRKALGO == 'TMTT'): - print "\n WARNING: This is not the baseline algorithm! Prefer HYBRID or HYBRID_DISPLACED! \n" + print("\n WARNING: This is not the baseline algorithm! Prefer HYBRID or HYBRID_DISPLACED! \n") process.load("L1Trigger.TrackFindingTMTT.TMTrackProducer_Ultimate_cff") L1TRK_PROC = process.TMTrackProducer L1TRK_NAME = "TMTrackProducer" @@ -172,15 +199,14 @@ process.TTTracksEmulationWithTruth = cms.Path(process.offlineBeamSpot*L1TRK_PROC*process.TrackTriggerAssociatorTracks) else: - print "ERROR: Unknown L1TRKALGO option" + print("ERROR: Unknown L1TRKALGO option") exit(1) - ############################################################ # Define the track ntuple process, MyProcess is the (unsigned) PDGID corresponding to the process which is run # e.g. single electron/positron = 11 # single pion+/pion- = 211 -# single muon+/muon- = 13 +# single muon+/muon- = 13 # pions in jets = 6 # taus = 15 # all TPs = 1 @@ -195,11 +221,11 @@ L1Tk_minNStub = cms.int32(4), # L1 tracks with >= 4 stubs TP_minNStub = cms.int32(4), # require TP to have >= X number of stubs associated with it TP_minNStubLayer = cms.int32(4), # require TP to have stubs in >= X layers/disks - TP_minPt = cms.double(2.0), # only save TPs with pt > X GeV + TP_minPt = cms.double(1.9), # only save TPs with pt > X GeV TP_maxEta = cms.double(2.5), # only save TPs with |eta| < X TP_maxZ0 = cms.double(30.0), # only save TPs with |z0| < X cm L1TrackInputTag = cms.InputTag(L1TRK_NAME, L1TRK_LABEL), # TTTrack input - MCTruthTrackInputTag = cms.InputTag(L1TRUTH_NAME, L1TRK_LABEL), # MCTruth input + MCTruthTrackInputTag = cms.InputTag(L1TRUTH_NAME, L1TRK_LABEL), # MCTruth input # other input collections L1StubInputTag = cms.InputTag("TTStubsFromPhase2TrackerDigis","StubAccepted"), MCTruthClusterInputTag = cms.InputTag("TTClusterAssociatorFromPixelDigis", "ClusterAccepted"), @@ -221,7 +247,7 @@ # use this if you want to re-run the stub making # process.schedule = cms.Schedule(process.TTClusterStub,process.TTClusterStubTruth,process.dtc,process.TTTracksEmulationWithTruth,process.ana) -# use this if cluster/stub associators not available +# use this if cluster/stub associators not available # process.schedule = cms.Schedule(process.TTClusterStubTruth,process.dtc,process.TTTracksEmulationWithTruth,process.ana) # use this to only run tracking + track associator @@ -248,4 +274,3 @@ process.pd = cms.EndPath(process.writeDataset) process.schedule.append(process.pd) - diff --git a/L1Trigger/TrackFindingTracklet/test/L1TrackNtuplePlot.C b/L1Trigger/TrackFindingTracklet/test/L1TrackNtuplePlot.C index 6643d69673e39..f026c2ce6cd31 100644 --- a/L1Trigger/TrackFindingTracklet/test/L1TrackNtuplePlot.C +++ b/L1Trigger/TrackFindingTracklet/test/L1TrackNtuplePlot.C @@ -118,6 +118,7 @@ void L1TrackNtuplePlot(TString type, int n_match_ptg40 = 0; // counters for total track rates + int ntrk = 0; int ntrk_pt2 = 0; int ntrk_pt3 = 0; int ntrk_pt10 = 0; @@ -466,9 +467,21 @@ void L1TrackNtuplePlot(TString type, TString ptrange[nRANGE] = {"0-5", "5-10", "10-15", "15-20", "20-25", "25-30", "30-35", "35-40", "40-45", "45-50", "50-55", "55-60", "60-65", "65-70", "70-75", "75-80", "80-85", "85-90", "90-95", "95-100"}; - const int nRANGE_L = 12; - TString ptrange_L[nRANGE] = { - "2-2.5", "2.5-3", "3-3.5", "3.5-4", "4-4.5", "4.5-5", "5-5.5", "5.5-6", "6-6.5", "6.5-7", "7-7.5", "7.5-8"}; + const float pt_resmin = 1.5; + const int nRANGE_L = 13; + TString ptrange_L[nRANGE_L] = {"1.5-2", + "2-2.5", + "2.5-3", + "3-3.5", + "3.5-4", + "4-4.5", + "4.5-5", + "5-5.5", + "5.5-6", + "6-6.5", + "6.5-7", + "7-7.5", + "7.5-8"}; TH1F* h_absResVsPt_pt[nRANGE]; TH1F* h_absResVsPt_ptRel[nRANGE]; @@ -528,9 +541,11 @@ void L1TrackNtuplePlot(TString type, // resolution vs. eta histograms - const int nETARANGE = 24; - TString etarange[nETARANGE] = {"0.1", "0.2", "0.3", "0.4", "0.5", "0.6", "0.7", "0.8", "0.9", "1.0", "1.1", "1.2", - "1.3", "1.4", "1.5", "1.6", "1.7", "1.8", "1.9", "2.0", "2.1", "2.2", "2.3", "2.4"}; + const float eta_resmax = 2.5; + const int nETARANGE = 25; + TString etarange[nETARANGE] = {"0.1", "0.2", "0.3", "0.4", "0.5", "0.6", "0.7", "0.8", "0.9", + "1.0", "1.1", "1.2", "1.3", "1.4", "1.5", "1.6", "1.7", "1.8", + "1.9", "2.0", "2.1", "2.2", "2.3", "2.4", "2.5"}; /* const int nETARANGE = 12; TString etarange[nETARANGE] = {"0.2","0.4","0.6","0.8","1.0", @@ -961,6 +976,8 @@ void L1TrackNtuplePlot(TString type, new TH1F("ntrk_genuine_pt10", ";# genuine tracks (p_{T} > 10 GeV) / event; Events", 100, 0, 100.0); // Max N tracks from a sector per event + TH1F* h_ntrkPerSector_all = + new TH1F("ntrkPerSector_all", ";Max. # tracks from a sector / event; Events", 50, 0, 100.0); TH1F* h_ntrkPerSector_pt2 = new TH1F("ntrkPerSector_pt2", ";Max. # tracks from a sector (p_{T} > 2 GeV) / event; Events", 50, 0, 100.0); TH1F* h_ntrkPerSector_pt3 = @@ -968,6 +985,10 @@ void L1TrackNtuplePlot(TString type, TH1F* h_ntrkPerSector_pt4 = new TH1F("ntrkPerSector_pt4", ";Max. # tracks from a sector (p_{T} > 10 GeV) / event; Events", 50, 0, 100.0); + // number of tracks vs. efficiency (eta, pT) + TH1F* h_trk_pt = new TH1F("trk_pt", Form(";Track p_{T} (GeV);Tracks / 0.5 GeV"), 200, 0., 100.); + TH1F* h_trk_eta = new TH1F("trk_eta", Form(";Track #eta;Tracks / 0.026"), 200, -2.6, 2.6); + // ---------------------------------------------------------------------------------------------------------------- // * * * * * S T A R T O F A C T U A L R U N N I N G O N E V E N T S * * * * * // ---------------------------------------------------------------------------------------------------------------- @@ -985,18 +1006,18 @@ void L1TrackNtuplePlot(TString type, // sumpt in jets if (TP_select_injet > 0) { for (int ij=0; ij<(int)jet_tp_sumpt->size(); ij++) { - + float fraction = 0; float fractionMatch = 0; if (jet_tp_sumpt->at(ij) > 0) { fraction = jet_trk_sumpt->at(ij)/jet_tp_sumpt->at(ij); fractionMatch = jet_matchtrk_sumpt->at(ij)/jet_tp_sumpt->at(ij); } - + h_jet_tp_sumpt_vspt->Fill(jet_tp_sumpt->at(ij),1.0); h_jet_trk_sumpt_vspt->Fill(jet_tp_sumpt->at(ij),fraction); h_jet_matchtrk_sumpt_vspt->Fill(jet_tp_sumpt->at(ij),fractionMatch); - + h_jet_tp_sumpt_vseta->Fill(jet_eta->at(ij),1.0); h_jet_trk_sumpt_vseta->Fill(jet_eta->at(ij),fraction); h_jet_matchtrk_sumpt_vseta->Fill(jet_eta->at(ij),fractionMatch); @@ -1015,6 +1036,7 @@ void L1TrackNtuplePlot(TString type, int ntrkevt_genuine_pt3 = 0; int ntrkevt_genuine_pt10 = 0; + vector nTrksPerSector_all(9, 0); vector nTrksPerSector_pt2(9, 0); vector nTrksPerSector_pt3(9, 0); vector nTrksPerSector_pt4(9, 0); @@ -1023,6 +1045,11 @@ void L1TrackNtuplePlot(TString type, // ---------------------------------------------------------------------------------------------------------------- // track properties + // ---------------------------------------------------------------------------------------------------------------- + // Fill number of tracks vs track param + h_trk_pt->Fill(trk_pt->at(it)); + h_trk_eta->Fill(trk_eta->at(it)); + // fill all trk chi2 & chi2/dof histograms, including for chi2 r-phi and chi2 r-z int ndof = 2 * trk_nstub->at(it) - 4; float chi2 = trk_chi2->at(it); @@ -1075,7 +1102,9 @@ void L1TrackNtuplePlot(TString type, if (TP_select_injet == 3 && trk_injet_vhighpt->at(it) == 0) continue; } - + ntrk++; + if (trk_pt->at(it) >= 0.0) + ++nTrksPerSector_all.at(trk_phiSector->at(it) % 9); if (std::abs(trk_eta->at(it)) > TP_maxEta) continue; if (trk_pt->at(it) < TP_minPt) @@ -1157,6 +1186,7 @@ void L1TrackNtuplePlot(TString type, h_ntrk_genuine_pt3->Fill(ntrkevt_genuine_pt3); h_ntrk_genuine_pt10->Fill(ntrkevt_genuine_pt10); + h_ntrkPerSector_all->Fill(*std::max_element(nTrksPerSector_all.begin(), nTrksPerSector_all.end())); h_ntrkPerSector_pt2->Fill(*std::max_element(nTrksPerSector_pt2.begin(), nTrksPerSector_pt2.end())); h_ntrkPerSector_pt3->Fill(*std::max_element(nTrksPerSector_pt3.begin(), nTrksPerSector_pt3.end())); h_ntrkPerSector_pt4->Fill(*std::max_element(nTrksPerSector_pt4.begin(), nTrksPerSector_pt4.end())); @@ -1537,14 +1567,14 @@ void L1TrackNtuplePlot(TString type, } } - for (int im = 4; im < nRANGE_L + 4; im++) { + for (int im = 3; im < nRANGE_L + 3; im++) { if ((tp_pt->at(it) > (float)im * 0.5) && (tp_pt->at(it) <= (float)(im + 1) * 0.5)) { - h_absResVsPt_pt_L[im - 4]->Fill(std::abs(matchtrk_pt->at(it) - tp_pt->at(it))); - h_absResVsPt_ptRel_L[im - 4]->Fill(std::abs((matchtrk_pt->at(it) - tp_pt->at(it))) / tp_pt->at(it)); - h_absResVsPt_z0_L[im - 4]->Fill(std::abs(matchtrk_z0->at(it) - tp_z0->at(it))); - h_absResVsPt_phi_L[im - 4]->Fill(std::abs(matchtrk_phi->at(it) - tp_phi->at(it))); - h_absResVsPt_eta_L[im - 4]->Fill(std::abs(matchtrk_eta->at(it) - tp_eta->at(it))); - h_absResVsPt_d0_L[im - 4]->Fill(std::abs(matchtrk_d0->at(it) - tp_d0->at(it))); + h_absResVsPt_pt_L[im - 3]->Fill(std::abs(matchtrk_pt->at(it) - tp_pt->at(it))); + h_absResVsPt_ptRel_L[im - 3]->Fill(std::abs((matchtrk_pt->at(it) - tp_pt->at(it))) / tp_pt->at(it)); + h_absResVsPt_z0_L[im - 3]->Fill(std::abs(matchtrk_z0->at(it) - tp_z0->at(it))); + h_absResVsPt_phi_L[im - 3]->Fill(std::abs(matchtrk_phi->at(it) - tp_phi->at(it))); + h_absResVsPt_eta_L[im - 3]->Fill(std::abs(matchtrk_eta->at(it) - tp_eta->at(it))); + h_absResVsPt_d0_L[im - 3]->Fill(std::abs(matchtrk_d0->at(it) - tp_d0->at(it))); } } @@ -1613,6 +1643,7 @@ void L1TrackNtuplePlot(TString type, } // end of matched track loop } // end of event loop + // ---------------------------------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------------------------------- @@ -1725,43 +1756,43 @@ void L1TrackNtuplePlot(TString type, new TH1F("resVsPt2_d0_99", ";Tracking particle p_{T} [GeV]; d_{0} resolution [cm]", 20, 0, 100); TH1F* h2_resVsPt_pt_L_68 = - new TH1F("resVsPt2_pt_L_68", ";Tracking particle p_{T} [GeV]; p_{T} resolution [GeV]", nRANGE_L, 2, 8); - TH1F* h2_resVsPt_ptRel_L_68 = - new TH1F("resVsPt2_ptRel_L_68", ";Tracking particle p_{T} [GeV]; p_{T} resolution / p_{T}", nRANGE_L, 2, 8); + new TH1F("resVsPt2_pt_L_68", ";Tracking particle p_{T} [GeV]; p_{T} resolution [GeV]", nRANGE_L, pt_resmin, 8); + TH1F* h2_resVsPt_ptRel_L_68 = new TH1F( + "resVsPt2_ptRel_L_68", ";Tracking particle p_{T} [GeV]; p_{T} resolution / p_{T}", nRANGE_L, pt_resmin, 8); TH1F* h2_resVsPt_z0_L_68 = - new TH1F("resVsPt2_z0_L_68", ";Tracking particle p_{T} [GeV]; z_{0} resolution [cm]", nRANGE_L, 2, 8); + new TH1F("resVsPt2_z0_L_68", ";Tracking particle p_{T} [GeV]; z_{0} resolution [cm]", nRANGE_L, pt_resmin, 8); TH1F* h2_resVsPt_phi_L_68 = - new TH1F("resVsPt2_phi_L_68", ";Tracking particle p_{T} [GeV]; #phi resolution [rad]", nRANGE_L, 2, 8); + new TH1F("resVsPt2_phi_L_68", ";Tracking particle p_{T} [GeV]; #phi resolution [rad]", nRANGE_L, pt_resmin, 8); TH1F* h2_resVsPt_eta_L_68 = - new TH1F("resVsPt2_eta_L_68", ";Tracking particle p_{T} [GeV]; #eta resolution", nRANGE_L, 2, 8); + new TH1F("resVsPt2_eta_L_68", ";Tracking particle p_{T} [GeV]; #eta resolution", nRANGE_L, pt_resmin, 8); TH1F* h2_resVsPt_d0_L_68 = - new TH1F("resVsPt2_d0_L_68", ";Tracking particle p_{T} [GeV]; d_{0} resolution [cm]", nRANGE_L, 2, 8); + new TH1F("resVsPt2_d0_L_68", ";Tracking particle p_{T} [GeV]; d_{0} resolution [cm]", nRANGE_L, pt_resmin, 8); TH1F* h2_resVsPt_pt_L_90 = - new TH1F("resVsPt2_pt_L_90", ";Tracking particle p_{T} [GeV]; p_{T} resolution [GeV]", nRANGE_L, 2, 8); - TH1F* h2_resVsPt_ptRel_L_90 = - new TH1F("resVsPt2_ptRel_L_90", ";Tracking particle p_{T} [GeV]; p_{T} resolution / p_{T}", nRANGE_L, 2, 8); + new TH1F("resVsPt2_pt_L_90", ";Tracking particle p_{T} [GeV]; p_{T} resolution [GeV]", nRANGE_L, pt_resmin, 8); + TH1F* h2_resVsPt_ptRel_L_90 = new TH1F( + "resVsPt2_ptRel_L_90", ";Tracking particle p_{T} [GeV]; p_{T} resolution / p_{T}", nRANGE_L, pt_resmin, 8); TH1F* h2_resVsPt_z0_L_90 = - new TH1F("resVsPt2_z0_L_90", ";Tracking particle p_{T} [GeV]; z_{0} resolution [cm]", nRANGE_L, 2, 8); + new TH1F("resVsPt2_z0_L_90", ";Tracking particle p_{T} [GeV]; z_{0} resolution [cm]", nRANGE_L, pt_resmin, 8); TH1F* h2_resVsPt_phi_L_90 = - new TH1F("resVsPt2_phi_L_90", ";Tracking particle p_{T} [GeV]; #phi resolution [rad]", nRANGE_L, 2, 8); + new TH1F("resVsPt2_phi_L_90", ";Tracking particle p_{T} [GeV]; #phi resolution [rad]", nRANGE_L, pt_resmin, 8); TH1F* h2_resVsPt_eta_L_90 = - new TH1F("resVsPt2_eta_L_90", ";Tracking particle p_{T} [GeV]; #eta resolution", nRANGE_L, 2, 8); + new TH1F("resVsPt2_eta_L_90", ";Tracking particle p_{T} [GeV]; #eta resolution", nRANGE_L, pt_resmin, 8); TH1F* h2_resVsPt_d0_L_90 = - new TH1F("resVsPt2_d0_L_90", ";Tracking particle p_{T} [GeV]; d_{0} resolution [cm]", nRANGE_L, 2, 8); + new TH1F("resVsPt2_d0_L_90", ";Tracking particle p_{T} [GeV]; d_{0} resolution [cm]", nRANGE_L, pt_resmin, 8); TH1F* h2_resVsPt_pt_L_99 = - new TH1F("resVsPt2_pt_L_99", ";Tracking particle p_{T} [GeV]; p_{T} resolution [cm]", nRANGE_L, 2, 8); - TH1F* h2_resVsPt_ptRel_L_99 = - new TH1F("resVsPt2_ptRel_L_99", ";Tracking particle p_{T} [GeV]; p_{T} resolution / p_{T}", nRANGE_L, 2, 8); + new TH1F("resVsPt2_pt_L_99", ";Tracking particle p_{T} [GeV]; p_{T} resolution [cm]", nRANGE_L, pt_resmin, 8); + TH1F* h2_resVsPt_ptRel_L_99 = new TH1F( + "resVsPt2_ptRel_L_99", ";Tracking particle p_{T} [GeV]; p_{T} resolution / p_{T}", nRANGE_L, pt_resmin, 8); TH1F* h2_resVsPt_z0_L_99 = - new TH1F("resVsPt2_z0_L_99", ";Tracking particle p_{T} [GeV]; z_{0} resolution [cm]", nRANGE_L, 2, 8); + new TH1F("resVsPt2_z0_L_99", ";Tracking particle p_{T} [GeV]; z_{0} resolution [cm]", nRANGE_L, pt_resmin, 8); TH1F* h2_resVsPt_phi_L_99 = - new TH1F("resVsPt2_phi_L_99", ";Tracking particle p_{T} [GeV]; #phi resolution [rad]", nRANGE_L, 2, 8); + new TH1F("resVsPt2_phi_L_99", ";Tracking particle p_{T} [GeV]; #phi resolution [rad]", nRANGE_L, pt_resmin, 8); TH1F* h2_resVsPt_eta_L_99 = - new TH1F("resVsPt2_eta_L_99", ";Tracking particle p_{T} [GeV]; #eta resolution", nRANGE_L, 2, 8); + new TH1F("resVsPt2_eta_L_99", ";Tracking particle p_{T} [GeV]; #eta resolution", nRANGE_L, pt_resmin, 8); TH1F* h2_resVsPt_d0_L_99 = - new TH1F("resVsPt2_d0_L_99", ";Tracking particle p_{T} [GeV]; d_{0} resolution [cm]", nRANGE_L, 2, 8); + new TH1F("resVsPt2_d0_L_99", ";Tracking particle p_{T} [GeV]; d_{0} resolution [cm]", nRANGE_L, pt_resmin, 8); for (int i = 0; i < nRANGE; i++) { // set bin content and error @@ -1868,160 +1899,167 @@ void L1TrackNtuplePlot(TString type, } // resolution vs. eta histograms - TH1F* h2_resVsEta_eta = new TH1F("resVsEta_eta", ";Tracking particle |#eta|; #eta resolution", nETARANGE, 0, 2.4); - TH1F* h2_resVsEta_eta_L = new TH1F("resVsEta_eta_L", ";Tracking particle |#eta|; #eta resolution", nETARANGE, 0, 2.4); - TH1F* h2_resVsEta_eta_H = new TH1F("resVsEta_eta_H", ";Tracking particle |#eta|; #eta resolution", nETARANGE, 0, 2.4); - - TH1F* h2_resVsEta_z0 = new TH1F("resVsEta_z0", ";Tracking particle |#eta|; z_{0} resolution [cm]", nETARANGE, 0, 2.4); + TH1F* h2_resVsEta_eta = + new TH1F("resVsEta_eta", ";Tracking particle |#eta|; #eta resolution", nETARANGE, 0, eta_resmax); + TH1F* h2_resVsEta_eta_L = + new TH1F("resVsEta_eta_L", ";Tracking particle |#eta|; #eta resolution", nETARANGE, 0, eta_resmax); + TH1F* h2_resVsEta_eta_H = + new TH1F("resVsEta_eta_H", ";Tracking particle |#eta|; #eta resolution", nETARANGE, 0, eta_resmax); + + TH1F* h2_resVsEta_z0 = + new TH1F("resVsEta_z0", ";Tracking particle |#eta|; z_{0} resolution [cm]", nETARANGE, 0, eta_resmax); TH1F* h2_resVsEta_z0_L = - new TH1F("resVsEta_z0_L", ";Tracking particle |#eta|; z_{0} resolution [cm]", nETARANGE, 0, 2.4); + new TH1F("resVsEta_z0_L", ";Tracking particle |#eta|; z_{0} resolution [cm]", nETARANGE, 0, eta_resmax); TH1F* h2_resVsEta_z0_H = - new TH1F("resVsEta_z0_H", ";Tracking particle |#eta|; z_{0} resolution [cm]", nETARANGE, 0, 2.4); + new TH1F("resVsEta_z0_H", ";Tracking particle |#eta|; z_{0} resolution [cm]", nETARANGE, 0, eta_resmax); TH1F* h2_resVsEta_phi = - new TH1F("resVsEta_phi", ";Tracking particle |#eta|; #phi resolution [rad]", nETARANGE, 0, 2.4); + new TH1F("resVsEta_phi", ";Tracking particle |#eta|; #phi resolution [rad]", nETARANGE, 0, eta_resmax); TH1F* h2_resVsEta_phi_L = - new TH1F("resVsEta_phi_L", ";Tracking particle |#eta|; #phi resolution [rad]", nETARANGE, 0, 2.4); + new TH1F("resVsEta_phi_L", ";Tracking particle |#eta|; #phi resolution [rad]", nETARANGE, 0, eta_resmax); TH1F* h2_resVsEta_phi_H = - new TH1F("resVsEta_phi_H", ";Tracking particle |#eta|; #phi resolution [rad]", nETARANGE, 0, 2.4); + new TH1F("resVsEta_phi_H", ";Tracking particle |#eta|; #phi resolution [rad]", nETARANGE, 0, eta_resmax); TH1F* h2_resVsEta_ptRel = - new TH1F("resVsEta_ptRel", ";Tracking particle |#eta|; p_{T} resolution / p_{T}", nETARANGE, 0, 2.4); + new TH1F("resVsEta_ptRel", ";Tracking particle |#eta|; p_{T} resolution / p_{T}", nETARANGE, 0, eta_resmax); TH1F* h2_resVsEta_ptRel_L = - new TH1F("resVsEta_ptRel_L", ";Tracking particle |#eta|; p_{T} resolution / p_{T}", nETARANGE, 0, 2.4); + new TH1F("resVsEta_ptRel_L", ";Tracking particle |#eta|; p_{T} resolution / p_{T}", nETARANGE, 0, eta_resmax); TH1F* h2_resVsEta_ptRel_H = - new TH1F("resVsEta_ptRel_H", ";Tracking particle |#eta|; p_{T} resolution / p_{T}", nETARANGE, 0, 2.4); + new TH1F("resVsEta_ptRel_H", ";Tracking particle |#eta|; p_{T} resolution / p_{T}", nETARANGE, 0, eta_resmax); - TH1F* h2_resVsEta_d0 = new TH1F("resVsEta_d0", ";Tracking particle |#eta|; d_{0} resolution [cm]", nETARANGE, 0, 2.4); + TH1F* h2_resVsEta_d0 = + new TH1F("resVsEta_d0", ";Tracking particle |#eta|; d_{0} resolution [cm]", nETARANGE, 0, eta_resmax); TH1F* h2_resVsEta_d0_L = - new TH1F("resVsEta_d0_L", ";Tracking particle |#eta|; d_{0} resolution [cm]", nETARANGE, 0, 2.4); + new TH1F("resVsEta_d0_L", ";Tracking particle |#eta|; d_{0} resolution [cm]", nETARANGE, 0, eta_resmax); TH1F* h2_resVsEta_d0_H = - new TH1F("resVsEta_d0_H", ";Tracking particle |#eta|; d_{0} resolution [cm]", nETARANGE, 0, 2.4); + new TH1F("resVsEta_d0_H", ";Tracking particle |#eta|; d_{0} resolution [cm]", nETARANGE, 0, eta_resmax); // mean of residuals TH1F* h2_mresVsEta_eta = - new TH1F("mresVsEta_eta", ";Tracking particle |#eta|; Mean(#eta residual)", nETARANGE, 0, 2.4); + new TH1F("mresVsEta_eta", ";Tracking particle |#eta|; Mean(#eta residual)", nETARANGE, 0, eta_resmax); TH1F* h2_mresVsEta_z0 = - new TH1F("mresVsEta_z0", ";Tracking particle |#eta|; Mean(z_{0} residual) [cm]", nETARANGE, 0, 2.4); + new TH1F("mresVsEta_z0", ";Tracking particle |#eta|; Mean(z_{0} residual) [cm]", nETARANGE, 0, eta_resmax); TH1F* h2_mresVsEta_phi = - new TH1F("mresVsEta_phi", ";Tracking particle |#eta|; Mean(phi residual) [rad]", nETARANGE, 0, 2.4); + new TH1F("mresVsEta_phi", ";Tracking particle |#eta|; Mean(phi residual) [rad]", nETARANGE, 0, eta_resmax); TH1F* h2_mresVsEta_ptRel = - new TH1F("mresVsEta_ptRel", ";Tracking particle |#eta|; Mean(ptrel residual)", nETARANGE, 0, 2.4); + new TH1F("mresVsEta_ptRel", ";Tracking particle |#eta|; Mean(ptrel residual)", nETARANGE, 0, eta_resmax); // 68 / 90 / 99% residuals TH1F* h2_resVsEta_eta_68 = - new TH1F("resVsEta_eta_68", ";Tracking particle |#eta|; #eta resolution", nETARANGE, 0, 2.4); + new TH1F("resVsEta_eta_68", ";Tracking particle |#eta|; #eta resolution", nETARANGE, 0, eta_resmax); TH1F* h2_resVsEta_eta_90 = - new TH1F("resVsEta_eta_90", ";Tracking particle |#eta|; #eta resolution", nETARANGE, 0, 2.4); + new TH1F("resVsEta_eta_90", ";Tracking particle |#eta|; #eta resolution", nETARANGE, 0, eta_resmax); TH1F* h2_resVsEta_eta_99 = - new TH1F("resVsEta_eta_99", ";Tracking particle |#eta|; #eta resolution", nETARANGE, 0, 2.4); + new TH1F("resVsEta_eta_99", ";Tracking particle |#eta|; #eta resolution", nETARANGE, 0, eta_resmax); TH1F* h2_resVsEta_z0_68 = - new TH1F("resVsEta_z0_68", ";Tracking particle |#eta|; z_{0} resolution [cm]", nETARANGE, 0, 2.4); + new TH1F("resVsEta_z0_68", ";Tracking particle |#eta|; z_{0} resolution [cm]", nETARANGE, 0, eta_resmax); TH1F* h2_resVsEta_z0_90 = - new TH1F("resVsEta_z0_90", ";Tracking particle |#eta|; z_{0} resolution [cm]", nETARANGE, 0, 2.4); + new TH1F("resVsEta_z0_90", ";Tracking particle |#eta|; z_{0} resolution [cm]", nETARANGE, 0, eta_resmax); TH1F* h2_resVsEta_z0_99 = - new TH1F("resVsEta_z0_99", ";Tracking particle |#eta|; z_{0} resolution [cm]", nETARANGE, 0, 2.4); + new TH1F("resVsEta_z0_99", ";Tracking particle |#eta|; z_{0} resolution [cm]", nETARANGE, 0, eta_resmax); TH1F* h2_resVsEta_phi_68 = - new TH1F("resVsEta_phi_68", ";Tracking particle |#eta|; #phi resolution [rad]", nETARANGE, 0, 2.4); + new TH1F("resVsEta_phi_68", ";Tracking particle |#eta|; #phi resolution [rad]", nETARANGE, 0, eta_resmax); TH1F* h2_resVsEta_phi_90 = - new TH1F("resVsEta_phi_90", ";Tracking particle |#eta|; #phi resolution [rad]", nETARANGE, 0, 2.4); + new TH1F("resVsEta_phi_90", ";Tracking particle |#eta|; #phi resolution [rad]", nETARANGE, 0, eta_resmax); TH1F* h2_resVsEta_phi_99 = - new TH1F("resVsEta_phi_99", ";Tracking particle |#eta|; #phi resolution [rad]", nETARANGE, 0, 2.4); + new TH1F("resVsEta_phi_99", ";Tracking particle |#eta|; #phi resolution [rad]", nETARANGE, 0, eta_resmax); TH1F* h2_resVsEta_ptRel_68 = - new TH1F("resVsEta_ptRel_68", ";Tracking particle |#eta|; p_{T} resolution / p_{T}", nETARANGE, 0, 2.4); + new TH1F("resVsEta_ptRel_68", ";Tracking particle |#eta|; p_{T} resolution / p_{T}", nETARANGE, 0, eta_resmax); TH1F* h2_resVsEta_ptRel_90 = - new TH1F("resVsEta_ptRel_90", ";Tracking particle |#eta|; p_{T} resolution / p_{T}", nETARANGE, 0, 2.4); + new TH1F("resVsEta_ptRel_90", ";Tracking particle |#eta|; p_{T} resolution / p_{T}", nETARANGE, 0, eta_resmax); TH1F* h2_resVsEta_ptRel_99 = - new TH1F("resVsEta_ptRel_99", ";Tracking particle |#eta|; p_{T} resolution / p_{T}", nETARANGE, 0, 2.4); + new TH1F("resVsEta_ptRel_99", ";Tracking particle |#eta|; p_{T} resolution / p_{T}", nETARANGE, 0, eta_resmax); TH1F* h2_resVsEta_d0_68 = - new TH1F("resVsEta_d0_68", ";Tracking particle |#eta|; d_{0} resolution [cm]", nETARANGE, 0, 2.4); + new TH1F("resVsEta_d0_68", ";Tracking particle |#eta|; d_{0} resolution [cm]", nETARANGE, 0, eta_resmax); TH1F* h2_resVsEta_d0_90 = - new TH1F("resVsEta_d0_90", ";Tracking particle |#eta|; d_{0} resolution [cm]", nETARANGE, 0, 2.4); + new TH1F("resVsEta_d0_90", ";Tracking particle |#eta|; d_{0} resolution [cm]", nETARANGE, 0, eta_resmax); TH1F* h2_resVsEta_d0_99 = - new TH1F("resVsEta_d0_99", ";Tracking particle |#eta|; d_{0} resolution [cm]", nETARANGE, 0, 2.4); + new TH1F("resVsEta_d0_99", ";Tracking particle |#eta|; d_{0} resolution [cm]", nETARANGE, 0, eta_resmax); TH1F* h2_resVsEta_eta_L_68 = - new TH1F("resVsEta_eta_L_68", ";Tracking particle |#eta|; #eta resolution", nETARANGE, 0, 2.4); + new TH1F("resVsEta_eta_L_68", ";Tracking particle |#eta|; #eta resolution", nETARANGE, 0, eta_resmax); TH1F* h2_resVsEta_z0_L_68 = - new TH1F("resVsEta_z0_L_68", ";Tracking particle |#eta|; z_{0} resolution [cm]", nETARANGE, 0, 2.4); + new TH1F("resVsEta_z0_L_68", ";Tracking particle |#eta|; z_{0} resolution [cm]", nETARANGE, 0, eta_resmax); TH1F* h2_resVsEta_phi_L_68 = - new TH1F("resVsEta_phi_L_68", ";Tracking particle |#eta|; #phi resolution [rad]", nETARANGE, 0, 2.4); + new TH1F("resVsEta_phi_L_68", ";Tracking particle |#eta|; #phi resolution [rad]", nETARANGE, 0, eta_resmax); TH1F* h2_resVsEta_ptRel_L_68 = - new TH1F("resVsEta_ptRel_L_68", ";Tracking particle |#eta|; p_{T} resolution / p_{T}", nETARANGE, 0, 2.4); + new TH1F("resVsEta_ptRel_L_68", ";Tracking particle |#eta|; p_{T} resolution / p_{T}", nETARANGE, 0, eta_resmax); TH1F* h2_resVsEta_d0_L_68 = - new TH1F("resVsEta_d0_L_68", ";Tracking particle |#eta|; d_{0} resolution [cm]", nETARANGE, 0, 2.4); + new TH1F("resVsEta_d0_L_68", ";Tracking particle |#eta|; d_{0} resolution [cm]", nETARANGE, 0, eta_resmax); TH1F* h2_resVsEta_eta_L_90 = - new TH1F("resVsEta_eta_L_90", ";Tracking particle |#eta|; #eta resolution", nETARANGE, 0, 2.4); + new TH1F("resVsEta_eta_L_90", ";Tracking particle |#eta|; #eta resolution", nETARANGE, 0, eta_resmax); TH1F* h2_resVsEta_z0_L_90 = - new TH1F("resVsEta_z0_L_90", ";Tracking particle |#eta|; z_{0} resolution [cm]", nETARANGE, 0, 2.4); + new TH1F("resVsEta_z0_L_90", ";Tracking particle |#eta|; z_{0} resolution [cm]", nETARANGE, 0, eta_resmax); TH1F* h2_resVsEta_phi_L_90 = - new TH1F("resVsEta_phi_L_90", ";Tracking particle |#eta|; #phi resolution [rad]", nETARANGE, 0, 2.4); + new TH1F("resVsEta_phi_L_90", ";Tracking particle |#eta|; #phi resolution [rad]", nETARANGE, 0, eta_resmax); TH1F* h2_resVsEta_ptRel_L_90 = - new TH1F("resVsEta_ptRel_L_90", ";Tracking particle |#eta|; p_{T} resolution / p_{T}", nETARANGE, 0, 2.4); + new TH1F("resVsEta_ptRel_L_90", ";Tracking particle |#eta|; p_{T} resolution / p_{T}", nETARANGE, 0, eta_resmax); TH1F* h2_resVsEta_d0_L_90 = - new TH1F("resVsEta_d0_L_90", ";Tracking particle |#eta|; d_{0} resolution [cm]", nETARANGE, 0, 2.4); + new TH1F("resVsEta_d0_L_90", ";Tracking particle |#eta|; d_{0} resolution [cm]", nETARANGE, 0, eta_resmax); TH1F* h2_resVsEta_eta_L_99 = - new TH1F("resVsEta_eta_L_99", ";Tracking particle |#eta|; #eta resolution", nETARANGE, 0, 2.4); + new TH1F("resVsEta_eta_L_99", ";Tracking particle |#eta|; #eta resolution", nETARANGE, 0, eta_resmax); TH1F* h2_resVsEta_z0_L_99 = - new TH1F("resVsEta_z0_L_99", ";Tracking particle |#eta|; z_{0} resolution [cm]", nETARANGE, 0, 2.4); + new TH1F("resVsEta_z0_L_99", ";Tracking particle |#eta|; z_{0} resolution [cm]", nETARANGE, 0, eta_resmax); TH1F* h2_resVsEta_phi_L_99 = - new TH1F("resVsEta_phi_L_99", ";Tracking particle |#eta|; #phi resolution [rad]", nETARANGE, 0, 2.4); + new TH1F("resVsEta_phi_L_99", ";Tracking particle |#eta|; #phi resolution [rad]", nETARANGE, 0, eta_resmax); TH1F* h2_resVsEta_ptRel_L_99 = - new TH1F("resVsEta_ptRel_L_99", ";Tracking particle |#eta|; p_{T} resolution / p_{T}", nETARANGE, 0, 2.4); + new TH1F("resVsEta_ptRel_L_99", ";Tracking particle |#eta|; p_{T} resolution / p_{T}", nETARANGE, 0, eta_resmax); TH1F* h2_resVsEta_d0_L_99 = - new TH1F("resVsEta_d0_L_99", ";Tracking particle |#eta|; d_{0} resolution [cm]", nETARANGE, 0, 2.4); + new TH1F("resVsEta_d0_L_99", ";Tracking particle |#eta|; d_{0} resolution [cm]", nETARANGE, 0, eta_resmax); TH1F* h2_resVsEta_eta_H_68 = - new TH1F("resVsEta_eta_H_68", ";Tracking particle |#eta|; #eta resolution", nETARANGE, 0, 2.4); + new TH1F("resVsEta_eta_H_68", ";Tracking particle |#eta|; #eta resolution", nETARANGE, 0, eta_resmax); TH1F* h2_resVsEta_z0_H_68 = - new TH1F("resVsEta_z0_H_68", ";Tracking particle |#eta|; z_{0} resolution [cm]", nETARANGE, 0, 2.4); + new TH1F("resVsEta_z0_H_68", ";Tracking particle |#eta|; z_{0} resolution [cm]", nETARANGE, 0, eta_resmax); TH1F* h2_resVsEta_phi_H_68 = - new TH1F("resVsEta_phi_H_68", ";Tracking particle |#eta|; #phi resolution [rad]", nETARANGE, 0, 2.4); + new TH1F("resVsEta_phi_H_68", ";Tracking particle |#eta|; #phi resolution [rad]", nETARANGE, 0, eta_resmax); TH1F* h2_resVsEta_ptRel_H_68 = - new TH1F("resVsEta_ptRel_H_68", ";Tracking particle |#eta|; p_{T} resolution / p_{T}", nETARANGE, 0, 2.4); + new TH1F("resVsEta_ptRel_H_68", ";Tracking particle |#eta|; p_{T} resolution / p_{T}", nETARANGE, 0, eta_resmax); TH1F* h2_resVsEta_d0_H_68 = - new TH1F("resVsEta_d0_H_68", ";Tracking particle |#eta|; d_{0} resolution [cm]", nETARANGE, 0, 2.4); + new TH1F("resVsEta_d0_H_68", ";Tracking particle |#eta|; d_{0} resolution [cm]", nETARANGE, 0, eta_resmax); TH1F* h2_resVsEta_eta_H_90 = - new TH1F("resVsEta_eta_H_90", ";Tracking particle |#eta|; #eta resolution", nETARANGE, 0, 2.4); + new TH1F("resVsEta_eta_H_90", ";Tracking particle |#eta|; #eta resolution", nETARANGE, 0, eta_resmax); TH1F* h2_resVsEta_z0_H_90 = - new TH1F("resVsEta_z0_H_90", ";Tracking particle |#eta|; z_{0} resolution [cm]", nETARANGE, 0, 2.4); + new TH1F("resVsEta_z0_H_90", ";Tracking particle |#eta|; z_{0} resolution [cm]", nETARANGE, 0, eta_resmax); TH1F* h2_resVsEta_phi_H_90 = - new TH1F("resVsEta_phi_H_90", ";Tracking particle |#eta|; #phi resolution [rad]", nETARANGE, 0, 2.4); + new TH1F("resVsEta_phi_H_90", ";Tracking particle |#eta|; #phi resolution [rad]", nETARANGE, 0, eta_resmax); TH1F* h2_resVsEta_ptRel_H_90 = - new TH1F("resVsEta_ptRel_H_90", ";Tracking particle |#eta|; p_{T} resolution / p_{T}", nETARANGE, 0, 2.4); + new TH1F("resVsEta_ptRel_H_90", ";Tracking particle |#eta|; p_{T} resolution / p_{T}", nETARANGE, 0, eta_resmax); TH1F* h2_resVsEta_d0_H_90 = - new TH1F("resVsEta_d0_H_90", ";Tracking particle |#eta|; d_{0} resolution [cm]", nETARANGE, 0, 2.4); + new TH1F("resVsEta_d0_H_90", ";Tracking particle |#eta|; d_{0} resolution [cm]", nETARANGE, 0, eta_resmax); TH1F* h2_resVsEta_eta_H_99 = - new TH1F("resVsEta_eta_H_99", ";Tracking particle |#eta|; #eta resolution", nETARANGE, 0, 2.4); + new TH1F("resVsEta_eta_H_99", ";Tracking particle |#eta|; #eta resolution", nETARANGE, 0, eta_resmax); TH1F* h2_resVsEta_z0_H_99 = - new TH1F("resVsEta_z0_H_99", ";Tracking particle |#eta|; z_{0} resolution [cm]", nETARANGE, 0, 2.4); + new TH1F("resVsEta_z0_H_99", ";Tracking particle |#eta|; z_{0} resolution [cm]", nETARANGE, 0, eta_resmax); TH1F* h2_resVsEta_phi_H_99 = - new TH1F("resVsEta_phi_H_99", ";Tracking particle |#eta|; #phi resolution [rad]", nETARANGE, 0, 2.4); + new TH1F("resVsEta_phi_H_99", ";Tracking particle |#eta|; #phi resolution [rad]", nETARANGE, 0, eta_resmax); TH1F* h2_resVsEta_ptRel_H_99 = - new TH1F("resVsEta_ptRel_H_99", ";Tracking particle |#eta|; p_{T} resolution / p_{T}", nETARANGE, 0, 2.4); + new TH1F("resVsEta_ptRel_H_99", ";Tracking particle |#eta|; p_{T} resolution / p_{T}", nETARANGE, 0, eta_resmax); TH1F* h2_resVsEta_d0_H_99 = - new TH1F("resVsEta_d0_H_99", ";Tracking particle |#eta|; d_{0} resolution [cm]", nETARANGE, 0, 2.4); + new TH1F("resVsEta_d0_H_99", ";Tracking particle |#eta|; d_{0} resolution [cm]", nETARANGE, 0, eta_resmax); // resolution vs. eta histograms (gaussian fit) - TH1F* h3_resVsEta_eta_L = new TH1F("resVsEta_eta_L_gaus", ";|#eta|; #sigma(#eta)", nETARANGE, 0, 2.4); - TH1F* h3_resVsEta_eta_H = new TH1F("resVsEta_eta_H_gaus", ";|#eta|; #sigma(#eta)", nETARANGE, 0, 2.4); + TH1F* h3_resVsEta_eta_L = new TH1F("resVsEta_eta_L_gaus", ";|#eta|; #sigma(#eta)", nETARANGE, 0, eta_resmax); + TH1F* h3_resVsEta_eta_H = new TH1F("resVsEta_eta_H_gaus", ";|#eta|; #sigma(#eta)", nETARANGE, 0, eta_resmax); - TH1F* h3_resVsEta_z0_L = new TH1F("resVsEta_z0_L_gaus", ";|#eta|; #sigma(z_{0}) [cm]", nETARANGE, 0, 2.4); - TH1F* h3_resVsEta_z0_H = new TH1F("resVsEta_z0_H_gaus", ";|#eta|; #sigma(z_{0}) [cm]", nETARANGE, 0, 2.4); + TH1F* h3_resVsEta_z0_L = new TH1F("resVsEta_z0_L_gaus", ";|#eta|; #sigma(z_{0}) [cm]", nETARANGE, 0, eta_resmax); + TH1F* h3_resVsEta_z0_H = new TH1F("resVsEta_z0_H_gaus", ";|#eta|; #sigma(z_{0}) [cm]", nETARANGE, 0, eta_resmax); - TH1F* h3_resVsEta_phi_L = new TH1F("resVsEta_phi_L_gaus", ";|#eta|; #sigma(#phi) [rad]", nETARANGE, 0, 2.4); - TH1F* h3_resVsEta_phi_H = new TH1F("resVsEta_phi_H_gaus", ";|#eta|; #sigma(#phi) [rad]", nETARANGE, 0, 2.4); + TH1F* h3_resVsEta_phi_L = new TH1F("resVsEta_phi_L_gaus", ";|#eta|; #sigma(#phi) [rad]", nETARANGE, 0, eta_resmax); + TH1F* h3_resVsEta_phi_H = new TH1F("resVsEta_phi_H_gaus", ";|#eta|; #sigma(#phi) [rad]", nETARANGE, 0, eta_resmax); - TH1F* h3_resVsEta_ptRel_L = new TH1F("resVsEta_ptRel_L_gaus", ";|#eta|; #sigma(p_{T}) / p_{T}", nETARANGE, 0, 2.4); - TH1F* h3_resVsEta_ptRel_H = new TH1F("resVsEta_ptRel_H_gaus", ";|#eta|; #sigma(p_{T}) / p_{T}", nETARANGE, 0, 2.4); + TH1F* h3_resVsEta_ptRel_L = + new TH1F("resVsEta_ptRel_L_gaus", ";|#eta|; #sigma(p_{T}) / p_{T}", nETARANGE, 0, eta_resmax); + TH1F* h3_resVsEta_ptRel_H = + new TH1F("resVsEta_ptRel_H_gaus", ";|#eta|; #sigma(p_{T}) / p_{T}", nETARANGE, 0, eta_resmax); gSystem->mkdir("FitResults"); TString fitdir = "FitResults/"; @@ -2448,8 +2486,7 @@ void L1TrackNtuplePlot(TString type, h2_resVsPt_ptRel_L_99, 0, max_pt_ptRel); - makeResidualIntervalPlot( - type, DIR, "resVsPt_L_pt", h2_resVsPt_pt_L_68, h2_resVsPt_pt_L_90, h2_resVsPt_pt_L_99, 0, max_pt_pt); + makeResidualIntervalPlot(type, DIR, "resVsPt_L_pt", h2_resVsPt_pt_L_68, h2_resVsPt_pt_L_90, h2_resVsPt_pt_L_99, 0, 4); makeResidualIntervalPlot( type, DIR, "resVsPt_L_z0", h2_resVsPt_z0_L_68, h2_resVsPt_z0_L_90, h2_resVsPt_z0_L_99, 0, max_z0); makeResidualIntervalPlot( @@ -2845,14 +2882,14 @@ void L1TrackNtuplePlot(TString type, h_tp_pt_H->Rebin(2); h_match_tp_pt_H->Rebin(2); - h_tp_eta->Rebin(2); - h_match_tp_eta->Rebin(2); - h_tp_eta_L->Rebin(2); - h_match_tp_eta_L->Rebin(2); - h_tp_eta_H->Rebin(2); - h_match_tp_eta_H->Rebin(2); + // h_tp_eta->Rebin(2); + // h_match_tp_eta->Rebin(2); + // h_tp_eta_L->Rebin(2); + // h_match_tp_eta_L->Rebin(2); + // h_tp_eta_H->Rebin(2); + // h_match_tp_eta_H->Rebin(2); - // calculate the effeciency + // calculate the efficiency h_match_tp_pt->Sumw2(); h_tp_pt->Sumw2(); TH1F* h_eff_pt = (TH1F*)h_match_tp_pt->Clone(); @@ -3460,40 +3497,40 @@ void L1TrackNtuplePlot(TString type, // sum track/ TP pt in jets /* if (TP_select_injet > 0) { - + TH1F* h_frac_sumpt_vspt = (TH1F*) h_jet_trk_sumpt_vspt->Clone(); h_frac_sumpt_vspt->SetName("frac_sumpt_vspt"); h_frac_sumpt_vspt->GetYaxis()->SetTitle("L1 sum(p_{T}) / TP sum(p_{T})"); h_frac_sumpt_vspt->Divide(h_jet_trk_sumpt_vspt, h_jet_tp_sumpt_vspt, 1.0, 1.0, "B"); - + TH1F* h_frac_sumpt_vseta = (TH1F*) h_jet_trk_sumpt_vseta->Clone(); h_frac_sumpt_vseta->SetName("frac_sumpt_vseta"); h_frac_sumpt_vseta->GetYaxis()->SetTitle("L1 sum(p_{T}) / TP sum(p_{T})"); h_frac_sumpt_vseta->Divide(h_jet_trk_sumpt_vseta, h_jet_tp_sumpt_vseta, 1.0, 1.0, "B"); - - + + TH1F* h_matchfrac_sumpt_vspt = (TH1F*) h_jet_matchtrk_sumpt_vspt->Clone(); h_matchfrac_sumpt_vspt->SetName("matchfrac_sumpt_vspt"); h_matchfrac_sumpt_vspt->GetYaxis()->SetTitle("Matched L1 sum(p_{T}) / TP sum(p_{T})"); h_matchfrac_sumpt_vspt->Divide(h_jet_matchtrk_sumpt_vspt, h_jet_tp_sumpt_vspt, 1.0, 1.0, "B"); - + TH1F* h_matchfrac_sumpt_vseta = (TH1F*) h_jet_matchtrk_sumpt_vseta->Clone(); h_matchfrac_sumpt_vseta->SetName("matchfrac_sumpt_vseta"); h_matchfrac_sumpt_vseta->GetYaxis()->SetTitle("Matched L1 sum(p_{T}) / TP sum(p_{T})"); h_matchfrac_sumpt_vseta->Divide(h_jet_matchtrk_sumpt_vseta, h_jet_tp_sumpt_vseta, 1.0, 1.0, "B"); - + h_frac_sumpt_vspt->Draw(); - c.SaveAs(DIR+type+"_sumpt_vspt.pdf"); - + c.SaveAs(DIR+type+"_sumpt_vspt.pdf"); + h_frac_sumpt_vseta->Draw(); - c.SaveAs(DIR+type+"_sumpt_vseta.pdf"); - + c.SaveAs(DIR+type+"_sumpt_vseta.pdf"); + h_matchfrac_sumpt_vspt->Draw(); - c.SaveAs(DIR+type+"_sumpt_match_vspt.pdf"); - + c.SaveAs(DIR+type+"_sumpt_match_vspt.pdf"); + h_matchfrac_sumpt_vseta->Draw(); - c.SaveAs(DIR+type+"_sumpt_match_vseta.pdf"); + c.SaveAs(DIR+type+"_sumpt_match_vseta.pdf"); } */ @@ -3503,26 +3540,30 @@ void L1TrackNtuplePlot(TString type, h_ntrk_pt3->Write(); h_ntrk_pt10->Write(); + h_ntrkPerSector_all->Write(); h_ntrkPerSector_pt2->Write(); h_ntrkPerSector_pt3->Write(); h_ntrkPerSector_pt4->Write(); + h_ntrkPerSector_all->Scale(1.0 / nevt); h_ntrkPerSector_pt2->Scale(1.0 / nevt); h_ntrkPerSector_pt3->Scale(1.0 / nevt); h_ntrkPerSector_pt4->Scale(1.0 / nevt); - h_ntrkPerSector_pt2->GetYaxis()->SetTitle("Fraction of events"); - h_ntrkPerSector_pt2->GetXaxis()->SetTitle("Max number of transmitted tracks per #phi sector"); + h_ntrkPerSector_all->GetYaxis()->SetTitle("Fraction of events"); + h_ntrkPerSector_all->GetXaxis()->SetTitle("Max number of transmitted tracks per #phi sector"); + h_ntrkPerSector_all->SetLineColor(1); h_ntrkPerSector_pt2->SetLineColor(4); h_ntrkPerSector_pt3->SetLineColor(2); h_ntrkPerSector_pt4->SetLineColor(8); - max = h_ntrkPerSector_pt2->GetMaximum(); - h_ntrkPerSector_pt2->SetAxisRange(0.00001, max * 5, "Y"); - h_ntrkPerSector_pt2->SetAxisRange(0., 100, "X"); + max = h_ntrkPerSector_all->GetMaximum(); + h_ntrkPerSector_all->SetAxisRange(0.00001, max * 5, "Y"); + h_ntrkPerSector_all->SetAxisRange(0., 100, "X"); - h_ntrkPerSector_pt2->Draw("hist"); + h_ntrkPerSector_all->Draw("hist"); + h_ntrkPerSector_pt2->Draw("same,hist"); h_ntrkPerSector_pt3->Draw("same,hist"); h_ntrkPerSector_pt4->Draw("same,hist"); gPad->SetLogy(); @@ -3531,6 +3572,7 @@ void L1TrackNtuplePlot(TString type, l->SetFillStyle(0); l->SetBorderSize(0); l->SetTextSize(0.04); + l->AddEntry(h_ntrkPerSector_all, "no p_{T}cut", "l"); l->AddEntry(h_ntrkPerSector_pt2, "p_{T}^{track} > 2 GeV", "l"); l->AddEntry(h_ntrkPerSector_pt3, "p_{T}^{track} > 3 GeV", "l"); l->AddEntry(h_ntrkPerSector_pt4, "p_{T}^{track} > 4 GeV", "l"); @@ -3555,6 +3597,18 @@ void L1TrackNtuplePlot(TString type, c.SaveAs(DIR + type + "_trackrate_pt10_perevt.pdf"); } + // number of tracks vs. eta, pT (trk_eta/trk_pt) + + if (doDetailedPlots) { + h_trk_eta->Write(); + h_trk_pt->Write(); + + h_trk_eta->Draw(); + c.SaveAs(DIR + type + "_trk_eta.pdf"); + h_trk_pt->Draw(); + c.SaveAs(DIR + type + "_trk_pt.pdf"); + } + fout->Close(); // --------------------------------------------------------------------------------------------------------- @@ -3610,6 +3664,7 @@ void L1TrackNtuplePlot(TString type, cout << "# TP/event (pt > 3.0) = " << (float)ntp_pt3 / nevt << endl; cout << "# TP/event (pt > 10.0) = " << (float)ntp_pt10 / nevt << endl; + cout << "# tracks/event (no pt cut)= " << (float)ntrk / nevt << endl; cout << "# tracks/event (pt > " << std::max(TP_minPt, 2.0f) << ") = " << (float)ntrk_pt2 / nevt << endl; cout << "# tracks/event (pt > 3.0) = " << (float)ntrk_pt3 / nevt << endl; cout << "# tracks/event (pt > 10.0) = " << (float)ntrk_pt10 / nevt << endl; diff --git a/L1Trigger/TrackFindingTracklet/test/L1TrackQualityPlot.C b/L1Trigger/TrackFindingTracklet/test/L1TrackQualityPlot.C index 0fa4aef25f682..9699993c54848 100644 --- a/L1Trigger/TrackFindingTracklet/test/L1TrackQualityPlot.C +++ b/L1Trigger/TrackFindingTracklet/test/L1TrackQualityPlot.C @@ -2,7 +2,7 @@ // Basic example ROOT script for making tracking performance plots using the ntuples produced by L1TrackNtupleMaker.cc // // e.g. in ROOT do: [0] .L L1TrackQualityPlot.C++ -// [1] L1TrackQualityPlot("TTbar_PU200_D49") +// [1] L1TrackQualityPlot("TTbar_PU200_D76") // // By Claire Savard, July 2020 // Based off of L1TrackNtuplePlot.C @@ -677,4 +677,4 @@ void SetPlotStyle() { // put tick marks on top and RHS of plots gStyle->SetPadTickX(1); gStyle->SetPadTickY(1); -} \ No newline at end of file +} diff --git a/L1Trigger/TrackFindingTracklet/test/Makefile b/L1Trigger/TrackFindingTracklet/test/Makefile index 0288bbb14082e..74e51b2c89ad5 100644 --- a/L1Trigger/TrackFindingTracklet/test/Makefile +++ b/L1Trigger/TrackFindingTracklet/test/Makefile @@ -221,7 +221,11 @@ DEPDIR = .deps MAKEDEPEND = makedepend -I../../.. -IdummyIncl -f- $< | sed 's/..\/src/lib/' > .deps/$*.d -SRCS = $(wildcard ../src/*.cc) +SRCSTMP = $(wildcard ../src/*.cc) + +DONTCOMPILE = $(wildcard ../src/*ChannelAssignment*.cc) + +SRCS = $(filter-out $(DONTCOMPILE), $(SRCSTMP)) OBJS = $(SRCS:../src/%.cc=lib/%.o) diff --git a/L1Trigger/TrackFindingTracklet/test/ProducerIRin.cc b/L1Trigger/TrackFindingTracklet/test/ProducerIRin.cc new file mode 100644 index 0000000000000..61d41e92db6d2 --- /dev/null +++ b/L1Trigger/TrackFindingTracklet/test/ProducerIRin.cc @@ -0,0 +1,106 @@ +#include "FWCore/Framework/interface/stream/EDProducer.h" +#include "FWCore/Framework/interface/Run.h" +#include "FWCore/Framework/interface/EventSetup.h" +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/MakerMacros.h" +#include "FWCore/Utilities/interface/EDGetToken.h" +#include "FWCore/Utilities/interface/EDPutToken.h" +#include "FWCore/Utilities/interface/ESGetToken.h" +#include "FWCore/Utilities/interface/InputTag.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "DataFormats/Common/interface/Handle.h" + +#include "L1Trigger/TrackTrigger/interface/Setup.h" +#include "L1Trigger/TrackFindingTracklet/interface/ChannelAssignment.h" + +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace edm; +using namespace tt; + +namespace trklet { + + /*! \class trklet::ProducerIRin + * \brief Transforms TTTDCinto f/w comparable format for summer chain configuratiotn + * \author Thomas Schuh + * \date 2021, Oct + */ + class ProducerIRin : public stream::EDProducer<> { + public: + explicit ProducerIRin(const ParameterSet&); + ~ProducerIRin() override {} + + private: + void beginRun(const Run&, const EventSetup&) override; + void produce(Event&, const EventSetup&) override; + virtual void endJob() {} + // ED input token of DTC Stubs + EDGetTokenT edGetTokenTTDTC_; + // ED output token for stubs + EDPutTokenT edPutTokenStubs_; + // Setup token + ESGetToken esGetTokenSetup_; + // ChannelAssignment token + ESGetToken esGetTokenChannelAssignment_; + // configuration + ParameterSet iConfig_; + // helper class to store configurations + const Setup* setup_; + // helper class to assign stubs to channel + const ChannelAssignment* channelAssignment_; + // map of used tfp channels + vector channelEncoding_; + }; + + ProducerIRin::ProducerIRin(const ParameterSet& iConfig) : iConfig_(iConfig) { + const InputTag& inputTag = iConfig.getParameter("InputTagDTC"); + const string& branchStubs = iConfig.getParameter("BranchAcceptedStubs"); + // book in- and output ED products + edGetTokenTTDTC_ = consumes(inputTag); + edPutTokenStubs_ = produces(branchStubs); + // book ES products + esGetTokenSetup_ = esConsumes(); + esGetTokenChannelAssignment_ = esConsumes(); + // initial ES products + setup_ = nullptr; + } + + void ProducerIRin::beginRun(const Run& iRun, const EventSetup& iSetup) { + // helper class to store configurations + setup_ = &iSetup.getData(esGetTokenSetup_); + if (!setup_->configurationSupported()) + return; + // check process history if desired + if (iConfig_.getParameter("CheckHistory")) + setup_->checkHistory(iRun.processHistory()); + channelAssignment_ = const_cast(&iSetup.getData(esGetTokenChannelAssignment_)); + // map of used tfp channels + channelEncoding_ = channelAssignment_->channelEncoding(); + } + + void ProducerIRin::produce(Event& iEvent, const EventSetup& iSetup) { + // empty IRin product + StreamsStub streamStubs; + // read in hybrid track finding product and produce KFin product + if (setup_->configurationSupported()) { + Handle handleTTDTC; + iEvent.getByToken(edGetTokenTTDTC_, handleTTDTC); + const int numChannel = channelEncoding_.size(); + streamStubs.reserve(numChannel); + for (int tfpRegion : handleTTDTC->tfpRegions()) + for (int tfpChannel : channelEncoding_) + streamStubs.emplace_back(handleTTDTC->stream(tfpRegion, tfpChannel)); + } + // store products + iEvent.emplace(edPutTokenStubs_, move(streamStubs)); + } + +} // namespace trklet + +DEFINE_FWK_MODULE(trklet::ProducerIRin); diff --git a/L1Trigger/TrackFindingTracklet/test/demonstrator_cfg.py b/L1Trigger/TrackFindingTracklet/test/demonstrator_cfg.py new file mode 100644 index 0000000000000..6e45507b61120 --- /dev/null +++ b/L1Trigger/TrackFindingTracklet/test/demonstrator_cfg.py @@ -0,0 +1,74 @@ +# this compares event by event the output of the C++ emulation with the ModelSim simulation of the firmware +import FWCore.ParameterSet.Config as cms + +process = cms.Process( "Demo" ) +process.load( 'FWCore.MessageService.MessageLogger_cfi' ) +process.load( 'Configuration.EventContent.EventContent_cff' ) +process.load( 'Configuration.Geometry.GeometryExtended2026D76Reco_cff' ) +process.load( 'Configuration.Geometry.GeometryExtended2026D76_cff' ) +#process.load( 'Configuration.Geometry.GeometryExtended2026D49Reco_cff' ) +#process.load( 'Configuration.Geometry.GeometryExtended2026D49_cff' ) +process.load( 'Configuration.StandardSequences.MagneticField_cff' ) +process.load( 'Configuration.StandardSequences.FrontierConditions_GlobalTag_cff' ) +process.load( 'L1Trigger.TrackTrigger.TrackTrigger_cff' ) + +from Configuration.AlCa.GlobalTag import GlobalTag +process.GlobalTag = GlobalTag(process.GlobalTag, 'auto:phase2_realistic', '') + +# load code that produces DTCStubs +process.load( 'L1Trigger.TrackerDTC.ProducerED_cff' ) +# L1 tracking => hybrid emulation +process.load("L1Trigger.TrackFindingTracklet.L1HybridEmulationTracks_cff") +# load code that fits hybrid tracks +process.load( 'L1Trigger.TrackFindingTracklet.Producer_cff' ) +#--- Load code that compares s/w with f/w +process.load( 'L1Trigger.TrackFindingTracklet.Demonstrator_cff' ) +from L1Trigger.TrackFindingTracklet.Customize_cff import * +#reducedConfig( process ) +fwConfig( process ) + +# build schedule +process.tt = cms.Sequence ( process.TrackerDTCProducer + + process.L1HybridTracks + + process.TrackFindingTrackletProducerIRin + + process.TrackFindingTrackletProducerTBout + + process.TrackFindingTrackletProducerKFin + + process.TrackFindingTrackletProducerKF + ) +process.demo = cms.Path( process.tt + process.TrackerTFPDemonstrator ) +process.schedule = cms.Schedule( process.demo ) + +# create options +import FWCore.ParameterSet.VarParsing as VarParsing +options = VarParsing.VarParsing( 'analysis' ) +# specify input MC +inputMC = [ + #'/store/relval/CMSSW_11_3_0_pre6/RelValSingleMuFlatPt2To100/GEN-SIM-DIGI-RAW/113X_mcRun4_realistic_v6_2026D76noPU-v1/10000/05f802b7-b0b3-4cca-8b70-754682c3bb4c.root' + #'/store/relval/CMSSW_11_3_0_pre6/RelValDisplacedMuPt2To100Dxy100/GEN-SIM-DIGI-RAW/113X_mcRun4_realistic_v6_2026D76noPU-v1/00000/011da61a-9524-4a96-b91f-03e8690af3bd.root' + '/store/relval/CMSSW_11_3_0_pre6/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/00000/00026541-6200-4eed-b6f8-d3a1fd720e9c.root', + '/store/relval/CMSSW_11_3_0_pre6/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/00000/013d0125-8f6e-496b-8335-614398c9210d.root', + '/store/relval/CMSSW_11_3_0_pre6/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/00000/058bd134-86de-47e1-bcde-379ed9b79e1b.root', + '/store/relval/CMSSW_11_3_0_pre6/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/00000/0915d66c-cbd4-4ef6-9971-7dd59e198b56.root', + '/store/relval/CMSSW_11_3_0_pre6/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/00000/09823c8d-e443-4066-8347-8c704929cb2b.root', + '/store/relval/CMSSW_11_3_0_pre6/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/00000/0c39a1aa-93ee-41c1-8543-6d90c09114a7.root', + '/store/relval/CMSSW_11_3_0_pre6/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/00000/0fcdcc53-fb9f-4f0b-8529-a4d60d914c14.root', + '/store/relval/CMSSW_11_3_0_pre6/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/00000/16760a5c-9cd2-41c3-82e5-399bb962d537.root', + '/store/relval/CMSSW_11_3_0_pre6/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/00000/1752640f-2001-4d14-9276-063ec07cea92.root', + '/store/relval/CMSSW_11_3_0_pre6/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/00000/180712c9-31a5-4f2a-bf92-a7fbee4dabad.root' + #"/store/relval/CMSSW_11_3_0_pre3/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v3_2026D49PU200_rsb-v1/00000/00260a30-734a-4a3a-a4b0-f836ce5502c6.root" +] +options.register( 'inputMC', inputMC, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.string, "Files to be processed" ) +# specify number of events to process. +options.register( 'Events',100,VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.int, "Number of Events to analyze" ) +options.parseArguments() + +process.options = cms.untracked.PSet( wantSummary = cms.untracked.bool(False) ) +process.maxEvents = cms.untracked.PSet( input = cms.untracked.int32(options.Events) ) +process.source = cms.Source( + "PoolSource", + fileNames = cms.untracked.vstring( options.inputMC ), + #skipEvents = cms.untracked.uint32( 993 ), + secondaryFileNames = cms.untracked.vstring(), + duplicateCheckMode = cms.untracked.string( 'noDuplicateCheck' ) +) +process.Timing = cms.Service( "Timing", summaryOnly = cms.untracked.bool( True ) ) \ No newline at end of file diff --git a/L1Trigger/TrackFindingTracklet/test/fpga.cc b/L1Trigger/TrackFindingTracklet/test/fpga.cc index 12c39e8cdc8ce..101f15b9c2f9d 100644 --- a/L1Trigger/TrackFindingTracklet/test/fpga.cc +++ b/L1Trigger/TrackFindingTracklet/test/fpga.cc @@ -26,6 +26,7 @@ #include "../interface/SLHCEvent.h" #include "../interface/Track.h" #include "../interface/Settings.h" +#include "../interface/StubStreamData.h" #include "../interface/TrackletEventProcessor.h" #include "FWCore/MessageLogger/interface/MessageLogger.h" @@ -208,7 +209,16 @@ int main(const int argc, const char **argv) { edm::LogVerbatim("Tracklet") << "Process event: " << eventnum << " with " << ev.nstubs() << " stubs and " << ev.nsimtracks() << " simtracks"; - eventProcessor.event(ev); + // Output track streams per nonant from track-builders. + constexpr unsigned int numStubStreamsPerTrack = settings.extended() ? N_SEED : N_SEED_PROMPT; + // Max. number of projection layers for any tracklet seed. + constexpr unsigned int maxNumProjectionLayers = 8; + constexpr unsigned int numStreamsTrack = N_SECTOR * numStubStreamsTrack; + constexpr unsigned int numStreamsStub = numStreamsTrack * maxNumProjectionLayers; + std::vector> tracksStream(numStreamsTrack); + std::vector> stubsStream(numStreamsStub); + + eventProcessor.event(ev, tracksStream, stubsStream); const std::vector &tracks = eventProcessor.tracks(); @@ -325,4 +335,6 @@ int main(const int argc, const char **argv) { } eventProcessor.printSummary(); + + exit(0); } diff --git a/L1Trigger/TrackFindingTracklet/test/makeHists.csh b/L1Trigger/TrackFindingTracklet/test/makeHists.csh index 6ad4919784a6b..426b0a05dcb9b 100755 --- a/L1Trigger/TrackFindingTracklet/test/makeHists.csh +++ b/L1Trigger/TrackFindingTracklet/test/makeHists.csh @@ -1,19 +1,19 @@ #!/bin/tcsh -########################################################################### -# Create L1 track histograms & print summary of tracking performance, # -# by running ROOT macro L1TrackNtuplePlot.C on .root file # -# from L1TrackNtupleMaker_cfg.py # -# # -# To use: # -# makeHists.csh rootFileName # -# # -# (where rootFileName is the name of the input .root file, # -# including its directory name, if its not in the current one. # -# If rootFileName not specified, it defaults to TTbar_PU200_hybrid.root) # -########################################################################### +######################################################################## +# Create L1 track histograms & print summary of tracking performance, # +# by running ROOT macros L1TrackNtuplePlot.C & L1TrackQualityPlot.C # +# on the .root file from L1TrackNtupleMaker_cfg.py . # # # +# # +# To use: # +# makeHists.csh rootFileName # +# # +# (where rootFileName is the name of the input .root file, # +# including its directory name, if its not in the current one. # +# If rootFileName not specified, it defaults to TTbar_PU200_D76.root) # +######################################################################## if ($#argv == 0) then - set inputFullFileName = "TTbar_PU200_D49.root" + set inputFullFileName = "TTbar_PU200_D76.root" else set inputFullFileName = $1 endif @@ -32,20 +32,20 @@ set fileName = `basename $inputFullFileName` # Get stem of filename, removing ".root". set inputFileStem = `echo $fileName | awk -F . '{print $1;}'` -# Find plotting macro eval `scramv1 runtime -csh` + +# Run track quality MVA plotting macro +set plotMacro = $CMSSW_BASE/src/L1Trigger/TrackFindingTracklet/test/L1TrackQualityPlot.C +if (-e MVA_plots) rm -r MVA_plots +\root -b -q ${plotMacro}'("'${inputFileStem}'","'${dirName}'")' +echo "MVA track quality Histograms written to MVA_plots/" + +# Run track performance plotting macro set plotMacro = $CMSSW_BASE/src/L1Trigger/TrackFindingTracklet/test/L1TrackNtuplePlot.C -if ( -e $plotMacro ) then - # Run plotting macro - if (-e TrkPlots) rm -r TrkPlots - \root -b -q ${plotMacro}'("'${inputFileStem}'","'${dirName}'")' | tail -n 19 >! results.out - cat results.out - echo "Tracking performance summary written to results.out" - echo "Histograms written to TrkPlots/" -else if ( -e ../L1TrackNtuplePlot.C ) then -else - echo "ERROR: $plotMacro not found" - exit(2) -endif +if (-e TrkPlots) rm -r TrkPlots +\root -b -q ${plotMacro}'("'${inputFileStem}'","'${dirName}'")' | tail -n 19 >! results.out +cat results.out +echo "Tracking performance summary written to results.out" +echo "Track performance histograms written to TrkPlots/" exit diff --git a/L1Trigger/TrackFindingTracklet/test/skimForCI_cfg.py b/L1Trigger/TrackFindingTracklet/test/skimForCI_cfg.py new file mode 100644 index 0000000000000..d21f0528f2d9d --- /dev/null +++ b/L1Trigger/TrackFindingTracklet/test/skimForCI_cfg.py @@ -0,0 +1,73 @@ +#----------------------------------------------------------- +# This job skims a MC dataset, selecting only products +# that are needed to run the L1 tracking & measure its +# performance. +# +# It is typically used to create small datasets that +# the git CI runs on to check new code. +# +# Whenever the L1 tracking group switches to a new default +# MC dataset, this skim should be run on ttbar+0PU MC, +# and the skimmed dataset placed in +# https://gitlab.cern.ch/cms-l1tk/cmssw_CI . +#----------------------------------------------------------- + +############################################################ +# define basic process +############################################################ + +import FWCore.ParameterSet.Config as cms +import FWCore.Utilities.FileUtils as FileUtils +import os +process = cms.Process("SKIM") + + +############################################################ +# import standard configurations +############################################################ + +process.load('Configuration.StandardSequences.Services_cff') +process.load('FWCore.MessageService.MessageLogger_cfi') +process.load('Configuration.EventContent.EventContent_cff') +process.load('Configuration.StandardSequences.MagneticField_cff') + +# D49 geometry (T15 tracker) +process.load('Configuration.Geometry.GeometryExtended2026D76Reco_cff') +process.load('Configuration.Geometry.GeometryExtended2026D76_cff') + +process.load('Configuration.StandardSequences.EndOfProcess_cff') + + +process.maxEvents = cms.untracked.PSet(input = cms.untracked.int32(1000)) + +#--- To use MCsamples scripts, defining functions get*data*() for easy MC access, +#--- follow instructions in https://github.com/cms-L1TK/MCsamples + +from MCsamples.Scripts.getCMSdata_cfi import * + +# Read data from card files (defines getCMSdataFromCards()): +from MCsamples.RelVal_1130_D76.PU0_TTbar_14TeV_cfi import * +inputMC = getCMSdataFromCards() + +process.source = cms.Source("PoolSource", fileNames = cms.untracked.vstring(*inputMC)) + +process.output = cms.OutputModule("PoolOutputModule", + splitLevel = cms.untracked.int32(0), + eventAutoFlushCompressedSize = cms.untracked.int32(5242880), + outputCommands = cms.untracked.vstring('drop *'), + fileName = cms.untracked.string('/tmp/skimmedForCI.root'), + dataset = cms.untracked.PSet( + filterName = cms.untracked.string(''), + dataTier = cms.untracked.string('GEN-SIM-DIGI-RAW') + ) +) + +process.output.outputCommands.append('keep *_*_*Level1TTTracks*_*') +process.output.outputCommands.append('keep *_*_*StubAccepted*_*') +process.output.outputCommands.append('keep *_*_*ClusterAccepted*_*') +process.output.outputCommands.append('keep *_*_*MergedTrackTruth*_*') +process.output.outputCommands.append('keep *_genParticles_*_*') + +process.pd = cms.EndPath(process.output) + +process.schedule = cms.Schedule(process.pd) diff --git a/L1Trigger/TrackTrigger/BuildFile.xml b/L1Trigger/TrackTrigger/BuildFile.xml index 65f7dde7a9ba9..f274595fed4b8 100644 --- a/L1Trigger/TrackTrigger/BuildFile.xml +++ b/L1Trigger/TrackTrigger/BuildFile.xml @@ -1,18 +1,43 @@ + + + + + + + + + + + + + + - + + + + + + + + + + + + diff --git a/L1Trigger/TrackTrigger/interface/HitPatternHelper.h b/L1Trigger/TrackTrigger/interface/HitPatternHelper.h new file mode 100644 index 0000000000000..955726779b9c0 --- /dev/null +++ b/L1Trigger/TrackTrigger/interface/HitPatternHelper.h @@ -0,0 +1,134 @@ +// This is a helper function that can be used to decode hitpattern, which is a 7-bit integer produced by the Kalman filter (KF). +// Hitpattern is stored at TTTrack objects (DataFormats/L1TrackTrigger/interface/TTTrack.h) +// It can be accessed via TTTrack: hitPattern() +// +// There are two classes declared in HitPatternHelper (hph) namesapce: +// 1)Setup: This is used to produce a layermap and a collection of needed by HitPatternHelper. +// 2)HitPatternHelper: This function returns more specific information (e.g. module type, layer id,...) about each stub on the TTTrack objects. +// This function needs three variables from TTTrack: hitPattern(),tanL() and z0(). +// It makes predictions in two different ways depending on which version of the KF is deployed: +// +// Old KF (L1Trigger/TrackFindingTMTT/plugins/TMTrackProducer.cc) is a CMSSW emulation of KF firmware that +// ignores truncation effect and is not bit/clock cycle accurate. +// With this version of the KF, HitPatternHelper relys on a hard-coded layermap to deterimne layer IDs of each stub. +// +// New KF (L1Trigger/TrackerTFP/plugins/ProducerKF.cc) is a new CMSSW emulation of KF firmware that +// considers truncaton effect and is bit/clock cycle accurate. +// With this version of the KF, HitPatternHelper makes predictions based on the spatial coordinates of tracks and detector modules. +// +// Created by J.Li on 1/23/21. +// + +#ifndef L1Trigger_TrackTrigger_interface_HitPatternHelper_h +#define L1Trigger_TrackTrigger_interface_HitPatternHelper_h + +#include "FWCore/Framework/interface/data_default_record_trait.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "Geometry/TrackerGeometryBuilder/interface/TrackerGeometry.h" +#include "DataFormats/SiStripDetId/interface/StripSubdetector.h" +#include "Geometry/CommonTopologies/interface/PixelGeomDetUnit.h" +#include "DataFormats/TrackerCommon/interface/TrackerTopology.h" +#include "L1Trigger/TrackTrigger/interface/HitPatternHelperRcd.h" +#include "L1Trigger/TrackTrigger/interface/Setup.h" + +#include +#include +#include + +using namespace std; +using namespace edm; + +namespace hph { + + //Class that stores configuration for HitPatternHelper + class Setup { + public: + Setup() {} + Setup(const edm::ParameterSet& iConfig, const tt::Setup& setupTT); + ~Setup() {} + + bool hphDebug() const { return iConfig_.getParameter("hphDebug"); } + bool useNewKF() const { return iConfig_.getParameter("useNewKF"); } + double deltaTanL() const { return iConfig_.getParameter("deltaTanL"); } + double chosenRofZ() const { return setupTT_.chosenRofZ(); } + std::vector etaRegions() const { return setupTT_.boundarieEta(); } + std::vector sensorModules() const { return setupTT_.sensorModules(); } + std::map>> layermap() const { return layermap_; } + int nKalmanLayers() const { return nKalmanLayers_; } + static auto smallerID(std::pair lhs, std::pair rhs) { return lhs.first < rhs.first; } + static auto equalID(std::pair lhs, std::pair rhs) { return lhs.first == rhs.first; } + + private: + edm::ParameterSet iConfig_; + const tt::Setup setupTT_; // Helper class to store TrackTrigger configuration + std::vector> + layerIds_; // layer IDs (1~6->L1~L6;11~15->D1~D5) and whether or not they are from tracker barrel + // Only needed by Old KF + std::map>> layermap_; // Hard-coded layermap in Old KF + int nEtaRegions_; // # of eta regions + int nKalmanLayers_; // # of maximum KF layers allowed + }; // Only needed by Old KF + + //Class that returns decoded information from hitpattern + class HitPatternHelper { + public: + HitPatternHelper() {} + HitPatternHelper(const Setup* setup, int hitpattern, double cot, double z0); + ~HitPatternHelper() {} + + int etaSector() { return etaSector_; } //Eta sectors defined in KF + int numExpLayer() { return numExpLayer_; } //The number of layers KF expects + int numMissingPS() { + return numMissingPS_; + } //The number of PS layers that are missing. It includes layers that are missing: + //1)before the innermost stub on the track, + //2)after the outermost stub on the track. + int numMissing2S() { + return numMissing2S_; + } //The number of 2S layers that are missing. It includes the two types of layers mentioned above. + int numPS() { return numPS_; } //The number of PS layers are found in hitpattern + int num2S() { return num2S_; } //The number of 2S layers are found in hitpattern + int numMissingInterior1() { + return numMissingInterior1_; + } //The number of missing interior layers (using only hitpattern) + int numMissingInterior2() { + return numMissingInterior2_; + } //The number of missing interior layers (using hitpattern, layermap from Old KF and sensor modules) + std::vector binary() { return binary_; } //11-bit hitmask needed by TrackQuality.cc (0~5->L1~L6;6~10->D1~D5) + static auto smallerID(tt::SensorModule lhs, tt::SensorModule rhs) { return lhs.layerId() < rhs.layerId(); } + static auto equalID(tt::SensorModule lhs, tt::SensorModule rhs) { return lhs.layerId() == rhs.layerId(); } + + int ReducedId( + int layerId); //Converts layer ID (1~6->L1~L6;11~15->D1~D5) to reduced layer ID (0~5->L1~L6;6~10->D1~D5) + int findLayer(int layerId); //Search for a layer ID from sensor modules + + private: + int etaSector_; + int hitpattern_; + int numExpLayer_; + int numMissingLayer_; + int numMissingPS_; + int numMissing2S_; + int numPS_; + int num2S_; + int numMissingInterior1_; + int numMissingInterior2_; + double cot_; + double z0_; + const Setup* setup_; + std::vector layers_; //Sensor modules that particles are expected to hit + std::vector binary_; + bool hphDebug_; + bool useNewKF_; + float chosenRofZ_; + float deltaTanL_; // Uncertainty added to tanL (cot) when layermap in new KF is determined + std::vector etaRegions_; + int nKalmanLayers_; + std::map>> layermap_; + }; + +} // namespace hph + +EVENTSETUP_DATA_DEFAULT_RECORD(hph::Setup, hph::SetupRcd); + +#endif diff --git a/L1Trigger/TrackTrigger/interface/HitPatternHelperRcd.h b/L1Trigger/TrackTrigger/interface/HitPatternHelperRcd.h new file mode 100644 index 0000000000000..8b13f07e9f8be --- /dev/null +++ b/L1Trigger/TrackTrigger/interface/HitPatternHelperRcd.h @@ -0,0 +1,23 @@ +// +// Created by J.Li on 1/23/21. +// + +#ifndef L1Trigger_TrackTrigger_interface_HitPatternHelperRcd_h +#define L1Trigger_TrackTrigger_interface_HitPatternHelperRcd_h + +#include "FWCore/Framework/interface/DependentRecordImplementation.h" + +#include "L1Trigger/TrackTrigger/interface/SetupRcd.h" + +#include "FWCore/Utilities/interface/mplVector.h" + +namespace hph { + + typedef edm::mpl::Vector Rcds; + + // record of hph::SetupRcd + class SetupRcd : public edm::eventsetup::DependentRecordImplementation {}; + +} // namespace hph + +#endif diff --git a/L1Trigger/TrackTrigger/interface/L1TrackQuality.h b/L1Trigger/TrackTrigger/interface/L1TrackQuality.h index c55aeb93cc0dd..5de1cbd4caac0 100644 --- a/L1Trigger/TrackTrigger/interface/L1TrackQuality.h +++ b/L1Trigger/TrackTrigger/interface/L1TrackQuality.h @@ -16,13 +16,13 @@ C.Brown 28/07/20 #include "FWCore/Framework/interface/Event.h" #include "FWCore/Framework/interface/EventSetup.h" #include "FWCore/Framework/interface/Frameworkfwd.h" - #include "FWCore/Framework/interface/MakerMacros.h" - #include "FWCore/ParameterSet/interface/ParameterSet.h" - #include "DataFormats/L1TrackTrigger/interface/TTTrack.h" #include "DataFormats/L1TrackTrigger/interface/TTTypes.h" +#include "L1Trigger/TrackTrigger/interface/HitPatternHelper.h" +#include "PhysicsTools/ONNXRuntime/interface/ONNXRuntime.h" +#include class L1TrackQuality { public: @@ -58,6 +58,8 @@ class L1TrackQuality { std::string const& ONNXInputName, std::vector const& featureNames); + void beginRun(const hph::Setup* setup); + private: // Private Member Data QualityAlgorithm qualityAlgorithm_ = QualityAlgorithm::None; @@ -70,6 +72,8 @@ class L1TrackQuality { float bendchi2Max_; float minPt_; int nStubsmin_; - float ONNXInvRScaling_; + const hph::Setup* setupHPH_; + bool useHPH_; + std::unique_ptr runTime_; }; #endif diff --git a/L1Trigger/TrackerDTC/interface/SensorModule.h b/L1Trigger/TrackTrigger/interface/SensorModule.h similarity index 81% rename from L1Trigger/TrackerDTC/interface/SensorModule.h rename to L1Trigger/TrackTrigger/interface/SensorModule.h index f1286bcf2934d..ffc7ec83468e8 100644 --- a/L1Trigger/TrackerDTC/interface/SensorModule.h +++ b/L1Trigger/TrackTrigger/interface/SensorModule.h @@ -1,16 +1,16 @@ -#ifndef L1Trigger_TrackerDTC_SensorModule_h -#define L1Trigger_TrackerDTC_SensorModule_h +#ifndef L1Trigger_TrackTrigger_SensorModule_h +#define L1Trigger_TrackTrigger_SensorModule_h #include "DataFormats/DetId/interface/DetId.h" -namespace trackerDTC { +namespace tt { class Setup; // representation of an outer tracker sensormodule class SensorModule { public: - SensorModule(const Setup& setup, const DetId& detId, int dtcId, int modId); + SensorModule(const Setup* setup, const DetId& detId, int dtcId, int modId); ~SensorModule() {} enum Type { BarrelPS, Barrel2S, DiskPS, Disk2S, NumTypes }; @@ -53,24 +53,25 @@ namespace trackerDTC { double pitchRow() const { return pitchRow_; } // sensor length in cm [strip=5,pixel=.15625] double pitchCol() const { return pitchCol_; } - // module tilt measured w.r.t. beam axis (0=barrel), tk layout measures w.r.t. radial axis + // module tilt angle measured w.r.t. beam axis (0=barrel), tk layout measures w.r.t. radial axis double tilt() const { return tilt_; } // sinus of module tilt measured w.r.t. beam axis (0=barrel), tk layout measures w.r.t. radial axis - double sin() const { return sin_; } + double sinTilt() const { return sinTilt_; } // cosinus of module tilt measured w.r.t. beam axis (+-1=endcap), tk layout measures w.r.t. radial axis - double cos() const { return cos_; } + double cosTilt() const { return cosTilt_; } // encoded radius of disk2S stubs, used in Hybrid int encodedR() const { return encodedR_; } - // encoded layer id [0-3] - int encodedLayerId() const { return encodedLayerId_; } // stub radius offset for barrelPS, barrel2S, used in Hybrid double offsetR() const { return offsetR_; } // stub z offset for diskPS, disk2S, used in Hybrid double offsetZ() const { return offsetZ_; } // bend window size in half strip units int windowSize() const { return windowSize_; } + // + double tiltCorrection(double cot) const { return abs(tiltCorrectionSlope_ * cot) + tiltCorrectionIntercept_; } private: + enum TypeTilt { nonBarrel = 0, tiltedMinus = 1, tiltedPlus = 2, flat = 3 }; // cmssw det id DetId detId_; // dtc id [0-215] @@ -109,26 +110,28 @@ namespace trackerDTC { double pitchRow_; // sensor length in cm [strip=5,pixel=.15625] double pitchCol_; - // module tilt measured w.r.t. beam axis (0=barrel), tk layout measures w.r.t. radial axis + // module tilt angle measured w.r.t. beam axis (0=barrel), tk layout measures w.r.t. radial axis double tilt_; // sinus of module tilt measured w.r.t. beam axis (0=barrel), tk layout measures w.r.t. radial axis - double sin_; + double sinTilt_; // cosinus of module tilt measured w.r.t. beam axis (+-1=endcap), tk layout measures w.r.t. radial axis - double cos_; + double cosTilt_; // module type (barrelPS, barrel2S, diskPS, disk2S) Type type_; // encoded radius of disk2S stubs, used in Hybrid int encodedR_; - // encoded layer id [0-3] - int encodedLayerId_; // stub radius offset for barrelPS, barrel2S, used in Hybrid double offsetR_; // stub z offset for diskPS, disk2S, used in Hybrid double offsetZ_; // bend window size in half strip units int windowSize_; + // tilt correction parameter used to project r to z uncertainty + double tiltCorrectionSlope_; + // tilt correction parameter used to project r to z uncertainty + double tiltCorrectionIntercept_; }; -} // namespace trackerDTC +} // namespace tt #endif diff --git a/L1Trigger/TrackerDTC/interface/Setup.h b/L1Trigger/TrackTrigger/interface/Setup.h similarity index 61% rename from L1Trigger/TrackerDTC/interface/Setup.h rename to L1Trigger/TrackTrigger/interface/Setup.h index 6200a0f511a80..3985daad77bf5 100644 --- a/L1Trigger/TrackerDTC/interface/Setup.h +++ b/L1Trigger/TrackTrigger/interface/Setup.h @@ -1,5 +1,5 @@ -#ifndef L1Trigger_TrackerDTC_Setup_h -#define L1Trigger_TrackerDTC_Setup_h +#ifndef L1Trigger_TrackTrigger_Setup_h +#define L1Trigger_TrackTrigger_Setup_h #include "FWCore/Framework/interface/data_default_record_trait.h" #include "FWCore/ParameterSet/interface/ParameterSet.h" @@ -18,23 +18,25 @@ #include "L1Trigger/TrackTrigger/interface/TTStubAlgorithm_official.h" #include "MagneticField/Engine/interface/MagneticField.h" #include "CondFormats/SiPhase2TrackerObjects/interface/TrackerDetToDTCELinkCablingMap.h" +#include "SimTracker/Common/interface/TrackingParticleSelector.h" -#include "DataFormats/L1TrackTrigger/interface/TTTypes.h" +#include "SimTracker/TrackTriggerAssociation/interface/TTTypes.h" #include "DataFormats/L1TrackTrigger/interface/TTDTC.h" -#include "L1Trigger/TrackerDTC/interface/SetupRcd.h" -#include "L1Trigger/TrackerDTC/interface/SensorModule.h" +#include "L1Trigger/TrackTrigger/interface/SensorModule.h" +#include "L1Trigger/TrackTrigger/interface/SetupRcd.h" #include +#include #include -namespace trackerDTC { +namespace tt { typedef TTStubAlgorithm StubAlgorithm; typedef TTStubAlgorithm_official StubAlgorithmOfficial; // handles 2 pi overflow inline double deltaPhi(double lhs, double rhs = 0.) { return reco::deltaPhi(lhs, rhs); } - /*! \class trackerDTC::Setup + /*! \class tt::Setup * \brief Class to process and provide run-time constants used by Track Trigger emulators * \author Thomas Schuh * \date 2020, Apr @@ -66,6 +68,8 @@ namespace trackerDTC { int dtcId(int tfpRegion, int tfpChannel) const; // checks if given dtcId is connected to PS or 2S sensormodules bool psModule(int dtcId) const; + // checks if given dtcId is connected via 10 gbps link + bool gbps10(int dtcId) const; // checks if given dtcId is connected to -z (false) or +z (true) bool side(int dtcId) const; // ATCA slot number [0-11] of given dtcId @@ -76,27 +80,110 @@ namespace trackerDTC { const TrackerGeometry* trackerGeometry() const { return trackerGeometry_; } // TrackerTopology const TrackerTopology* trackerTopology() const { return trackerTopology_; } - // returns bit accurate position of a stub from a given tfp identifier region [0-8] channel [0-47] - GlobalPoint stubPos(bool hybrid, const TTDTC::Frame& frame, int tfpRegion, int tfpChannel) const; // returns global TTStub position GlobalPoint stubPos(const TTStubRef& ttStubRef) const; + // returns bit accurate hybrid stub radius for given TTStubRef and h/w bit word + double stubR(const TTBV& hw, const TTStubRef& ttStubRef) const; + // returns bit accurate position of a stub from a given tfp region [0-8] + GlobalPoint stubPos(bool hybrid, const tt::FrameStub& frame, int region) const; // empty trackerDTC EDProduct TTDTC ttDTC() const { return TTDTC(numRegions_, numOverlappingRegions_, numDTCsPerRegion_); } - - // Common track finding parameter - - // half lumi region size in cm - double beamWindowZ() const { return beamWindowZ_; } + // checks if stub collection is considered forming a reconstructable track + bool reconstructable(const std::vector& ttStubRefs) const; + // checks if tracking particle is selected for efficiency measurements + bool useForAlgEff(const TrackingParticle& tp) const; + // checks if tracking particle is selected for fake and duplicate rate measurements + bool useForReconstructable(const TrackingParticle& tp) const { return tpSelectorLoose_(tp); } + // stub layer id (barrel: 1 - 6, endcap: 11 - 15) + int layerId(const TTStubRef& ttStubRef) const; + // return tracklet layerId (barrel: [0-5], endcap: [6-10]) for given TTStubRef + int trackletLayerId(const TTStubRef& ttStubRef) const; + // return index layerId (barrel: [0-5], endcap: [0-6]) for given TTStubRef + int indexLayerId(const TTStubRef& ttStubRef) const; + // true if stub from barrel module + bool barrel(const TTStubRef& ttStubRef) const; + // true if stub from barrel module + bool psModule(const TTStubRef& ttStubRef) const; + // return sensor moduel type + SensorModule::Type type(const TTStubRef& ttStubRef) const; + // + TTBV layerMap(const std::vector& ints) const; + // + TTBV layerMap(const TTBV& hitPattern, const std::vector& ints) const; + // + std::vector layerMap(const TTBV& hitPattern, const TTBV& ttBV) const; + // + std::vector layerMap(const TTBV& ttBV) const; + // stub projected phi uncertainty + double dPhi(const TTStubRef& ttStubRef, double inv2R) const; + // stub projected z uncertainty + double dZ(const TTStubRef& ttStubRef, double cot) const; + // stub projected chi2phi wheight + double v0(const TTStubRef& ttStubRef, double inv2R) const; + // stub projected chi2z wheight + double v1(const TTStubRef& ttStubRef, double cot) const; + // + const std::vector& sensorModules() const { return sensorModules_; } + + // Firmware specific Parameter + + // width of the 'A' port of an DSP slice + int widthDSPa() const { return widthDSPa_; } + // width of the 'A' port of an DSP slice using biased twos complement + int widthDSPab() const { return widthDSPab_; } + // width of the 'A' port of an DSP slice using biased binary + int widthDSPau() const { return widthDSPau_; } + // width of the 'B' port of an DSP slice + int widthDSPb() const { return widthDSPb_; } + // width of the 'B' port of an DSP slice using biased twos complement + int widthDSPbb() const { return widthDSPbb_; } + // width of the 'B' port of an DSP slice using biased binary + int widthDSPbu() const { return widthDSPbu_; } + // width of the 'C' port of an DSP slice + int widthDSPc() const { return widthDSPc_; } + // width of the 'C' port of an DSP slice using biased twos complement + int widthDSPcb() const { return widthDSPcb_; } + // width of the 'C' port of an DSP slice using biased binary + int widthDSPcu() const { return widthDSPcu_; } + // smallest address width of an BRAM36 configured as broadest simple dual port memory + int widthAddrBRAM36() const { return widthAddrBRAM36_; } + // smallest address width of an BRAM18 configured as broadest simple dual port memory + int widthAddrBRAM18() const { return widthAddrBRAM18_; } // number of frames betwen 2 resets of 18 BX packets int numFrames() const { return numFrames_; } + // number of frames needed per reset + int numFramesInfra() const { return numFramesInfra_; } // number of valid frames per 18 BX packet int numFramesIO() const { return numFramesIO_; } // number of valid frames per 8 BX packet int numFramesFE() const { return numFramesFE_; } + // maximum representable stub phi uncertainty + double maxdPhi() const { return maxdPhi_; } + // maximum representable stub z uncertainty + double maxdZ() const { return maxdZ_; } + // barrel layer limit z value to partition into tilted and untilted region + double tiltedLayerLimitZ(int layer) const { return tiltedLayerLimitsZ_.at(layer); } + // endcap disk limit r value to partition into PS and 2S region + double psDiskLimitR(int layer) const { return psDiskLimitsR_.at(layer); } + // strip pitch of outer tracker sensors in cm + double pitch2S() const { return pitch2S_; } + // pixel pitch of outer tracker sensors in cm + double pitchPS() const { return pitchPS_; } + // strip length of outer tracker sensors in cm + double length2S() const { return length2S_; } + // pixel length of outer tracker sensors in cm + double lengthPS() const { return lengthPS_; } + + // Common track finding parameter + + // half lumi region size in cm + double beamWindowZ() const { return beamWindowZ_; } // converts GeV in 1/cm double invPtToDphi() const { return invPtToDphi_; } // region size in rad double baseRegion() const { return baseRegion_; } + // pt cut + double tpMinPt() const { return tpMinPt_; } // TP eta cut double tpMaxEta() const { return tpMaxEta_; } // TP cut on vertex pos r in cm @@ -109,6 +196,12 @@ namespace trackerDTC { int tpMinLayers() const { return tpMinLayers_; } // required number of associated ps layers to a TP to consider it reconstruct-able int tpMinLayersPS() const { return tpMinLayersPS_; } + // max number of unassociated 2S stubs allowed to still associate TTTrack with TP + int tpMaxBadStubs2S() const { return tpMaxBadStubs2S_; } + // max number of unassociated PS stubs allowed to still associate TTTrack with TP + int tpMaxBadStubsPS() const { return tpMaxBadStubsPS_; } + // BField used in fw in T + double bField() const { return bField_; } // TMTT specific parameter @@ -121,26 +214,52 @@ namespace trackerDTC { // number of detector layers a reconstructbale particle may cross int numLayers() const { return numLayers_; } // number of bits used for stub r - ChosenRofPhi - int widthR() const { return widthR_; } + int tmttWidthR() const { return tmttWidthR_; } // number of bits used for stub phi w.r.t. phi sector centre - int widthPhi() const { return widthPhi_; } + int tmttWidthPhi() const { return tmttWidthPhi_; } // number of bits used for stub z - int widthZ() const { return widthZ_; } + int tmttWidthZ() const { return tmttWidthZ_; } // number of bits used for stub layer id - int widthLayer() const { return widthLayer_; } + int tmttWidthLayer() const { return tmttWidthLayer_; } + // number of bits used for stub eta sector + int tmttWidthSectorEta() const { return tmttWidthSectorEta_; } + // number of bits used for stub inv2R + int tmttWidthInv2R() const { return tmttWidthInv2R_; } // internal stub r precision in cm - double baseR() const { return baseR_; } + double tmttBaseR() const { return tmttBaseR_; } // internal stub z precision in cm - double baseZ() const { return baseZ_; } + double tmttBaseZ() const { return tmttBaseZ_; } // internal stub phi precision in rad - double basePhi() const { return basePhi_; } + double tmttBasePhi() const { return tmttBasePhi_; } + // internal stub inv2R precision in 1/cm + double tmttBaseInv2R() const { return tmttBaseInv2R_; } + // internal stub phiT precision in rad + double tmttBasePhiT() const { return tmttBasePhiT_; } // number of padded 0s in output data format - int dtcNumUnusedBits() const { return dtcNumUnusedBits_; } + int tmttNumUnusedBits() const { return tmttNumUnusedBits_; } + // outer radius of outer tracker in cm + double outerRadius() const { return outerRadius_; } + // inner radius of outer tracker in cm + double innerRadius() const { return innerRadius_; } + // half length of outer tracker in cm + double halfLength() const { return halfLength_; } + // max strip/pixel length of outer tracker sensors in cm + double maxLength() const { return maxLength_; } + // In tilted barrel, grad*|z|/r + int approximates |cosTilt| + |sinTilt * cotTheta| + double tiltApproxSlope() const { return tiltApproxSlope_; } + // In tilted barrel, grad*|z|/r + int approximates |cosTilt| + |sinTilt * cotTheta| + double tiltApproxIntercept() const { return tiltApproxIntercept_; } + // In tilted barrel, constant assumed stub radial uncertainty * sqrt(12) in cm + double tiltUncertaintyR() const { return tiltUncertaintyR_; } + // scattering term used to add stub phi uncertainty depending on assumed track inv2R + double scattering() const { return scattering_; } // Hybrid specific parameter - // cut on stub and TP pt, also defines region overlap shape in GeV - double hybridMinPt() const { return hybridMinPt_; } + // cut on stub pt in GeV, also defines region overlap shape + double hybridMinPtStub() const { return hybridMinPtStub_; } + // cut on andidate pt in GeV + double hybridMinPtCand() const { return hybridMinPtCand_; } // cut on stub eta double hybridMaxEta() const { return hybridMaxEta_; } // critical radius defining region overlap shape in cm @@ -158,7 +277,7 @@ namespace trackerDTC { // number of bits used for stub bend number for module types (barrelPS, barrel2S, diskPS, disk2S) int hybridWidthBend(SensorModule::Type type) const { return hybridWidthsBend_.at(type); } // number of bits used for stub layer id - int hybridWidthLayer() const { return hybridWidthLayer_; } + int hybridWidthLayerId() const { return hybridWidthLayerId_; } // precision or r in cm for (barrelPS, barrel2S, diskPS, disk2S) double hybridBaseR(SensorModule::Type type) const { return hybridBasesR_.at(type); } // precision or phi in rad for (barrelPS, barrel2S, diskPS, disk2S) @@ -177,6 +296,12 @@ namespace trackerDTC { double hybridLayerR(int layerId) const { return hybridLayerRs_.at(layerId); } // mean z of outer tracker endcap disks double hybridDiskZ(int layerId) const { return hybridDiskZs_.at(layerId); } + // range of stub phi in rad + double hybridRangePhi() const { return hybridRangePhi_; } + // range of stub r in cm + double hybridRangeR() const { return hybridRangesR_[SensorModule::DiskPS]; } + // smallest stub radius after TrackBuilder in cm + double tbInnerRadius() const { return tbInnerRadius_; } // Parameter specifying TTStub algorithm @@ -220,6 +345,8 @@ namespace trackerDTC { int numRegions() const { return numRegions_; } // number of regions a reconstructable particles may cross int numOverlappingRegions() const { return numOverlappingRegions_; } + // number of Tracker boards per ATCA crate. + int numATCASlots() const { return numATCASlots_; } // number of DTC boards used to readout a detector region, likely constructed to be an integerer multiple of NumSlots_ int numDTCsPerRegion() const { return numDTCsPerRegion_; } // max number of sensor modules connected to one DTC board @@ -230,8 +357,8 @@ namespace trackerDTC { int dtcDepthMemory() const { return dtcDepthMemory_; } // number of row bits used in look up table int dtcWidthRowLUT() const { return dtcWidthRowLUT_; } - // number of bits used for stub qOverPt. lut addr is col + bend = 11 => 1 BRAM -> 18 bits for min and max val -> 9 - int dtcWidthQoverPt() const { return dtcWidthQoverPt_; } + // number of bits used for stub inv2R. lut addr is col + bend = 11 => 1 BRAM -> 18 bits for min and max val -> 9 + int dtcWidthInv2R() const { return dtcWidthInv2R_; } // tk layout det id minus DetSetVec->detId int offsetDetIdDSV() const { return offsetDetIdDSV_; } // tk layout det id minus TrackerTopology lower det id @@ -252,20 +379,31 @@ namespace trackerDTC { int dtcNumMergedRows() const { return dtcNumMergedRows_; } // number of bits used for phi of row slope int dtcWidthM() const { return dtcWidthM_; } - // internal stub q over pt precision in 1 /cm - double dtcBaseQoverPt() const { return dtcBaseQoverPt_; } + // internal stub inv2R precision in 1 /cm + double dtcBaseInv2R() const { return dtcBaseInv2R_; } // phi of row slope precision in rad / pitch unit double dtcBaseM() const { return dtcBaseM_; } - // number of bits for internal stub phi - int widthPhiDTC() const { return widthPhiDTC_; } // sensor modules connected to given dtc id const std::vector& dtcModules(int dtcId) const { return dtcModules_.at(dtcId); } - // index = encoded layerId, inner value = decoded layerId for given tfp channel [0-47] - const std::vector& encodingLayerId(int tfpChannel) const; + // total number of output channel + int dtcNumStreams() const { return dtcNumStreams_; } + + // Parameter specifying TFP + + // number of bist used for phi0 + int tfpWidthPhi0() const { return tfpWidthPhi0_; } + // umber of bist used for inv2R + int tfpWidthInv2R() const { return tfpWidthInv2R_; } + // number of bist used for cot(theta) + int tfpWidthCot() const { return tfpWidthCot_; } + // number of bist used for z0 + int tfpWidthZ0() const { return tfpWidthZ0_; } + // number of output links + int tfpNumChannel() const { return tfpNumChannel_; } // Parameter specifying GeometricProcessor - // number of phi sectors used in hough transform + // number of phi sectors in a processing nonant used in hough transform int numSectorsPhi() const { return numSectorsPhi_; } // number of eta sectors used in hough transform int numSectorsEta() const { return numSectorsEta_; } @@ -275,136 +413,102 @@ namespace trackerDTC { int gpDepthMemory() const { return gpDepthMemory_; } // defining r-z sector shape double boundarieEta(int eta) const { return boundariesEta_.at(eta); } + std::vector boundarieEta() const { return boundariesEta_; } // phi sector size in rad double baseSector() const { return baseSector_; } // cut on zT double maxZT() const { return maxZT_; } // cut on stub cot theta double maxCot() const { return maxCot_; } - // number of bits used for internal stub sector eta - int widthSectorEta() const { return widthSectorEta_; } - // number of bits to represent z residual w.r.t. sector center - int widthChiZ() const { return widthChiZ_; } + // total number of sectors + int numSectors() const { return numSectors_; } + // cot(theta) of given eta sector + double sectorCot(int eta) const { return sectorCots_.at(eta); } + // + double neededRangeChiZ() const { return neededRangeChiZ_; } // Parameter specifying HoughTransform - // number of qOverPt bins used in hough transform - int htNumBinsQoverPt() const { return htNumBinsQoverPt_; } + // number of inv2R bins used in hough transform + int htNumBinsInv2R() const { return htNumBinsInv2R_; } // number of phiT bins used in hough transform int htNumBinsPhiT() const { return htNumBinsPhiT_; } // required number of stub layers to form a candidate int htMinLayers() const { return htMinLayers_; } // internal fifo depth int htDepthMemory() const { return htDepthMemory_; } - // number of bits used for candidate q over pt - int htWidthQoverPt() const { return htWidthQoverPt_; } - // number of bits used for candidate phiT - int htWidthPhiT() const { return htWidthPhiT_; } - // number of bits to represent phi residual w.r.t. ht candiate - int widthChiPhi() const { return widthChiPhi_; } - // q over pt bin width precision in 1 /cm - double htBaseQoverPt() const { return htBaseQoverPt_; } - // phiT bin width in rad - double htBasePhiT() const { return htBasePhiT_; } // Parameter specifying MiniHoughTransform - // number of finer qOverPt bins inside HT bin - int mhtNumBinsQoverPt() const { return mhtNumBinsQoverPt_; } + // number of finer inv2R bins inside HT bin + int mhtNumBinsInv2R() const { return mhtNumBinsInv2R_; } // number of finer phiT bins inside HT bin int mhtNumBinsPhiT() const { return mhtNumBinsPhiT_; } // number of dynamic load balancing steps - int mhtNumDLB() const { return mhtNumDLB_; } + int mhtNumDLBs() const { return mhtNumDLBs_; } + // number of units per dynamic load balancing step + int mhtNumDLBNodes() const { return mhtNumDLBNodes_; } + // number of inputs per dynamic load balancing unit + int mhtNumDLBChannel() const { return mhtNumDLBChannel_; } // required number of stub layers to form a candidate int mhtMinLayers() const { return mhtMinLayers_; } // number of mht cells int mhtNumCells() const { return mhtNumCells_; } - // number of bits used for candidate q over pt - int mhtWidthQoverPt() const { return mhtWidthQoverPt_; } - // number of bits used for candidate phiT - int mhtWidthPhiT() const { return mhtWidthPhiT_; } - // q over pt bin width precision in 1 /cm - double mhtBaseQoverPt() const { return mhtBaseQoverPt_; } - // phiT bin width in rad - double mhtBasePhiT() const { return mhtBasePhiT_; } - // Parameter specifying SeedFilter + // Parameter specifying ZHoughTransform + //number of used zT bins + int zhtNumBinsZT() const { return zhtNumBinsZT_; } + // number of used cot bins + int zhtNumBinsCot() const { return zhtNumBinsCot_; } + // number of stages + int zhtNumStages() const { return zhtNumStages_; } // required number of stub layers to form a candidate - int sfMinLayers() const { return sfMinLayers_; } - // cot(theta) precision - double sfBaseCot() const { return sfBaseCot_; } - // zT precision in cm - double sfBaseZT() const { return sfBaseZT_; } + int zhtMinLayers() const { return zhtMinLayers_; } + // max number of output tracks per node + int zhtMaxTracks() const { return zhtMaxTracks_; } + // cut on number of stub per layer for input candidates + int zhtMaxStubsPerLayer() const { return zhtMaxStubsPerLayer_; } + // number of zht cells + int zhtNumCells() const { return zhtNumCells_; } + + // Parameter specifying KalmanFilter Input Formatter + + // power of 2 multiplier of stub phi residual range + int kfinShiftRangePhi() const { return kfinShiftRangePhi_; } + // power of 2 multiplier of stub z residual range + int kfinShiftRangeZ() const { return kfinShiftRangeZ_; } // Parameter specifying KalmanFilter - // number of bits for internal reciprocal look up - int kfWidthLutInvPhi() const { return kfWidthLutInvPhi_; } - // number of bits for internal reciprocal look up - int kfWidthLutInvZ() const { return kfWidthLutInvZ_; } - // cut on number of input candidates - int kfNumTracks() const { return kfNumTracks_; } + // number of kf worker + int kfNumWorker() const { return kfNumWorker_; } // required number of stub layers to form a track int kfMinLayers() const { return kfMinLayers_; } // maximum number of layers added to a track int kfMaxLayers() const { return kfMaxLayers_; } - // cut on number of stub per layer for input candidates - int kfMaxStubsPerLayer() const { return kfMaxStubsPerLayer_; } - // maximum allowed skipped layers from inside to outside to form a track - int kfMaxSkippedLayers() const { return kfMaxSkippedLayers_; } - double kfBasem0() const { return kfBasem0_; } - double kfBasem1() const { return kfBasem1_; } - double kfBasev0() const { return kfBasev0_; } - double kfBasev1() const { return kfBasev1_; } - double kfBasex0() const { return kfBasex0_; } - double kfBasex1() const { return kfBasex1_; } - double kfBasex2() const { return kfBasex2_; } - double kfBasex3() const { return kfBasex3_; } - double kfBaseH00() const { return kfBaseH00_; } - double kfBaseH12() const { return kfBaseH12_; } - double kfBaser0() const { return kfBaser0_; } - double kfBaser1() const { return kfBaser1_; } - double kfBaser02() const { return kfBaser02_; } - double kfBaser12() const { return kfBaser12_; } - double kfBaseS00() const { return kfBaseS00_; } - double kfBaseS01() const { return kfBaseS01_; } - double kfBaseS12() const { return kfBaseS12_; } - double kfBaseS13() const { return kfBaseS13_; } - double kfBaseR00() const { return kfBaseR00_; } - double kfBaseR11() const { return kfBaseR11_; } - double kfBaseInvR00() const { return kfBaseInvR00_; } - double kfBaseInvR11() const { return kfBaseInvR11_; } - double kfBaseK00() const { return kfBaseK00_; } - double kfBaseK10() const { return kfBaseK10_; } - double kfBaseK21() const { return kfBaseK21_; } - double kfBaseK31() const { return kfBaseK31_; } - double kfBaseC00() const { return kfBaseC00_; } - double kfBaseC01() const { return kfBaseC01_; } - double kfBaseC11() const { return kfBaseC11_; } - double kfBaseC22() const { return kfBaseC22_; } - double kfBaseC23() const { return kfBaseC23_; } - double kfBaseC33() const { return kfBaseC33_; } - double kfBaseChi20() const { return kfBaseChi20_; } - double kfBaseChi21() const { return kfBaseChi21_; } - double kfBaseChi2() const { return kfBaseChi2_; } + // search window of each track parameter in initial uncertainties + double kfRangeFactor() const { return kfRangeFactor_; } + + // Parameter specifying KalmanFilter Output Formatter + + // Final Chi2rphi digitization TODO extract from TTTrack Word + std::vector kfoutchi2rphiBins() const { return kfoutchi2rphiBins_; } + // Final Chi2rz digitization TODO extract from TTTrack Word + std::vector kfoutchi2rzBins() const { return kfoutchi2rzBins_; } + // Conversion factor between dphi^2/weight and chi2rphi + int kfoutchi2rphiConv() const { return kfoutchi2rphiConv_; } + // Conversion factor between dz^2/weight and chi2rz + int kfoutchi2rzConv() const { return kfoutchi2rzConv_; } + // Number of bits for the tttrack word + int tttrackBits() const { return tttrackBits_; } + // Fraction of total dphi and dz ranges to calculate v0 and v1 LUT for + int weightBinFraction() const { return weightBinFraction_; } // Parameter specifying DuplicateRemoval // internal memory depth int drDepthMemory() const { return drDepthMemory_; } - // number of bist used for phi0 - int drWidthPhi0() const { return drWidthPhi0_; } - // umber of bist used for qOverPt - int drWidthQoverPt() const { return drWidthQoverPt_; } - // number of bist used for cot(theta) - int drWidthCot() const { return drWidthCot_; } - // number of bist used for z0 - int drWidthZ0() const { return drWidthZ0_; } - double drBaseQoverPt() const { return drBaseQoverPt_; } - double drBasePhi0() const { return drBasePhi0_; } - double drBaseCot() const { return drBaseCot_; } - double drBaseZ0() const { return drBaseZ0_; } private: // checks consitency between history and current configuration for a specific module @@ -424,8 +528,6 @@ namespace trackerDTC { void consumeStubAlgorithm(); // create bend encodings void encodeBend(std::vector>&, bool) const; - // create encodingsLayerId - void encodeLayerId(); // create sensor modules void produceSensorModules(); // range check of dtc id @@ -434,6 +536,8 @@ namespace trackerDTC { void checkTKLayoutId(int tkLayoutId) const; // range check of tfp identifier void checkTFPIdentifier(int tfpRegion, int tfpChannel) const; + // configure TPSelector + void configureTPSelector(); // MagneticField const MagneticField* magneticField_; @@ -487,6 +591,8 @@ namespace trackerDTC { int unMatchedStubs_; // allowed number of PS stubs a found track may have not in common with its matched TP int unMatchedStubsPS_; + // scattering term used to add stub phi uncertainty depending on assumed track inv2R + double scattering_; // TMTT specific parameter edm::ParameterSet pSetTMTT_; @@ -499,16 +605,18 @@ namespace trackerDTC { // number of detector layers a reconstructbale particle may cross int numLayers_; // number of bits used for stub r - ChosenRofPhi - int widthR_; + int tmttWidthR_; // number of bits used for stub phi w.r.t. phi sector centre - int widthPhi_; + int tmttWidthPhi_; // number of bits used for stub z - int widthZ_; + int tmttWidthZ_; // Hybrid specific parameter edm::ParameterSet pSetHybrid_; - // cut on stub and TP pt, also defines region overlap shape in GeV - double hybridMinPt_; + // cut on stub pt in GeV, also defines region overlap shape + double hybridMinPtStub_; + // cut on andidate pt in GeV + double hybridMinPtCand_; // cut on stub eta double hybridMaxEta_; // critical radius defining region overlap shape in cm @@ -539,9 +647,15 @@ namespace trackerDTC { std::vector hybridDiskZs_; // center radius of outer tracker endcap 2S diks strips std::vector hybridDisk2SRsSet_; + // range of stub phi in rad + double hybridRangePhi_; + // smallest stub radius after TrackBuilder in cm + double tbInnerRadius_; // Parameter specifying TrackingParticle used for Efficiency measurements edm::ParameterSet pSetTP_; + // pt cut + double tpMinPt_; // eta cut double tpMaxEta_; // cut on vertex pos r in cm @@ -554,9 +668,35 @@ namespace trackerDTC { int tpMinLayers_; // required number of associated ps layers to a TP to consider it reconstruct-able int tpMinLayersPS_; + // max number of unassociated 2S stubs allowed to still associate TTTrack with TP + int tpMaxBadStubs2S_; + // max number of unassociated PS stubs allowed to still associate TTTrack with TP + int tpMaxBadStubsPS_; - // Fimrware specific Parameter + // Firmware specific Parameter edm::ParameterSet pSetFW_; + // width of the 'A' port of an DSP slice + int widthDSPa_; + // width of the 'A' port of an DSP slice using biased twos complement + int widthDSPab_; + // width of the 'A' port of an DSP slice using biased binary + int widthDSPau_; + // width of the 'B' port of an DSP slice + int widthDSPb_; + // width of the 'B' port of an DSP slice using biased twos complement + int widthDSPbb_; + // width of the 'B' port of an DSP slice using biased binary + int widthDSPbu_; + // width of the 'C' port of an DSP slice + int widthDSPc_; + // width of the 'C' port of an DSP slice using biased twos complement + int widthDSPcb_; + // width of the 'C' port of an DSP slice using biased binary + int widthDSPcu_; + // smallest address width of an BRAM36 configured as broadest simple dual port memory + int widthAddrBRAM36_; + // smallest address width of an BRAM18 configured as broadest simple dual port memory + int widthAddrBRAM18_; // needed gap between events of emp-infrastructure firmware int numFramesInfra_; // LHC bunch crossing rate in MHz @@ -581,6 +721,34 @@ namespace trackerDTC { double halfLength_; // max strip/pixel pitch of outer tracker sensors in cm double maxPitch_; + // max strip/pixel length of outer tracker sensors in cm + double maxLength_; + // approximated tilt correction parameter used to project r to z uncertainty + double tiltApproxSlope_; + // approximated tilt correction parameter used to project r to z uncertainty + double tiltApproxIntercept_; + // In tilted barrel, constant assumed stub radial uncertainty * sqrt(12) in cm + double tiltUncertaintyR_; + // minimum representable stub phi uncertainty + double mindPhi_; + // maximum representable stub phi uncertainty + double maxdPhi_; + // minimum representable stub z uncertainty + double mindZ_; + // maximum representable stub z uncertainty + double maxdZ_; + // strip pitch of outer tracker sensors in cm + double pitch2S_; + // pixel pitch of outer tracker sensors in cm + double pitchPS_; + // strip length of outer tracker sensors in cm + double length2S_; + // pixel length of outer tracker sensors in cm + double lengthPS_; + // barrel layer limit |z| value to partition into tilted and untilted region + std::vector tiltedLayerLimitsZ_; + // endcap disk limit r value to partition into PS and 2S region + std::vector psDiskLimitsR_; // Parameter specifying front-end edm::ParameterSet pSetFE_; @@ -619,8 +787,8 @@ namespace trackerDTC { int dtcDepthMemory_; // number of row bits used in look up table int dtcWidthRowLUT_; - // number of bits used for stub qOverPt. lut addr is col + bend = 11 => 1 BRAM -> 18 bits for min and max val -> 9 - int dtcWidthQoverPt_; + // number of bits used for stub inv2R. lut addr is col + bend = 11 => 1 BRAM -> 18 bits for min and max val -> 9 + int dtcWidthInv2R_; // tk layout det id minus DetSetVec->detId int offsetDetIdDSV_; // tk layout det id minus TrackerTopology lower det id @@ -629,6 +797,25 @@ namespace trackerDTC { int offsetLayerDisks_; // offset between 0 and smallest layer id (barrel layer 1) int offsetLayerId_; + // total number of output channel + int dtcNumStreams_; + // slot number changing from PS to 2S (default: 6) + int slotLimitPS_; + // slot number changing from 10 gbps to 5gbps (default: 3) + int slotLimit10gbps_; + + // Parameter specifying TFP + edm::ParameterSet pSetTFP_; + // number of bist used for phi0 + int tfpWidthPhi0_; + // umber of bist used for qOverPt + int tfpWidthInv2R_; + // number of bist used for cot(theta) + int tfpWidthCot_; + // number of bist used for z0 + int tfpWidthZ0_; + // number of output links + int tfpNumChannel_; // Parameter specifying GeometricProcessor edm::ParameterSet pSetGP_; @@ -647,8 +834,8 @@ namespace trackerDTC { // Parameter specifying HoughTransform edm::ParameterSet pSetHT_; - // number of qOverPt bins used in hough transform - int htNumBinsQoverPt_; + // number of inv2R bins used in hough transform + int htNumBinsInv2R_; // number of phiT bins used in hough transform int htNumBinsPhiT_; // required number of stub layers to form a candidate @@ -658,80 +845,79 @@ namespace trackerDTC { // Parameter specifying MiniHoughTransform edm::ParameterSet pSetMHT_; - // number of finer qOverPt bins inside HT bin - int mhtNumBinsQoverPt_; + // number of finer inv2R bins inside HT bin + int mhtNumBinsInv2R_; // number of finer phiT bins inside HT bin int mhtNumBinsPhiT_; // number of dynamic load balancing steps - int mhtNumDLB_; + int mhtNumDLBs_; + // number of units per dynamic load balancing step + int mhtNumDLBNodes_; + // number of inputs per dynamic load balancing unit + int mhtNumDLBChannel_; // required number of stub layers to form a candidate int mhtMinLayers_; - // Parameter specifying SeedFilter - edm::ParameterSet pSetSF_; - // used cot(Theta) bin width = 2 ** this - int sfPowerBaseCot_; - // used zT bin width = baseZ * 2 ** this - int sfBaseDiffZ_; + // Parameter specifying ZHoughTransform + edm::ParameterSet pSetZHT_; + //number of used zT bins + int zhtNumBinsZT_; + // number of used cot bins + int zhtNumBinsCot_; + // number of stages + int zhtNumStages_; // required number of stub layers to form a candidate - int sfMinLayers_; + int zhtMinLayers_; + // max number of output tracks per node + int zhtMaxTracks_; + // cut on number of stub per layer for input candidates + int zhtMaxStubsPerLayer_; + + // Parameter specifying KalmanFilter Input Formatter + edm::ParameterSet pSetKFin_; + // power of 2 multiplier of stub phi residual range + int kfinShiftRangePhi_; + // power of 2 multiplier of stub z residual range + int kfinShiftRangeZ_; // Parameter specifying KalmanFilter edm::ParameterSet pSetKF_; - // number of bits for internal reciprocal look up - int kfWidthLutInvPhi_; - // number of bits for internal reciprocal look up - int kfWidthLutInvZ_; - // cut on number of input candidates - int kfNumTracks_; + // number of kf worker + int kfNumWorker_; // required number of stub layers to form a track int kfMinLayers_; // maximum number of layers added to a track int kfMaxLayers_; - // cut on number of stub per layer for input candidates - int kfMaxStubsPerLayer_; - // maximum allowed skipped layers from inside to outside to form a track - int kfMaxSkippedLayers_; - int kfBaseShiftr0_; - int kfBaseShiftr02_; - int kfBaseShiftv0_; - int kfBaseShiftS00_; - int kfBaseShiftS01_; - int kfBaseShiftK00_; - int kfBaseShiftK10_; - int kfBaseShiftR00_; - int kfBaseShiftInvR00_; - int kfBaseShiftChi20_; - int kfBaseShiftC00_; - int kfBaseShiftC01_; - int kfBaseShiftC11_; - int kfBaseShiftr1_; - int kfBaseShiftr12_; - int kfBaseShiftv1_; - int kfBaseShiftS12_; - int kfBaseShiftS13_; - int kfBaseShiftK21_; - int kfBaseShiftK31_; - int kfBaseShiftR11_; - int kfBaseShiftInvR11_; - int kfBaseShiftChi21_; - int kfBaseShiftC22_; - int kfBaseShiftC23_; - int kfBaseShiftC33_; - int kfBaseShiftChi2_; + // search window of each track parameter in initial uncertainties + double kfRangeFactor_; + + // Parameter specifying KalmanFilter Output Formatter + edm::ParameterSet pSetKFOut_; + // Bins used to digitize dPhi for chi2 calculation + std::vector kfoutdPhiBins_; + // Bins used to digitize dZ for chi2 calculation + std::vector kfoutdZBins_; + // v0 weight Bins corresponding to dPhi Bins for chi2 calculation + std::vector kfoutv0Bins_; + // v1 weight Bins corresponding to dZ Bins for chi2 calculation + std::vector kfoutv1Bins_; + // Final Chi2rphi digitization TODO extract from TTTrack Word + std::vector kfoutchi2rphiBins_; + // Final Chi2rz digitization TODO extract from TTTrack Word + std::vector kfoutchi2rzBins_; + // Conversion factor between dphi^2/weight and chi2rphi + int kfoutchi2rphiConv_; + // Conversion factor between dz^2/weight and chi2rz + int kfoutchi2rzConv_; + // Number of bits for the tttrack word + int tttrackBits_; + // Fraction of total dphi and dz ranges to calculate v0 and v1 LUT for + int weightBinFraction_; // Parameter specifying DuplicateRemoval edm::ParameterSet pSetDR_; // internal memory depth int drDepthMemory_; - // number of bist used for phi0 - int drWidthPhi0_; - // umber of bist used for qOverPt - int drWidthQoverPt_; - // number of bist used for cot(theta) - int drWidthCot_; - // number of bist used for z0 - int drWidthZ0_; // // Derived constants @@ -739,6 +925,10 @@ namespace trackerDTC { // true if tracker geometry and magnetic field supported bool configurationSupported_; + // selector to partly select TPs for efficiency measurements + TrackingParticleSelector tpSelector_; + // selector to partly select TPs for fake and duplicate rate measurements + TrackingParticleSelector tpSelectorLoose_; // TTStubAlgorithm @@ -769,20 +959,32 @@ namespace trackerDTC { // TMTT // number of bits used for stub layer id - int widthLayer_; + int widthLayerId_; // internal stub r precision in cm - double baseR_; + double tmttBaseR_; // internal stub z precision in cm - double baseZ_; + double tmttBaseZ_; // internal stub phi precision in rad - double basePhi_; + double tmttBasePhi_; + // internal stub inv2R precision in 1/cm + double tmttBaseInv2R_; + // internal stub phiT precision in rad + double tmttBasePhiT_; // number of padded 0s in output data format int dtcNumUnusedBits_; + // number of bits used for stub layer id + int tmttWidthLayer_; + // number of bits used for stub eta sector + int tmttWidthSectorEta_; + // number of bits used for stub inv2R + int tmttWidthInv2R_; + // number of padded 0s in output data format + int tmttNumUnusedBits_; // hybrid // number of bits used for stub layer id - int hybridWidthLayer_; + int hybridWidthLayerId_; // precision or r in cm for (barrelPS, barrel2S, diskPS, disk2S) std::vector hybridBasesR_; // precision or phi in rad for (barrelPS, barrel2S, diskPS, disk2S) @@ -818,18 +1020,14 @@ namespace trackerDTC { int dtcNumMergedRows_; // number of bits used for phi of row slope int dtcWidthM_; - // internal stub q over pt precision in 1 /cm - double dtcBaseQoverPt_; + // internal stub inv2R precision in 1 /cm + double dtcBaseInv2R_; // phi of row slope precision in rad / pitch unit double dtcBaseM_; - // number of bits for internal stub phi - int widthPhiDTC_; // outer index = module window size, inner index = encoded bend, inner value = decoded bend, for ps modules std::vector> encodingsBendPS_; // outer index = module window size, inner index = encoded bend, inner value = decoded bend, for 2s modules std::vector> encodingsBend2S_; - // outer index = dtc id in region, inner index = encoded layerId, inner value = decoded layerId - std::vector> encodingsLayerId_; // collection of outer tracker sensor modules std::vector sensorModules_; // collection of outer tracker sensor modules organised in DTCS [0-215][0-71] @@ -845,99 +1043,30 @@ namespace trackerDTC { double maxZT_; // cut on stub cot theta double maxCot_; - // number of bits used for internal stub sector eta - int widthSectorEta_; - // number of bits to represent z residual w.r.t. sector center - int widthChiZ_; - - // HT - - // number of bits used for candidate q over pt - int htWidthQoverPt_; - // number of bits used for candidate phiT - int htWidthPhiT_; - // number of bits to represent phi residual w.r.t. ht candiate - int widthChiPhi_; - // q over pt bin width precision in 1 /cm - double htBaseQoverPt_; - // phiT bin width precision in rad - double htBasePhiT_; + // total number of sectors + int numSectors_; + // number of unused bits in GP output format + int gpNumUnusedBits_; + // cot(theta) of eta sectors + std::vector sectorCots_; // MHT // number of mht cells int mhtNumCells_; - // number of bits used for candidate q over pt - int mhtWidthQoverPt_; - // number of bits used for candidate phiT - int mhtWidthPhiT_; - // q over pt bin width precision in 1 /cm - double mhtBaseQoverPt_; - // phiT bin width in rad - double mhtBasePhiT_; - - // SF - - // cot(theta) precision - double sfBaseCot_; - // zT precision in cm - double sfBaseZT_; + + // ZHT + + // number of zht cells + int zhtNumCells_; // KF - double kfBasem0_; - double kfBasem1_; - double kfBasev0_; - double kfBasev1_; - double kfBasex0_; - double kfBasex1_; - double kfBasex2_; - double kfBasex3_; - double kfBasex4_; - double kfBaseH00_; - double kfBaseH04_; - double kfBaseH12_; - double kfBaser0_; - double kfBaser1_; - double kfBaser02_; - double kfBaser12_; - double kfBaseS00_; - double kfBaseS01_; - double kfBaseS04_; - double kfBaseS12_; - double kfBaseS13_; - double kfBaseR00_; - double kfBaseR11_; - double kfBaseInvR00_; - double kfBaseInvR11_; - double kfBaseK00_; - double kfBaseK10_; - double kfBaseK21_; - double kfBaseK31_; - double kfBaseK40_; - double kfBaseC00_; - double kfBaseC01_; - double kfBaseC04_; - double kfBaseC11_; - double kfBaseC14_; - double kfBaseC44_; - double kfBaseC22_; - double kfBaseC23_; - double kfBaseC33_; - double kfBaseChi20_; - double kfBaseChi21_; - double kfBaseChi2_; - - // DR - - double drBaseQoverPt_; - double drBasePhi0_; - double drBaseCot_; - double drBaseZ0_; + int kfWidthLayerCount_; }; -} // namespace trackerDTC +} // namespace tt -EVENTSETUP_DATA_DEFAULT_RECORD(trackerDTC::Setup, trackerDTC::SetupRcd); +EVENTSETUP_DATA_DEFAULT_RECORD(tt::Setup, tt::SetupRcd); #endif diff --git a/L1Trigger/TrackerDTC/interface/SetupRcd.h b/L1Trigger/TrackTrigger/interface/SetupRcd.h similarity index 94% rename from L1Trigger/TrackerDTC/interface/SetupRcd.h rename to L1Trigger/TrackTrigger/interface/SetupRcd.h index 25819e66caa98..2a4b324436e3c 100644 --- a/L1Trigger/TrackerDTC/interface/SetupRcd.h +++ b/L1Trigger/TrackTrigger/interface/SetupRcd.h @@ -12,7 +12,7 @@ #include "FWCore/Utilities/interface/mplVector.h" -namespace trackerDTC { +namespace tt { typedef edm::mpl::Vector Rcds; + // record of tt::Setup class SetupRcd : public edm::eventsetup::DependentRecordImplementation {}; -} // namespace trackerDTC +} // namespace tt #endif \ No newline at end of file diff --git a/L1Trigger/TrackTrigger/plugins/BuildFile.xml b/L1Trigger/TrackTrigger/plugins/BuildFile.xml index 9d81221431d34..dbf6e6ba55ad8 100644 --- a/L1Trigger/TrackTrigger/plugins/BuildFile.xml +++ b/L1Trigger/TrackTrigger/plugins/BuildFile.xml @@ -1,6 +1,8 @@ + + diff --git a/L1Trigger/TrackTrigger/plugins/ProducerHPH.cc b/L1Trigger/TrackTrigger/plugins/ProducerHPH.cc new file mode 100644 index 0000000000000..e46d0be9f4bb3 --- /dev/null +++ b/L1Trigger/TrackTrigger/plugins/ProducerHPH.cc @@ -0,0 +1,46 @@ +// This ESproducer produces configuration needed by HitPatternHelper +// +// Created by J.Li on 1/23/21. +// + +#include "FWCore/Framework/interface/ModuleFactory.h" +#include "FWCore/Framework/interface/ESProducer.h" +#include "FWCore/Framework/interface/ESHandle.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/Utilities/interface/ESGetToken.h" +#include "FWCore/Utilities/interface/ESInputTag.h" +#include "DataFormats/Provenance/interface/ParameterSetID.h" +#include "L1Trigger/TrackTrigger/interface/HitPatternHelper.h" +#include "L1Trigger/TrackTrigger/interface/Setup.h" + +#include + +using namespace std; +using namespace edm; + +namespace hph { + + class ProducerHPH : public ESProducer { + public: + ProducerHPH(const ParameterSet& iConfig); + ~ProducerHPH() override {} + unique_ptr produce(const SetupRcd& Rcd); + + private: + const ParameterSet iConfig_; + ESGetToken getTokenSetup_; + }; + + ProducerHPH::ProducerHPH(const ParameterSet& iConfig) : iConfig_(iConfig) { + auto cc = setWhatProduced(this); + getTokenSetup_ = cc.consumes(); + } + + unique_ptr ProducerHPH::produce(const SetupRcd& Rcd) { + const tt::Setup& setupTT = Rcd.get(getTokenSetup_); + return make_unique(iConfig_, setupTT); + } + +} // namespace hph + +DEFINE_FWK_EVENTSETUP_MODULE(hph::ProducerHPH); diff --git a/L1Trigger/TrackerDTC/plugins/ProducerES.cc b/L1Trigger/TrackTrigger/plugins/ProducerSetup.cc similarity index 88% rename from L1Trigger/TrackerDTC/plugins/ProducerES.cc rename to L1Trigger/TrackTrigger/plugins/ProducerSetup.cc index 6110f2fd4310e..51c053df55416 100644 --- a/L1Trigger/TrackerDTC/plugins/ProducerES.cc +++ b/L1Trigger/TrackTrigger/plugins/ProducerSetup.cc @@ -4,26 +4,24 @@ #include "FWCore/Utilities/interface/ESGetToken.h" #include "FWCore/Utilities/interface/ESInputTag.h" #include "DataFormats/Provenance/interface/ParameterSetID.h" -#include "L1Trigger/TrackerDTC/interface/Setup.h" -#include "MagneticField/Engine/interface/MagneticField.h" -#include "MagneticField/Records/interface/IdealMagneticFieldRecord.h" +#include "L1Trigger/TrackTrigger/interface/Setup.h" #include using namespace std; using namespace edm; -namespace trackerDTC { +namespace tt { - /*! \class trackerDTC::ProducerES + /*! \class tt::ProducerSetup * \brief Class to produce setup of Track Trigger emulators * \author Thomas Schuh * \date 2020, Apr */ - class ProducerES : public ESProducer { + class ProducerSetup : public ESProducer { public: - ProducerES(const ParameterSet& iConfig); - ~ProducerES() override {} + ProducerSetup(const ParameterSet& iConfig); + ~ProducerSetup() override {} unique_ptr produce(const SetupRcd& setupRcd); private: @@ -38,7 +36,7 @@ namespace trackerDTC { bool fromDD4hep_; }; - ProducerES::ProducerES(const ParameterSet& iConfig) : iConfig_(iConfig) { + ProducerSetup::ProducerSetup(const ParameterSet& iConfig) : iConfig_(iConfig) { fromDD4hep_ = iConfig.getParameter("fromDD4hep"); auto cc = setWhatProduced(this); getTokenTTStubAlgorithm_ = cc.consumes(); @@ -52,7 +50,7 @@ namespace trackerDTC { getTokenGeometryConfiguration_ = cc.consumes(); } - unique_ptr ProducerES::produce(const SetupRcd& setupRcd) { + unique_ptr ProducerSetup::produce(const SetupRcd& setupRcd) { const MagneticField& magneticField = setupRcd.get(getTokenMagneticField_); const TrackerGeometry& trackerGeometry = setupRcd.get(getTokenTrackerGeometry_); const TrackerTopology& trackerTopology = setupRcd.get(getTokenTrackerTopology_); @@ -93,6 +91,6 @@ namespace trackerDTC { pSetIdGeometryConfiguration); } } -} // namespace trackerDTC +} // namespace tt -DEFINE_FWK_EVENTSETUP_MODULE(trackerDTC::ProducerES); +DEFINE_FWK_EVENTSETUP_MODULE(tt::ProducerSetup); diff --git a/L1Trigger/TrackTrigger/python/ProducerHPH_cff.py b/L1Trigger/TrackTrigger/python/ProducerHPH_cff.py new file mode 100644 index 0000000000000..d788e09a4748b --- /dev/null +++ b/L1Trigger/TrackTrigger/python/ProducerHPH_cff.py @@ -0,0 +1,5 @@ +import FWCore.ParameterSet.Config as cms + +from L1Trigger.TrackTrigger.ProducerHPH_cfi import HitPatternHelper_params + +HitPatternHelperSetup = cms.ESProducer("hph::ProducerHPH", HitPatternHelper_params) diff --git a/L1Trigger/TrackTrigger/python/ProducerHPH_cfi.py b/L1Trigger/TrackTrigger/python/ProducerHPH_cfi.py new file mode 100644 index 0000000000000..ddc4aaa4c1431 --- /dev/null +++ b/L1Trigger/TrackTrigger/python/ProducerHPH_cfi.py @@ -0,0 +1,11 @@ +import FWCore.ParameterSet.Config as cms + +# ParameterSet used by HitPatternHelper + +HitPatternHelper_params = cms.PSet ( + + hphDebug = cms.bool(False), + useNewKF = cms.bool(False), + deltaTanL = cms.double(0.125) + +) diff --git a/L1Trigger/TrackerDTC/python/ProducerES_cff.py b/L1Trigger/TrackTrigger/python/ProducerSetup_cff.py similarity index 74% rename from L1Trigger/TrackerDTC/python/ProducerES_cff.py rename to L1Trigger/TrackTrigger/python/ProducerSetup_cff.py index e62787308b0be..1bb2fc46f0693 100644 --- a/L1Trigger/TrackerDTC/python/ProducerES_cff.py +++ b/L1Trigger/TrackTrigger/python/ProducerSetup_cff.py @@ -1,8 +1,8 @@ import FWCore.ParameterSet.Config as cms -from L1Trigger.TrackerDTC.ProducerES_cfi import TrackTrigger_params - from Configuration.ProcessModifiers.dd4hep_cff import dd4hep +from L1Trigger.TrackTrigger.ProducerSetup_cfi import TrackTrigger_params + dd4hep.toModify(TrackTrigger_params, fromDD4hep = cms.bool(True), ProcessHistory = cms.PSet ( @@ -11,4 +11,4 @@ ) ) -TrackTriggerSetup = cms.ESProducer("trackerDTC::ProducerES", TrackTrigger_params) +TrackTriggerSetup = cms.ESProducer("tt::ProducerSetup", TrackTrigger_params) diff --git a/L1Trigger/TrackTrigger/python/ProducerSetup_cfi.py b/L1Trigger/TrackTrigger/python/ProducerSetup_cfi.py new file mode 100644 index 0000000000000..253de0fcb02da --- /dev/null +++ b/L1Trigger/TrackTrigger/python/ProducerSetup_cfi.py @@ -0,0 +1,228 @@ +import FWCore.ParameterSet.Config as cms + +TrackTrigger_params = cms.PSet ( + + fromDD4hep = cms.bool(False), + + # Parameter to check if configured Tracker Geometry is supported + # this refers to files included by Configuration/Geometry/python/GeometryExtended*_cff.py + UnSupportedGeometry = cms.PSet ( + XMLLabel = cms.string ("geomXMLFiles" ), # label of ESProducer/ESSource + XMLPath = cms.string ("Geometry/TrackerCommonData/data/PhaseII/" ), # compared path + XMLFile = cms.string ("tracker.xml" ), # compared filen ame + XMLVersions = cms.vstring() # list of unsupported versions + ), + + # Parameter to check if Process History is consistent with process configuration + ProcessHistory = cms.PSet ( + GeometryConfiguration = cms.string( "XMLIdealGeometryESSource@" ), # label of compared GeometryConfiguration + TTStubAlgorithm = cms.string( "TTStubAlgorithm_official_Phase2TrackerDigi_@" ) # label of compared TTStubAlgorithm + ), + + # Common track finding parameter + TrackFinding = cms.PSet ( + BeamWindowZ = cms.double( 15. ), # half lumi region size in cm + MatchedLayers = cms.int32 ( 4 ), # required number of layers a found track has to have in common with a TP to consider it matched to it + MatchedLayersPS = cms.int32 ( 0 ), # required number of ps layers a found track has to have in common with a TP to consider it matched to it + UnMatchedStubs = cms.int32 ( 1 ), # allowed number of stubs a found track may have not in common with its matched TP + UnMatchedStubsPS = cms.int32 ( 0 ), # allowed number of PS stubs a found track may have not in common with its matched TP + Scattering = cms.double( 0.131283 ) # additional radial uncertainty in cm used to calculate stub phi residual uncertainty to take multiple scattering into account + ), + + # TMTT specific parameter + TMTT = cms.PSet ( + MinPt = cms.double( 3. ), # cut on stub in GeV, also defines region overlap shape + MaxEta = cms.double( 2.4 ), # cut on stub eta + ChosenRofPhi = cms.double( 67.24 ), # critical radius defining region overlap shape in cm + NumLayers = cms.int32 ( 7 ), # number of detector layers a reconstructbale particle may cross, reduced to 7, 8th layer almost never corssed + WidthR = cms.int32 ( 12 ), # number of bits used for stub r - ChosenRofPhi + WidthPhi = cms.int32 ( 15 ), # number of bits used for stub phi w.r.t. phi region centre + WidthZ = cms.int32 ( 14 ) # number of bits used for stub z + ), + + # Hybrid specific parameter + Hybrid = cms.PSet ( + MinPtStub = cms.double( 2.0 ), # cut on stub pt in GeV, also defines region overlap shape + MinPtCand = cms.double( 1.34 ), # cut on candidate pt in GeV + MaxEta = cms.double( 2.5 ), # cut on stub eta + ChosenRofPhi = cms.double( 55. ), # critical radius defining region overlap shape in cm + NumLayers = cms.int32 ( 4 ), # max number of detector layer connected to one DTC + NumRingsPS = cms.vint32 ( 11, 11, 8, 8, 8 ), # number of outer PS rings for disk 1, 2, 3, 4, 5 + WidthsR = cms.vint32 ( 7, 7, 12, 7 ), # number of bits used for stub r w.r.t layer/disk centre for module types (barrelPS, barrel2S, diskPS, disk2S) + WidthsZ = cms.vint32 ( 12, 8, 7, 7 ), # number of bits used for stub z w.r.t layer/disk centre for module types (barrelPS, barrel2S, diskPS, disk2S) + WidthsPhi = cms.vint32 ( 14, 17, 14, 14 ), # number of bits used for stub phi w.r.t. region centre for module types (barrelPS, barrel2S, diskPS, disk2S) + WidthsAlpha = cms.vint32 ( 0, 0, 0, 4 ), # number of bits used for stub row number for module types (barrelPS, barrel2S, diskPS, disk2S) + WidthsBend = cms.vint32 ( 3, 4, 3, 4 ), # number of bits used for stub bend number for module types (barrelPS, barrel2S, diskPS, disk2S) + RangesR = cms.vdouble( 7.5, 7.5, 120. , 0. ), # range in stub r which needs to be covered for module types (barrelPS, barrel2S, diskPS, disk2S) + RangesZ = cms.vdouble( 240., 240., 7.5, 7.5 ), # range in stub z which needs to be covered for module types (barrelPS, barrel2S, diskPS, disk2S) + RangesAlpha = cms.vdouble( 0., 0., 0., 2048. ), # range in stub row which needs to be covered for module types (barrelPS, barrel2S, diskPS, disk2S) + LayerRs = cms.vdouble( 24.9316, 37.1777, 52.2656, 68.7598, 86.0156, 108.3105 ), # mean radius of outer tracker barrel layer + DiskZs = cms.vdouble( 131.1914, 154.9805, 185.3320, 221.6016, 265.0195 ), # mean z of outer tracker endcap disks + Disk2SRsSet = cms.VPSet( # center radius of outer tracker endcap 2S diks strips + cms.PSet( Disk2SRs = cms.vdouble( 66.4391, 71.4391, 76.2750, 81.2750, 82.9550, 87.9550, 93.8150, 98.8150, 99.8160, 104.8160 ) ), # disk 1 + cms.PSet( Disk2SRs = cms.vdouble( 66.4391, 71.4391, 76.2750, 81.2750, 82.9550, 87.9550, 93.8150, 98.8150, 99.8160, 104.8160 ) ), # disk 2 + cms.PSet( Disk2SRs = cms.vdouble( 63.9903, 68.9903, 74.2750, 79.2750, 81.9562, 86.9562, 92.4920, 97.4920, 99.8160, 104.8160 ) ), # disk 3 + cms.PSet( Disk2SRs = cms.vdouble( 63.9903, 68.9903, 74.2750, 79.2750, 81.9562, 86.9562, 92.4920, 97.4920, 99.8160, 104.8160 ) ), # disk 4 + cms.PSet( Disk2SRs = cms.vdouble( 63.9903, 68.9903, 74.2750, 79.2750, 81.9562, 86.9562, 92.4920, 97.4920, 99.8160, 104.8160 ) ) # disk 5 + ), + InnerRadius = cms.double( 19.6 ), # smallest stub radius after TrackBuilder in cm + ), + + # Parameter specifying TrackingParticle used for Efficiency measurements + TrackingParticle = cms.PSet ( + MinPt = cms.double( 2. ), # pt cut in GeV + MaxEta = cms.double( 2.4 ), # eta cut + MaxVertR = cms.double( 1. ), # cut on vertex pos r in cm + MaxVertZ = cms.double( 30. ), # cut on vertex pos z in cm + MaxD0 = cms.double( 5. ), # cut on impact parameter in cm + MinLayers = cms.int32 ( 4 ), # required number of associated layers to a TP to consider it reconstruct-able and to match it with TTTrack + MinLayersPS = cms.int32 ( 0 ), # required number of associated ps layers to a TP to consider it reconstruct-able + MaxBadStubs2S = cms.int32 ( 1 ), # max number of unassociated 2S stubs allowed to still associate TTTrack with TP + MaxBadStubsPS = cms.int32 ( 0 ) # max number of unassociated PS stubs allowed to still associate TTTrack with TP + ), + + # Fimrware specific Parameter + Firmware = cms.PSet ( + WidthDSPa = cms.int32( 27 ), # width of the 'A' port of an DSP slice + WidthDSPb = cms.int32( 18 ), # width of the 'B' port of an DSP slice + WidthDSPc = cms.int32( 48 ), # width of the 'C' port of an DSP slice + WidthAddrBRAM36 = cms.int32( 9 ), # smallest address width of an BRAM36 configured as broadest simple dual port memory + WidthAddrBRAM18 = cms.int32( 10 ), # smallest address width of an BRAM18 configured as broadest simple dual port memory + NumFramesInfra = cms.int32 ( 6 ), # needed gap between events of emp-infrastructure firmware + FreqLHC = cms.double( 40. ), # LHC bunch crossing rate in MHz + FreqBE = cms.double( 360. ), # processing Frequency of DTC, KF & TFP in MHz, has to be integer multiple of FreqLHC + TMP_FE = cms.int32 ( 8 ), # number of events collected in front-end + TMP_TFP = cms.int32 ( 18 ), # time multiplexed period of track finding processor + SpeedOfLight = cms.double( 2.99792458 ), # in e8 m/s + BField = cms.double( 3.81120228767395 ), # in T + BFieldError = cms.double( 1.e-6 ), # accepted difference to EventSetup in T + OuterRadius = cms.double( 112.7 ), # outer radius of outer tracker in cm + InnerRadius = cms.double( 21.8 ), # inner radius of outer tracker in cm + HalfLength = cms.double( 270. ), # half length of outer tracker in cm + TiltApproxSlope = cms.double( 0.884 ), # In tilted barrel, grad*|z|/r + int approximates |cosTilt| + |sinTilt * cotTheta| + TiltApproxIntercept = cms.double( 0.507 ), # In tilted barrel, grad*|z|/r + int approximates |cosTilt| + |sinTilt * cotTheta| + TiltUncertaintyR = cms.double( 0.12 ), # In tilted barrel, constant assumed stub radial uncertainty * sqrt(12) in cm + MindPhi = cms.double( 0.0001 ), # minimum representable stub phi uncertainty * sqrt(12) + additional terms in rad + MaxdPhi = cms.double( 0.02 ), # maximum representable stub phi uncertainty * sqrt(12) + additional terms in rad + MindZ = cms.double( 0.1 ), # minimum representable stub z uncertainty * sqrt(12) + additional terms in cm + MaxdZ = cms.double( 30. ), # maximum representable stub z uncertainty * sqrt(12) + additional terms in cm + Pitch2S = cms.double( 0.009 ), # strip pitch of outer tracker sensors in cm + PitchPS = cms.double( 0.01 ), # pixel pitch of outer tracker sensors in cm + Length2S = cms.double( 5.025 ), # strip length of outer tracker sensors in cm + LengthPS = cms.double( 0.1467 ), # pixel length of outer tracker sensors in cm + TiltedLayerLimitsZ = cms.vdouble( 15.5, 24.9, 34.3, -1., -1., -1. ), # barrel layer limit |z| value to partition into tilted and untilted region + PSDiskLimitsR = cms.vdouble( 66.4, 66.4, 64.55, 64.55, 64.55 ), # endcap disk limit r value to partition into PS and 2S region + ), + + # Parmeter specifying front-end + FrontEnd = cms.PSet ( + WidthBend = cms.int32 ( 6 ), # number of bits used for internal stub bend + WidthCol = cms.int32 ( 5 ), # number of bits used for internal stub column + WidthRow = cms.int32 ( 11 ), # number of bits used for internal stub row + BaseBend = cms.double( .25 ), # precision of internal stub bend in pitch units + BaseCol = cms.double( 1. ), # precision of internal stub column in pitch units + BaseRow = cms.double( .5 ), # precision of internal stub row in pitch units + BaseWindowSize = cms.double( .5 ), # precision of window sizes in pitch units + BendCut = cms.double( 1.3125 ) # used stub bend uncertainty in pitch units + ), + + # Parmeter specifying DTC + DTC = cms.PSet ( + NumRegions = cms.int32( 9 ), # number of phi slices the outer tracker readout is organized in + NumOverlappingRegions = cms.int32( 2 ), # number of regions a reconstructable particles may cross + NumATCASlots = cms.int32( 12 ), # number of Slots in used ATCA crates + NumDTCsPerRegion = cms.int32( 24 ), # number of DTC boards used to readout a detector region, likely constructed to be an integerer multiple of NumSlots_ + NumModulesPerDTC = cms.int32( 72 ), # max number of sensor modules connected to one DTC board + NumRoutingBlocks = cms.int32( 2 ), # number of systiloic arrays in stub router firmware + DepthMemory = cms.int32( 64 ), # fifo depth in stub router firmware + WidthRowLUT = cms.int32( 4 ), # number of row bits used in look up table + WidthInv2R = cms.int32( 9 ), # number of bits used for stub inv2R. lut addr is col + bend = 11 => 1 BRAM -> 18 bits for min and max val -> 9 + OffsetDetIdDSV = cms.int32( 1 ), # tk layout det id minus DetSetVec->detId + OffsetDetIdTP = cms.int32( -1 ), # tk layout det id minus TrackerTopology lower det id + OffsetLayerDisks = cms.int32( 10 ), # offset in layer ids between barrel layer and endcap disks + OffsetLayerId = cms.int32( 1 ), # offset between 0 and smallest layer id (barrel layer 1) + SlotLimitPS = cms.int32( 6 ), # slot number changing from PS to 2S + SlotLimit10gbps = cms.int32( 3 ) # slot number changing from 10 gbps to 5gbps + ), + + # Parmeter specifying TFP + TFP = cms.PSet ( + WidthPhi0 = cms.int32( 12 ), # number of bist used for phi0 + WidthInv2R = cms.int32( 15 ), # number of bist used for inv2R + WidthCot = cms.int32( 16 ), # number of bist used for cot(theta) + WidthZ0 = cms.int32( 12 ), # number of bist used for z0 + NumChannel = cms.int32( 2 ) # number of output links + ), + + # Parmeter specifying GeometricProcessor + GeometricProcessor = cms.PSet ( + NumSectorsPhi = cms.int32 ( 2 ), # number of phi sectors used in hough transform + ChosenRofZ = cms.double( 50. ), # critical radius defining r-z sector shape in cm + RangeChiZ = cms.double( 160. ), # range of stub z residual w.r.t. sector center which needs to be covered + DepthMemory = cms.int32 ( 64 ), # fifo depth in stub router firmware + #BoundariesEta = cms.vdouble( -2.40, -2.08, -1.68, -1.26, -0.90, -0.62, -0.41, -0.20, 0.0, 0.20, 0.41, 0.62, 0.90, 1.26, 1.68, 2.08, 2.40 ) # defining r-z sector shape + BoundariesEta = cms.vdouble( -2.50, -2.23, -1.88, -1.36, -0.90, -0.62, -0.41, -0.20, 0.0, 0.20, 0.41, 0.62, 0.90, 1.36, 1.88, 2.23, 2.50 ) # defining r-z sector shape + ), + + # Parmeter specifying HoughTransform + HoughTransform = cms.PSet ( + NumBinsInv2R = cms.int32( 16 ), # number of used inv2R bins + NumBinsPhiT = cms.int32( 32 ), # number of used phiT bins + MinLayers = cms.int32( 5 ), # required number of stub layers to form a candidate + DepthMemory = cms.int32( 32 ) # internal fifo depth + ), + + # Parmeter specifying MiniHoughTransform + MiniHoughTransform = cms.PSet ( + NumBinsInv2R = cms.int32( 2 ), # number of finer inv2R bins inside HT bin + NumBinsPhiT = cms.int32( 2 ), # number of finer phiT bins inside HT bin + NumDLBs = cms.int32( 2 ), # number of dynamic load balancing steps + NumDLBNodes = cms.int32( 8 ), # number of units per dynamic load balancing step + NumDLBChannel = cms.int32( 2 ), # number of inputs per dynamic load balancing unit + MinLayers = cms.int32( 5 ) # required number of stub layers to form a candidate + ), + + # Parmeter specifying ZHoughTransform + ZHoughTransform = cms.PSet ( + NumBinsZT = cms.int32( 2 ), # + NumBinsCot = cms.int32( 2 ), # + NumStages = cms.int32( 5 ), # + MinLayers = cms.int32( 4 ), # required number of stub layers to form a candidate + MaxTracks = cms.int32( 16 ), # max number of output tracks per node + MaxStubsPerLayer = cms.int32( 4 ) # cut on number of stub per layer for input candidates + ), + + # Parmeter specifying KalmanFilter Input Formatter + + KalmanFilterIn = cms.PSet ( + ShiftRangePhi = cms.int32( 2 ), # power of 2 multiplier of stub phi residual range + ShiftRangeZ = cms.int32( 1 ) # power of 2 multiplier of stub z residual range + ), + + # Parmeter specifying KalmanFilter + KalmanFilter = cms.PSet ( + NumWorker = cms.int32 ( 2 ), # number of kf worker + RangeFactor = cms.double( 2.0 ), # search window of each track parameter in initial uncertainties + MinLayers = cms.int32 ( 4 ), # required number of stub layers to form a track + MaxLayers = cms.int32 ( 7 ) # maximum number of layers added to a track + ), + + # Parmeter specifying KalmanFilter Output Formatter + KalmanFilterOut = cms.PSet ( + chi2rphiBins = cms.vdouble( 0, 0.25, 0.5, 1, 2, 3, 5, 7, 10, 20, 40, 100, 200, 500, 1000, 3000,6000 ), # Final Chi2rphi digitization TODO extract from TTTrack Word + chi2rzBins = cms.vdouble( 0, 0.25, 0.5, 1, 2, 3, 5, 7, 10, 20, 40, 100, 200, 500, 1000, 3000,6000 ), # Final Chi2rz digitization TODO extract from TTTrack Word + + chi2rphiConv = cms.int32 ( 3 ), # Conversion factor between dphi^2/weight and chi2rphi + chi2rzConv = cms.int32 ( 13 ), # Conversion factor between dz^2/weight and chi2rz + + WeightBinFraction = cms.int32( 0 ), # Number of bits dropped from dphi and dz for v0 and v1 LUTs + + TTTrackBits = cms.int32( 96 ) # Number of bits for the tttrack word TODO extract from TTTrack_word dataformat + ), + + # Parmeter specifying DuplicateRemoval + DuplicateRemoval = cms.PSet ( + DepthMemory = cms.int32( 16 ) # internal memory depth + ) + +) diff --git a/L1Trigger/TrackTrigger/python/TrackQualityParams_cfi.py b/L1Trigger/TrackTrigger/python/TrackQualityParams_cfi.py index 6b19f0ede10af..fbfd22f0944a9 100644 --- a/L1Trigger/TrackTrigger/python/TrackQualityParams_cfi.py +++ b/L1Trigger/TrackTrigger/python/TrackQualityParams_cfi.py @@ -16,6 +16,4 @@ bendchi2Max = cms.double( 2.4 ), minPt = cms.double( 2. ), # in GeV nStubsmin = cms.int32( 4 ), - - ONNXInvRScale = cms.double(500) # Scaling InvR to same order of magnitude as other variables for ML models ) diff --git a/L1Trigger/TrackTrigger/src/ES_HitPatternHelper.cc b/L1Trigger/TrackTrigger/src/ES_HitPatternHelper.cc new file mode 100644 index 0000000000000..24881410dc8f7 --- /dev/null +++ b/L1Trigger/TrackTrigger/src/ES_HitPatternHelper.cc @@ -0,0 +1,8 @@ +// +// Created by J.Li on 1/23/21. +// + +#include "FWCore/Utilities/interface/typelookup.h" +#include "L1Trigger/TrackTrigger/interface/HitPatternHelper.h" + +TYPELOOKUP_DATA_REG(hph::Setup); diff --git a/L1Trigger/TrackTrigger/src/ES_Setup.cc b/L1Trigger/TrackTrigger/src/ES_Setup.cc new file mode 100644 index 0000000000000..c600cb42fefab --- /dev/null +++ b/L1Trigger/TrackTrigger/src/ES_Setup.cc @@ -0,0 +1,4 @@ +#include "FWCore/Utilities/interface/typelookup.h" +#include "L1Trigger/TrackTrigger/interface/Setup.h" + +TYPELOOKUP_DATA_REG(tt::Setup); \ No newline at end of file diff --git a/L1Trigger/TrackTrigger/src/HitPatternHelper.cc b/L1Trigger/TrackTrigger/src/HitPatternHelper.cc new file mode 100644 index 0000000000000..8beaef9352ae0 --- /dev/null +++ b/L1Trigger/TrackTrigger/src/HitPatternHelper.cc @@ -0,0 +1,273 @@ +// +// Created by J.Li on 1/23/21. +// + +#include "L1Trigger/TrackTrigger/interface/HitPatternHelper.h" +#include "L1Trigger/TrackFindingTMTT/interface/KFbase.h" +#include "L1Trigger/TrackFindingTMTT/interface/TrackerModule.h" + +#include "FWCore/MessageLogger/interface/MessageLogger.h" + +#include +#include + +namespace hph { + + Setup::Setup(const edm::ParameterSet& iConfig, const tt::Setup& setupTT) + : iConfig_(iConfig), + setupTT_(setupTT), + layerIds_(), + layermap_(), + nEtaRegions_(tmtt::KFbase::nEta_ / 2), + nKalmanLayers_(tmtt::KFbase::nKFlayer_) { + for (const tt::SensorModule& sm : setupTT_.sensorModules()) { + layerIds_.push_back(std::make_pair(sm.layerId(), sm.barrel())); + } + sort(layerIds_.begin(), layerIds_.end(), smallerID); + layerIds_.erase(unique(layerIds_.begin(), layerIds_.end(), equalID), layerIds_.end()); //Keep only unique layerIds + // Converting tmtt::KFbase::layerMap_ to a format that is acceptatble by HitPatternHelper + for (int i = 0; i < nEtaRegions_; i++) { + for (int j = 0; j < (int)layerIds_.size(); j++) { + int layer = nKalmanLayers_; + if (layerIds_[j].second) { + layer = tmtt::KFbase::layerMap_[i][tmtt::TrackerModule::calcLayerIdReduced(layerIds_[j].first)].first; + } else { + layer = tmtt::KFbase::layerMap_[i][tmtt::TrackerModule::calcLayerIdReduced(layerIds_[j].first)].second; + } + if (layer < nKalmanLayers_) { + layermap_[i][layer].push_back(layerIds_[j].first); + } + } + } + } + + HitPatternHelper::HitPatternHelper(const Setup* setup, int hitpattern, double cot, double z0) + : hitpattern_(hitpattern), + numExpLayer_(0), + numMissingLayer_(0), + numMissingPS_(0), + numMissing2S_(0), + numPS_(0), + num2S_(0), + numMissingInterior1_(0), + numMissingInterior2_(0), + cot_(cot), + z0_(z0), + setup_(setup), + binary_(11, 0), + hphDebug_(setup_->hphDebug()), + useNewKF_(setup_->useNewKF()), + chosenRofZ_(setup_->chosenRofZ()), + deltaTanL_(setup_->deltaTanL()), + etaRegions_(setup_->etaRegions()), + nKalmanLayers_(setup_->nKalmanLayers()), + layermap_(setup_->layermap()) { + //Calculating eta sector based on cot and z0 + float kfzRef = z0_ + chosenRofZ_ * cot_; + int kf_eta_reg = 0; + for (int iEtaSec = 1; iEtaSec < ((int)etaRegions_.size() - 1); iEtaSec++) { // Doesn't apply eta < 2.4 cut. + float etaMax = etaRegions_[iEtaSec]; + float zRefMax = chosenRofZ_ / tan(2. * atan(exp(-etaMax))); + if (kfzRef > zRefMax) { + kf_eta_reg = iEtaSec; + } + } + etaSector_ = kf_eta_reg; + if (kf_eta_reg < ((int)etaRegions_.size() - 1) / 2) { + kf_eta_reg = ((int)etaRegions_.size() - 1) / 2 - 1 - kf_eta_reg; + } else { + kf_eta_reg = kf_eta_reg - (int)(etaRegions_.size() - 1) / 2; + } + //Looping over sensor modules to make predictions on which layers particles are expected to hit + for (const tt::SensorModule& sm : setup_->sensorModules()) { + double d = (z0_ - sm.z() + sm.r() * cot_) / (sm.cosTilt() - sm.sinTilt() * cot_); + double d_p = + (z0_ - sm.z() + sm.r() * (cot_ + deltaTanL_ / 2)) / (sm.cosTilt() - sm.sinTilt() * (cot_ + deltaTanL_ / 2)); + double d_m = + (z0_ - sm.z() + sm.r() * (cot_ - deltaTanL_ / 2)) / (sm.cosTilt() - sm.sinTilt() * (cot_ - deltaTanL_ / 2)); + if (useNewKF_ && + (abs(d_p) < sm.numColumns() * sm.pitchCol() / 2. || abs(d_m) < sm.numColumns() * sm.pitchCol() / 2.)) { + layers_.push_back(sm); + } + if (!useNewKF_ && abs(d) < sm.numColumns() * sm.pitchCol() / 2.) { + layers_.push_back(sm); + } + } + //layers_ constains all the sensor modules that particles are expected to hit + sort(layers_.begin(), layers_.end(), smallerID); + layers_.erase(unique(layers_.begin(), layers_.end(), equalID), layers_.end()); //Keep only one sensor per layer + + numExpLayer_ = layers_.size(); + + int nbits = floor(log2(hitpattern_)) + 1; + int lay_i = 0; + bool seq = false; + for (int i = 0; i < nbits; i++) { + lay_i = ((1 << i) & hitpattern_) >> i; //0 or 1 in ith bit (right to left) + + if (lay_i && !seq) + seq = true; //sequence starts when first 1 found + if (!lay_i && seq) { + numMissingInterior1_++; //This is the same as the "tmp_trk_nlaymiss_interior" calculated in Trackquality.cc + } + if (!lay_i) { + bool realhit = false; + if (layermap_[kf_eta_reg][i].empty()) + continue; + for (int j : layermap_[kf_eta_reg][i]) { + int k = findLayer(j); + if (k > 0) + realhit = true; + } + if (realhit) + numMissingInterior2_++; //This variable doesn't make sense for new KF because it uses the layermap from Old KF + } + } + + if (hphDebug_) { + if (useNewKF_) { + edm::LogVerbatim("TrackTriggerHPH") << "Running with New KF"; + } else { + edm::LogVerbatim("TrackTriggerHPH") << "Running with Old KF"; + } + edm::LogVerbatim("TrackTriggerHPH") << "======================================================"; + edm::LogVerbatim("TrackTriggerHPH") + << "Looking at hitpattern " << std::bitset<7>(hitpattern_) << "; Looping over KF layers:"; + } + + if (useNewKF_) { + //New KF uses sensor modules to determine the hitmask already + for (int i = 0; i < numExpLayer_; i++) { + if (hphDebug_) { + edm::LogVerbatim("TrackTriggerHPH") << "--------------------------"; + edm::LogVerbatim("TrackTriggerHPH") << "Looking at KF layer " << i; + if (layers_[i].layerId() < 10) { + edm::LogVerbatim("TrackTriggerHPH") << "KF expects L" << layers_[i].layerId(); + } else { + edm::LogVerbatim("TrackTriggerHPH") << "KF expects D" << layers_[i].layerId() - 10; + } + } + + if (((1 << i) & hitpattern_) >> i) { + if (hphDebug_) { + edm::LogVerbatim("TrackTriggerHPH") << "Layer found in hitpattern"; + } + + binary_[ReducedId(layers_[i].layerId())] = 1; + if (layers_[i].psModule()) { + numPS_++; + } else { + num2S_++; + } + } else { + if (hphDebug_) { + edm::LogVerbatim("TrackTriggerHPH") << "Layer missing in hitpattern"; + } + + if (layers_[i].psModule()) { + numMissingPS_++; + } else { + numMissing2S_++; + } + } + } + + } else { + //Old KF uses the hard coded layermap to determien hitmask + for (int i = 0; i < nKalmanLayers_; i++) { //Loop over each digit of hitpattern + + if (hphDebug_) { + edm::LogVerbatim("TrackTriggerHPH") << "--------------------------"; + edm::LogVerbatim("TrackTriggerHPH") << "Looking at KF layer " << i; + } + + if (layermap_[kf_eta_reg][i].empty()) { + if (hphDebug_) { + edm::LogVerbatim("TrackTriggerHPH") << "KF does not expect this layer"; + } + + continue; + } + + for (int j : + layermap_[kf_eta_reg][i]) { //Find out which layer the Old KF is dealing with when hitpattern is encoded + + if (hphDebug_) { + if (j < 10) { + edm::LogVerbatim("TrackTriggerHPH") << "KF expects L" << j; + } else { + edm::LogVerbatim("TrackTriggerHPH") << "KF expects D" << j - 10; + } + } + + int k = findLayer(j); + if (k < 0) { + //k<0 means even though layer j is predicted by Old KF, this prediction is rejected because it contradicts + if (hphDebug_) { //a more accurate prediction made with the help of information from sensor modules + edm::LogVerbatim("TrackTriggerHPH") << "Rejected by sensor modules"; + } + + continue; + } + + if (hphDebug_) { + edm::LogVerbatim("TrackTriggerHPH") << "Confirmed by sensor modules"; + } + //prediction is accepted + if (((1 << i) & hitpattern_) >> i) { + if (hphDebug_) { + edm::LogVerbatim("TrackTriggerHPH") << "Layer found in hitpattern"; + } + + binary_[ReducedId(j)] = 1; + if (layers_[k].psModule()) { + numPS_++; + } else { + num2S_++; + } + } else { + if (hphDebug_) { + edm::LogVerbatim("TrackTriggerHPH") << "Layer missing in hitpattern"; + } + + if (layers_[k].psModule()) { + numMissingPS_++; + } else { + numMissing2S_++; + } + } + } + } + } + + if (hphDebug_) { + edm::LogVerbatim("TrackTriggerHPH") << "------------------------------"; + edm::LogVerbatim("TrackTriggerHPH") << "numPS = " << numPS_ << ", num2S = " << num2S_ + << ", missingPS = " << numMissingPS_ << ", missing2S = " << numMissing2S_; + edm::LogVerbatim("TrackTriggerHPH") << "======================================================"; + } + } + + int HitPatternHelper::ReducedId(int layerId) { + if (hphDebug_ && (layerId > 15 || layerId < 1)) { + edm::LogVerbatim("TrackTriggerHPH") << "Warning: invalid layer id !"; + } + if (layerId <= 6) { + layerId = layerId - 1; + return layerId; + } else { + layerId = layerId - 5; + return layerId; + } + }; + + int HitPatternHelper::findLayer(int layerId) { + for (int i = 0; i < (int)layers_.size(); i++) { + if (layerId == (int)layers_[i].layerId()) { + return i; + } + } + return -1; + } + +} // namespace hph diff --git a/L1Trigger/TrackTrigger/src/HitPatternHelperRcd.cc b/L1Trigger/TrackTrigger/src/HitPatternHelperRcd.cc new file mode 100644 index 0000000000000..b502d531ccc05 --- /dev/null +++ b/L1Trigger/TrackTrigger/src/HitPatternHelperRcd.cc @@ -0,0 +1,8 @@ +// +// Created by J.Li on 1/23/21. +// + +#include "L1Trigger/TrackTrigger/interface/HitPatternHelperRcd.h" +#include "FWCore/Framework/interface/eventsetuprecord_registration_macro.h" + +EVENTSETUP_RECORD_REG(hph::SetupRcd); diff --git a/L1Trigger/TrackTrigger/src/L1TrackQuality.cc b/L1Trigger/TrackTrigger/src/L1TrackQuality.cc index 17c3ff6b28259..06c9dfa1a99dc 100644 --- a/L1Trigger/TrackTrigger/src/L1TrackQuality.cc +++ b/L1Trigger/TrackTrigger/src/L1TrackQuality.cc @@ -5,13 +5,12 @@ C.Brown & C.Savard 07/2020 */ #include "L1Trigger/TrackTrigger/interface/L1TrackQuality.h" -#include "PhysicsTools/ONNXRuntime/interface/ONNXRuntime.h" //Constructors L1TrackQuality::L1TrackQuality() {} -L1TrackQuality::L1TrackQuality(const edm::ParameterSet& qualityParams) { +L1TrackQuality::L1TrackQuality(const edm::ParameterSet& qualityParams) : setupHPH_(), useHPH_(false) { std::string AlgorithmString = qualityParams.getParameter("qualityAlgorithm"); // Unpacks EDM parameter set itself to save unecessary processing within TrackProducers if (AlgorithmString == "Cut") { @@ -29,50 +28,27 @@ L1TrackQuality::L1TrackQuality(const edm::ParameterSet& qualityParams) { qualityParams.getParameter("ONNXmodel"), qualityParams.getParameter("ONNXInputName"), qualityParams.getParameter>("featureNames")); - ONNXInvRScaling_ = qualityParams.getParameter("ONNXInvRScale"); + runTime_ = std::make_unique(this->ONNXmodel_.fullPath()); } } std::vector L1TrackQuality::featureTransform(TTTrack& aTrack, std::vector const& featureNames) { - // List input features for MVA in proper order below, the features options are - // {"log_chi2","log_chi2rphi","log_chi2rz","log_bendchi2","nstubs","lay1_hits","lay2_hits", - // "lay3_hits","lay4_hits","lay5_hits","lay6_hits","disk1_hits","disk2_hits","disk3_hits", - // "disk4_hits","disk5_hits","rinv","tanl","z0","dtot","ltot","chi2","chi2rz","chi2rphi", - // "bendchi2","pt","eta","nlaymiss_interior","phi","bendchi2_bin","chi2rz_bin","chi2rphi_bin"} + // List input features for MVA in proper order below, the current features options are + // {"phi", "eta", "z0", "bendchi2_bin", "nstub", "nlaymiss_interior", "chi2rphi_bin", + // "chi2rz_bin"} + // + // To use more features, they must be created here and added to feature_map below std::vector transformedFeatures; // Define feature map, filled as features are generated std::map feature_map; - // The following converts the 7 bit hitmask in the TTTrackword to an expected - // 11 bit hitmask based on the eta of the track - std::vector hitpattern_binary = {0, 0, 0, 0, 0, 0, 0}; - std::vector hitpattern_expanded_binary = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - std::vector eta_bins = {0.0, 0.2, 0.41, 0.62, 0.9, 1.26, 1.68, 2.08, 2.4}; - - // Expected hitmap table, each row corresponds to an eta bin, each value corresponds to - // the expected layer in the expanded hit pattern. The expanded hit pattern should be - // 11 bits but contains a 12th element so this hitmap table is symmetric - int hitmap[8][7] = {{0, 1, 2, 3, 4, 5, 11}, - {0, 1, 2, 3, 4, 5, 11}, - {0, 1, 2, 3, 4, 5, 11}, - {0, 1, 2, 3, 4, 5, 11}, - {0, 1, 2, 3, 4, 5, 11}, - {0, 1, 2, 6, 7, 8, 9}, - {0, 1, 7, 8, 9, 10, 11}, - {0, 6, 7, 8, 9, 10, 11}}; - - // iterate through bits of the hitpattern and compare to 1 filling the hitpattern binary vector - int tmp_trk_hitpattern = aTrack.hitPattern(); - for (int i = 6; i >= 0; i--) { - int k = tmp_trk_hitpattern >> i; - if (k & 1) - hitpattern_binary[i] = 1; - } + // -------- calculate feature variables -------- // calculate number of missed interior layers from hitpattern + int tmp_trk_hitpattern = aTrack.hitPattern(); int nbits = floor(log2(tmp_trk_hitpattern)) + 1; int lay_i = 0; int tmp_trk_nlaymiss_interior = 0; @@ -86,119 +62,35 @@ std::vector L1TrackQuality::featureTransform(TTTrack(eta_bins.size()); - // First iterate through eta bins - - for (int j = 1; j < eta_size; j++) { - if (eta < eta_bins[j] && eta >= eta_bins[j - 1]) // if track in eta bin - { - // Iterate through hitpattern binary - for (int k = 0; k <= 6; k++) - // Fill expanded binary entries using the expected hitmap table positions - hitpattern_expanded_binary[hitmap[j - 1][k]] = hitpattern_binary[k]; - break; - } - } - - int tmp_trk_ltot = 0; - //calculate number of layer hits - for (int i = 0; i < 6; ++i) { - tmp_trk_ltot += hitpattern_expanded_binary[i]; - } - - int tmp_trk_dtot = 0; - //calculate number of disk hits - for (int i = 6; i < 11; ++i) { - tmp_trk_dtot += hitpattern_expanded_binary[i]; - } + // binned chi2 variables + int tmp_trk_bendchi2_bin = aTrack.getBendChi2Bits(); + int tmp_trk_chi2rphi_bin = aTrack.getChi2RPhiBits(); + int tmp_trk_chi2rz_bin = aTrack.getChi2RZBits(); - // bin bendchi2 variable (bins from https://twiki.cern.ch/twiki/bin/viewauth/CMS/HybridDataFormat#Fitted_Tracks_written_by_KalmanF) - float tmp_trk_bendchi2 = aTrack.stubPtConsistency(); - std::array bendchi2_bins{{0, 0.5, 1.25, 2, 3, 5, 10, 50}}; - int n_bendchi2 = static_cast(bendchi2_bins.size()); - float tmp_trk_bendchi2_bin = -1; - for (int i = 0; i < (n_bendchi2 - 1); i++) { - if (tmp_trk_bendchi2 >= bendchi2_bins[i] && tmp_trk_bendchi2 < bendchi2_bins[i + 1]) { - tmp_trk_bendchi2_bin = i; - break; - } - } - if (tmp_trk_bendchi2_bin < 0) - tmp_trk_bendchi2_bin = n_bendchi2; - - // bin chi2rphi variable (bins from https://twiki.cern.ch/twiki/bin/viewauth/CMS/HybridDataFormat#Fitted_Tracks_written_by_KalmanF) - float tmp_trk_chi2rphi = aTrack.chi2XY(); - std::array chi2rphi_bins{{0, 0.25, 0.5, 1, 2, 3, 5, 7, 10, 20, 40, 100, 200, 500, 1000, 3000}}; - int n_chi2rphi = static_cast(chi2rphi_bins.size()); - float tmp_trk_chi2rphi_bin = -1; - for (int i = 0; i < (n_chi2rphi - 1); i++) { - if (tmp_trk_chi2rphi >= chi2rphi_bins[i] && tmp_trk_chi2rphi < chi2rphi_bins[i + 1]) { - tmp_trk_chi2rphi_bin = i; - break; - } - } - if (tmp_trk_chi2rphi_bin < 0) - tmp_trk_chi2rphi_bin = n_chi2rphi; - - // bin chi2rz variable (bins from https://twiki.cern.ch/twiki/bin/viewauth/CMS/HybridDataFormat#Fitted_Tracks_written_by_KalmanF) - float tmp_trk_chi2rz = aTrack.chi2Z(); - std::array chi2rz_bins{{0, 0.25, 0.5, 1, 2, 3, 5, 7, 10, 20, 40, 100, 200, 500, 1000, 3000}}; - int n_chi2rz = static_cast(chi2rz_bins.size()); - float tmp_trk_chi2rz_bin = -1; - for (int i = 0; i < (n_chi2rz - 1); i++) { - if (tmp_trk_chi2rz >= chi2rz_bins[i] && tmp_trk_chi2rz < chi2rz_bins[i + 1]) { - tmp_trk_chi2rz_bin = i; - break; - } - } - if (tmp_trk_chi2rz_bin < 0) - tmp_trk_chi2rz_bin = n_chi2rz; + // Extra variables from HitPatternHelper don't improve performance, so commented out. + //if (useHPH_) { + // hph::HitPatternHelper hph(setupHPH_, tmp_trk_hitpattern, tmp_trk_tanL, tmp_trk_z0); + // hitpattern_expanded_binary = hph.binary(); + // tmp_trk_nlaymiss_PS = hph.numMissingPS(); + // tmp_trk_nlaymiss_2S = hph.numMissing2S(); + //} // get the nstub std::vector>, TTStub>> stubRefs = aTrack.getStubRefs(); + int tmp_trk_nstub = stubRefs.size(); + + // get other variables directly from TTTrack + float tmp_trk_z0 = aTrack.z0(); + float tmp_trk_phi = aTrack.phi(); + float tmp_trk_eta = aTrack.eta(); - // fill the feature map - feature_map["nstub"] = stubRefs.size(); - feature_map["rinv"] = ONNXInvRScaling_ * abs(aTrack.rInv()); - feature_map["tanl"] = abs(aTrack.tanL()); - feature_map["z0"] = aTrack.z0(); - feature_map["phi"] = aTrack.phi(); - feature_map["pt"] = aTrack.momentum().perp(); - feature_map["eta"] = aTrack.eta(); - - float tmp_trk_chi2 = aTrack.chi2(); - feature_map["chi2"] = tmp_trk_chi2; - feature_map["log_chi2"] = log(tmp_trk_chi2); - - feature_map["chi2rphi"] = tmp_trk_chi2rphi; - feature_map["log_chi2rphi"] = log(tmp_trk_chi2rphi); - - feature_map["chi2rz"] = tmp_trk_chi2rz; - feature_map["log_chi2rz"] = log(tmp_trk_chi2rz); - - feature_map["chi2rz"] = tmp_trk_chi2rz; - feature_map["log_chi2rz"] = log(tmp_trk_chi2rz); - - feature_map["bendchi2"] = tmp_trk_bendchi2; - feature_map["log_bendchi2"] = log(tmp_trk_bendchi2); - - feature_map["lay1_hits"] = float(hitpattern_expanded_binary[0]); - feature_map["lay2_hits"] = float(hitpattern_expanded_binary[1]); - feature_map["lay3_hits"] = float(hitpattern_expanded_binary[2]); - feature_map["lay4_hits"] = float(hitpattern_expanded_binary[3]); - feature_map["lay5_hits"] = float(hitpattern_expanded_binary[4]); - feature_map["lay6_hits"] = float(hitpattern_expanded_binary[5]); - feature_map["disk1_hits"] = float(hitpattern_expanded_binary[6]); - feature_map["disk2_hits"] = float(hitpattern_expanded_binary[7]); - feature_map["disk3_hits"] = float(hitpattern_expanded_binary[8]); - feature_map["disk4_hits"] = float(hitpattern_expanded_binary[9]); - feature_map["disk5_hits"] = float(hitpattern_expanded_binary[10]); - - feature_map["dtot"] = float(tmp_trk_dtot); - feature_map["ltot"] = float(tmp_trk_ltot); + // -------- fill the feature map --------- + feature_map["nstub"] = float(tmp_trk_nstub); + feature_map["z0"] = tmp_trk_z0; + feature_map["phi"] = tmp_trk_phi; + feature_map["eta"] = tmp_trk_eta; feature_map["nlaymiss_interior"] = float(tmp_trk_nlaymiss_interior); feature_map["bendchi2_bin"] = tmp_trk_bendchi2_bin; feature_map["chi2rphi_bin"] = tmp_trk_chi2rphi_bin; @@ -242,10 +134,10 @@ void L1TrackQuality::setL1TrackQuality(TTTrack& aTrack) cms::Ort::FloatArrays ortoutputs; std::vector Transformed_features = featureTransform(aTrack, this->featureNames_); - cms::Ort::ONNXRuntime Runtime(this->ONNXmodel_.fullPath()); //Setup ONNX runtime + // cms::Ort::ONNXRuntime runTime(this->ONNXmodel_.fullPath()); //Setup ONNX runtime ortinput_names.push_back(this->ONNXInputName_); - ortoutput_names = Runtime.getOutputNames(); + ortoutput_names = runTime_->getOutputNames(); //ONNX runtime recieves a vector of vectors of floats so push back the input // vector of float to create a 1,1,21 ortinput @@ -254,7 +146,7 @@ void L1TrackQuality::setL1TrackQuality(TTTrack& aTrack) // batch_size 1 as only one set of transformed features is being processed int batch_size = 1; // Run classification - ortoutputs = Runtime.run(ortinput_names, ortinput, {}, ortoutput_names, batch_size); + ortoutputs = runTime_->run(ortinput_names, ortinput, {}, ortoutput_names, batch_size); if (this->qualityAlgorithm_ == QualityAlgorithm::NN) { aTrack.settrkMVA1(ortoutputs[0][0]); @@ -304,3 +196,9 @@ void L1TrackQuality::setONNXModel(std::string const& AlgorithmString, ONNXInputName_ = ONNXInputName; featureNames_ = featureNames; } + +void L1TrackQuality::beginRun(const hph::Setup* setupHPH) { + // Initialize helper for decoding hit patterns. + setupHPH_ = setupHPH; + useHPH_ = true; +} diff --git a/L1Trigger/TrackerDTC/src/SensorModule.cc b/L1Trigger/TrackTrigger/src/SensorModule.cc similarity index 64% rename from L1Trigger/TrackerDTC/src/SensorModule.cc rename to L1Trigger/TrackTrigger/src/SensorModule.cc index 0febf78f0116d..de8011d3e2f60 100644 --- a/L1Trigger/TrackerDTC/src/SensorModule.cc +++ b/L1Trigger/TrackTrigger/src/SensorModule.cc @@ -1,5 +1,5 @@ -#include "L1Trigger/TrackerDTC/interface/SensorModule.h" -#include "L1Trigger/TrackerDTC/interface/Setup.h" +#include "L1Trigger/TrackTrigger/interface/SensorModule.h" +#include "L1Trigger/TrackTrigger/interface/Setup.h" #include "DataFormats/GeometrySurface/interface/Plane.h" #include @@ -10,12 +10,12 @@ using namespace std; using namespace edm; -namespace trackerDTC { +namespace tt { - SensorModule::SensorModule(const Setup& setup, const DetId& detId, int dtcId, int modId) + SensorModule::SensorModule(const Setup* setup, const DetId& detId, int dtcId, int modId) : detId_(detId), dtcId_(dtcId), modId_(modId) { - const TrackerGeometry* trackerGeometry = setup.trackerGeometry(); - const TrackerTopology* trackerTopology = setup.trackerTopology(); + const TrackerGeometry* trackerGeometry = setup->trackerGeometry(); + const TrackerTopology* trackerTopology = setup->trackerTopology(); const GeomDetUnit* geomDetUnit = trackerGeometry->idToDetUnit(detId); const PixelTopology* pixelTopology = dynamic_cast(&(dynamic_cast(geomDetUnit)->specificTopology())); @@ -24,11 +24,11 @@ namespace trackerDTC { const GlobalPoint pos1 = GlobalPoint(trackerGeometry->idToDetUnit(trackerTopology->partnerDetId(detId))->position()); // detector region [0-8] - const int region = dtcId_ / setup.numDTCsPerRegion(); + const int region = dtcId_ / setup->numDTCsPerRegion(); // module radius in cm r_ = pos0.perp(); // module phi w.r.t. detector region_ centre in rad - phi_ = deltaPhi(pos0.phi() - (region + .5) * setup.baseRegion()); + phi_ = deltaPhi(pos0.phi() - (region + .5) * setup->baseRegion()); // module z in cm z_ = pos0.z(); // sensor separation in cm @@ -49,18 +49,18 @@ namespace trackerDTC { barrel_ = detId.subdetId() == StripSubdetector::TOB; // Pixel-Strip or 2Strip module psModule_ = trackerGeometry->getDetectorType(detId) == TrackerGeometry::ModuleType::Ph2PSP; - // module tilt measured w.r.t. beam axis (0=barrel), tk layout measures w.r.t. radial axis + // module tilt angle measured w.r.t. beam axis (0=barrel), tk layout measures w.r.t. radial axis tilt_ = flipped_ ? atan2(pos1.z() - pos0.z(), pos0.perp() - pos1.perp()) : atan2(pos0.z() - pos1.z(), pos1.perp() - pos0.perp()); // sinus of module tilt measured w.r.t. beam axis (0=barrel), tk layout measures w.r.t. radial axis - sin_ = std::sin(tilt_); + sinTilt_ = std::sin(tilt_); // cosinus of module tilt measured w.r.t. beam axis (+-1=endcap), tk layout measures w.r.t. radial axis - cos_ = std::cos(tilt_); + cosTilt_ = std::cos(tilt_); // layer id [barrel: 0-5, endcap: 0-4] const int layer = - (barrel_ ? trackerTopology->layer(detId) : trackerTopology->tidWheel(detId)) - setup.offsetLayerId(); + (barrel_ ? trackerTopology->layer(detId) : trackerTopology->tidWheel(detId)) - setup->offsetLayerId(); // layer id [1-6,11-15] - layerId_ = layer + setup.offsetLayerId() + (barrel_ ? 0 : setup.offsetLayerDisks()); + layerId_ = layer + setup->offsetLayerId() + (barrel_ ? 0 : setup->offsetLayerDisks()); // TTStub row needs flip of sign signRow_ = signbit(deltaPhi(plane.rotation().x().phi() - pos0.phi())); // TTStub col needs flip of sign @@ -79,42 +79,44 @@ namespace trackerDTC { // encoding for 2S endcap radii encodedR_ = -1; if (type_ == Disk2S) { - const int offset = setup.hybridNumRingsPS(layer); + const int offset = setup->hybridNumRingsPS(layer); const int ring = trackerTopology->tidRing(detId); encodedR_ = numColumns_ * (ring - offset); } // r and z offsets if (barrel_) { - offsetR_ = setup.hybridLayerR(layer); + offsetR_ = setup->hybridLayerR(layer); offsetZ_ = 0.; } else { offsetR_ = 0.; - offsetZ_ = side_ ? setup.hybridDiskZ(layer) : -setup.hybridDiskZ(layer); + offsetZ_ = side_ ? setup->hybridDiskZ(layer) : -setup->hybridDiskZ(layer); } + const TypeTilt typeTilt = static_cast(trackerTopology->tobSide(detId)); // getting bend window size double windowSize(-1.); if (barrel_) { - enum TypeBarrel { nonBarrel = 0, tiltedMinus = 1, tiltedPlus = 2, flat = 3 }; - const TypeBarrel type = static_cast(trackerTopology->tobSide(detId)); - if (type == flat) - windowSize = setup.windowSizeBarrelLayer(layerId_); + if (typeTilt == flat) + windowSize = setup->windowSizeBarrelLayer(layerId_); else { int ladder = trackerTopology->tobRod(detId); - if (type == tiltedMinus) + if (typeTilt == tiltedMinus) // Corrected ring number, bet 0 and barrelNTilt.at(layer), in ascending |z| - ladder = 1 + setup.numTiltedLayerRing(layerId_) - ladder; - windowSize = setup.windowSizeTiltedLayerRing(layerId_, ladder); + ladder = 1 + setup->numTiltedLayerRing(layerId_) - ladder; + windowSize = setup->windowSizeTiltedLayerRing(layerId_, ladder); } } else { const int ring = trackerTopology->tidRing(detId); - const int lay = layer + setup.offsetLayerId(); - windowSize = setup.windowSizeEndcapDisksRing(lay, ring); + const int lay = layer + setup->offsetLayerId(); + windowSize = setup->windowSizeEndcapDisksRing(lay, ring); + } + windowSize_ = windowSize / setup->baseWindowSize(); + // calculate tilt correction parameter used to project r to z uncertainty + tiltCorrectionSlope_ = barrel_ ? 0. : 1.; + tiltCorrectionIntercept_ = barrel_ ? 1. : 0.; + if (typeTilt == tiltedMinus || typeTilt == tiltedPlus) { + tiltCorrectionSlope_ = setup->tiltApproxSlope(); + tiltCorrectionIntercept_ = setup->tiltApproxIntercept(); } - windowSize_ = windowSize / setup.baseWindowSize(); - // getting encoded layer id - const vector& encodingLayerId = setup.encodingLayerId(dtcId_); - const auto pos = find(encodingLayerId.begin(), encodingLayerId.end(), layerId_); - encodedLayerId_ = distance(encodingLayerId.begin(), pos); } -} // namespace trackerDTC \ No newline at end of file +} // namespace tt \ No newline at end of file diff --git a/L1Trigger/TrackerDTC/src/Setup.cc b/L1Trigger/TrackTrigger/src/Setup.cc similarity index 60% rename from L1Trigger/TrackerDTC/src/Setup.cc rename to L1Trigger/TrackTrigger/src/Setup.cc index 837bf742803a8..240426331aaca 100644 --- a/L1Trigger/TrackerDTC/src/Setup.cc +++ b/L1Trigger/TrackTrigger/src/Setup.cc @@ -1,20 +1,21 @@ -#include "L1Trigger/TrackerDTC/interface/Setup.h" +#include "L1Trigger/TrackTrigger/interface/Setup.h" #include "FWCore/Utilities/interface/Exception.h" #include "DataFormats/Provenance/interface/ProcessConfiguration.h" -#include "DataFormats/SiPixelDetId/interface/PixelSubdetector.h" #include "DataFormats/L1TrackTrigger/interface/TTBV.h" +#include "DataFormats/L1TrackTrigger/interface/TTTypes.h" #include #include #include #include +#include #include #include using namespace std; using namespace edm; -namespace trackerDTC { +namespace tt { Setup::Setup(const ParameterSet& iConfig, const MagneticField& magneticField, @@ -38,7 +39,7 @@ namespace trackerDTC { // DD4hep fromDD4hep_(iConfig.getParameter("fromDD4hep")), // Parameter to check if configured Tracker Geometry is supported - pSetSG_(iConfig.getParameter("SupportedGeometry")), + pSetSG_(iConfig.getParameter("UnSupportedGeometry")), sgXMLLabel_(pSetSG_.getParameter("XMLLabel")), sgXMLPath_(pSetSG_.getParameter("XMLPath")), sgXMLFile_(pSetSG_.getParameter("XMLFile")), @@ -54,18 +55,20 @@ namespace trackerDTC { matchedLayersPS_(pSetTF_.getParameter("MatchedLayersPS")), unMatchedStubs_(pSetTF_.getParameter("UnMatchedStubs")), unMatchedStubsPS_(pSetTF_.getParameter("UnMatchedStubsPS")), + scattering_(pSetTF_.getParameter("Scattering")), // TMTT specific parameter pSetTMTT_(iConfig.getParameter("TMTT")), minPt_(pSetTMTT_.getParameter("MinPt")), maxEta_(pSetTMTT_.getParameter("MaxEta")), chosenRofPhi_(pSetTMTT_.getParameter("ChosenRofPhi")), numLayers_(pSetTMTT_.getParameter("NumLayers")), - widthR_(pSetTMTT_.getParameter("WidthR")), - widthPhi_(pSetTMTT_.getParameter("WidthPhi")), - widthZ_(pSetTMTT_.getParameter("WidthZ")), + tmttWidthR_(pSetTMTT_.getParameter("WidthR")), + tmttWidthPhi_(pSetTMTT_.getParameter("WidthPhi")), + tmttWidthZ_(pSetTMTT_.getParameter("WidthZ")), // Hybrid specific parameter pSetHybrid_(iConfig.getParameter("Hybrid")), - hybridMinPt_(pSetHybrid_.getParameter("MinPt")), + hybridMinPtStub_(pSetHybrid_.getParameter("MinPtStub")), + hybridMinPtCand_(pSetHybrid_.getParameter("MinPtCand")), hybridMaxEta_(pSetHybrid_.getParameter("MaxEta")), hybridChosenRofPhi_(pSetHybrid_.getParameter("ChosenRofPhi")), hybridNumLayers_(pSetHybrid_.getParameter("NumLayers")), @@ -81,16 +84,25 @@ namespace trackerDTC { hybridLayerRs_(pSetHybrid_.getParameter>("LayerRs")), hybridDiskZs_(pSetHybrid_.getParameter>("DiskZs")), hybridDisk2SRsSet_(pSetHybrid_.getParameter>("Disk2SRsSet")), + tbInnerRadius_(pSetHybrid_.getParameter("InnerRadius")), // Parameter specifying TrackingParticle used for Efficiency measurements pSetTP_(iConfig.getParameter("TrackingParticle")), + tpMinPt_(pSetTP_.getParameter("MinPt")), tpMaxEta_(pSetTP_.getParameter("MaxEta")), tpMaxVertR_(pSetTP_.getParameter("MaxVertR")), tpMaxVertZ_(pSetTP_.getParameter("MaxVertZ")), tpMaxD0_(pSetTP_.getParameter("MaxD0")), tpMinLayers_(pSetTP_.getParameter("MinLayers")), tpMinLayersPS_(pSetTP_.getParameter("MinLayersPS")), + tpMaxBadStubs2S_(pSetTP_.getParameter("MaxBadStubs2S")), + tpMaxBadStubsPS_(pSetTP_.getParameter("MaxBadStubsPS")), // Fimrware specific Parameter pSetFW_(iConfig.getParameter("Firmware")), + widthDSPa_(pSetFW_.getParameter("WidthDSPa")), + widthDSPb_(pSetFW_.getParameter("WidthDSPb")), + widthDSPc_(pSetFW_.getParameter("WidthDSPc")), + widthAddrBRAM36_(pSetFW_.getParameter("WidthAddrBRAM36")), + widthAddrBRAM18_(pSetFW_.getParameter("WidthAddrBRAM18")), numFramesInfra_(pSetFW_.getParameter("NumFramesInfra")), freqLHC_(pSetFW_.getParameter("FreqLHC")), freqBE_(pSetFW_.getParameter("FreqBE")), @@ -102,7 +114,19 @@ namespace trackerDTC { outerRadius_(pSetFW_.getParameter("OuterRadius")), innerRadius_(pSetFW_.getParameter("InnerRadius")), halfLength_(pSetFW_.getParameter("HalfLength")), - maxPitch_(pSetFW_.getParameter("MaxPitch")), + tiltApproxSlope_(pSetFW_.getParameter("TiltApproxSlope")), + tiltApproxIntercept_(pSetFW_.getParameter("TiltApproxIntercept")), + tiltUncertaintyR_(pSetFW_.getParameter("TiltUncertaintyR")), + mindPhi_(pSetFW_.getParameter("MindPhi")), + maxdPhi_(pSetFW_.getParameter("MaxdPhi")), + mindZ_(pSetFW_.getParameter("MindZ")), + maxdZ_(pSetFW_.getParameter("MaxdZ")), + pitch2S_(pSetFW_.getParameter("Pitch2S")), + pitchPS_(pSetFW_.getParameter("PitchPS")), + length2S_(pSetFW_.getParameter("Length2S")), + lengthPS_(pSetFW_.getParameter("LengthPS")), + tiltedLayerLimitsZ_(pSetFW_.getParameter>("TiltedLayerLimitsZ")), + psDiskLimitsR_(pSetFW_.getParameter>("PSDiskLimitsR")), // Parmeter specifying front-end pSetFE_(iConfig.getParameter("FrontEnd")), widthBend_(pSetFE_.getParameter("WidthBend")), @@ -123,11 +147,20 @@ namespace trackerDTC { dtcNumRoutingBlocks_(pSetDTC_.getParameter("NumRoutingBlocks")), dtcDepthMemory_(pSetDTC_.getParameter("DepthMemory")), dtcWidthRowLUT_(pSetDTC_.getParameter("WidthRowLUT")), - dtcWidthQoverPt_(pSetDTC_.getParameter("WidthQoverPt")), + dtcWidthInv2R_(pSetDTC_.getParameter("WidthInv2R")), offsetDetIdDSV_(pSetDTC_.getParameter("OffsetDetIdDSV")), offsetDetIdTP_(pSetDTC_.getParameter("OffsetDetIdTP")), offsetLayerDisks_(pSetDTC_.getParameter("OffsetLayerDisks")), offsetLayerId_(pSetDTC_.getParameter("OffsetLayerId")), + slotLimitPS_(pSetDTC_.getParameter("SlotLimitPS")), + slotLimit10gbps_(pSetDTC_.getParameter("SlotLimit10gbps")), + // Parmeter specifying TFP + pSetTFP_(iConfig.getParameter("TFP")), + tfpWidthPhi0_(pSetTFP_.getParameter("WidthPhi0")), + tfpWidthInv2R_(pSetTFP_.getParameter("WidthInv2R")), + tfpWidthCot_(pSetTFP_.getParameter("WidthCot")), + tfpWidthZ0_(pSetTFP_.getParameter("WidthZ0")), + tfpNumChannel_(pSetTFP_.getParameter("NumChannel")), // Parmeter specifying GeometricProcessor pSetGP_(iConfig.getParameter("GeometricProcessor")), numSectorsPhi_(pSetGP_.getParameter("NumSectorsPhi")), @@ -137,64 +170,47 @@ namespace trackerDTC { boundariesEta_(pSetGP_.getParameter>("BoundariesEta")), // Parmeter specifying HoughTransform pSetHT_(iConfig.getParameter("HoughTransform")), - htNumBinsQoverPt_(pSetHT_.getParameter("NumBinsQoverPt")), + htNumBinsInv2R_(pSetHT_.getParameter("NumBinsInv2R")), htNumBinsPhiT_(pSetHT_.getParameter("NumBinsPhiT")), htMinLayers_(pSetHT_.getParameter("MinLayers")), htDepthMemory_(pSetHT_.getParameter("DepthMemory")), // Parmeter specifying MiniHoughTransform pSetMHT_(iConfig.getParameter("MiniHoughTransform")), - mhtNumBinsQoverPt_(pSetMHT_.getParameter("NumBinsQoverPt")), + mhtNumBinsInv2R_(pSetMHT_.getParameter("NumBinsInv2R")), mhtNumBinsPhiT_(pSetMHT_.getParameter("NumBinsPhiT")), - mhtNumDLB_(pSetMHT_.getParameter("NumDLB")), + mhtNumDLBs_(pSetMHT_.getParameter("NumDLBs")), + mhtNumDLBNodes_(pSetMHT_.getParameter("NumDLBNodes")), + mhtNumDLBChannel_(pSetMHT_.getParameter("NumDLBChannel")), mhtMinLayers_(pSetMHT_.getParameter("MinLayers")), - // Parmeter specifying SeedFilter - pSetSF_(iConfig.getParameter("SeedFilter")), - sfPowerBaseCot_(pSetSF_.getParameter("PowerBaseCot")), - sfBaseDiffZ_(pSetSF_.getParameter("BaseDiffZ")), - sfMinLayers_(pSetSF_.getParameter("MinLayers")), + // Parmeter specifying ZHoughTransform + pSetZHT_(iConfig.getParameter("ZHoughTransform")), + zhtNumBinsZT_(pSetZHT_.getParameter("NumBinsZT")), + zhtNumBinsCot_(pSetZHT_.getParameter("NumBinsCot")), + zhtNumStages_(pSetZHT_.getParameter("NumStages")), + zhtMinLayers_(pSetZHT_.getParameter("MinLayers")), + zhtMaxTracks_(pSetZHT_.getParameter("MaxTracks")), + zhtMaxStubsPerLayer_(pSetZHT_.getParameter("MaxStubsPerLayer")), + // Parameter specifying KalmanFilter Input Formatter + pSetKFin_(iConfig.getParameter("KalmanFilterIn")), + kfinShiftRangePhi_(pSetKFin_.getParameter("ShiftRangePhi")), + kfinShiftRangeZ_(pSetKFin_.getParameter("ShiftRangeZ")), // Parmeter specifying KalmanFilter pSetKF_(iConfig.getParameter("KalmanFilter")), - kfWidthLutInvPhi_(pSetKF_.getParameter("WidthLutInvPhi")), - kfWidthLutInvZ_(pSetKF_.getParameter("WidthLutInvZ")), - kfNumTracks_(pSetKF_.getParameter("NumTracks")), + kfNumWorker_(pSetKF_.getParameter("NumWorker")), kfMinLayers_(pSetKF_.getParameter("MinLayers")), kfMaxLayers_(pSetKF_.getParameter("MaxLayers")), - kfMaxStubsPerLayer_(pSetKF_.getParameter("MaxStubsPerLayer")), - kfMaxSkippedLayers_(pSetKF_.getParameter("MaxSkippedLayers")), - kfBaseShiftr0_(pSetKF_.getParameter("BaseShiftr0")), - kfBaseShiftr02_(pSetKF_.getParameter("BaseShiftr02")), - kfBaseShiftv0_(pSetKF_.getParameter("BaseShiftv0")), - kfBaseShiftS00_(pSetKF_.getParameter("BaseShiftS00")), - kfBaseShiftS01_(pSetKF_.getParameter("BaseShiftS01")), - kfBaseShiftK00_(pSetKF_.getParameter("BaseShiftK00")), - kfBaseShiftK10_(pSetKF_.getParameter("BaseShiftK10")), - kfBaseShiftR00_(pSetKF_.getParameter("BaseShiftR00")), - kfBaseShiftInvR00_(pSetKF_.getParameter("BaseShiftInvR00")), - kfBaseShiftChi20_(pSetKF_.getParameter("BaseShiftChi20")), - kfBaseShiftC00_(pSetKF_.getParameter("BaseShiftC00")), - kfBaseShiftC01_(pSetKF_.getParameter("BaseShiftC01")), - kfBaseShiftC11_(pSetKF_.getParameter("BaseShiftC11")), - kfBaseShiftr1_(pSetKF_.getParameter("BaseShiftr1")), - kfBaseShiftr12_(pSetKF_.getParameter("BaseShiftr12")), - kfBaseShiftv1_(pSetKF_.getParameter("BaseShiftv1")), - kfBaseShiftS12_(pSetKF_.getParameter("BaseShiftS12")), - kfBaseShiftS13_(pSetKF_.getParameter("BaseShiftS13")), - kfBaseShiftK21_(pSetKF_.getParameter("BaseShiftK21")), - kfBaseShiftK31_(pSetKF_.getParameter("BaseShiftK31")), - kfBaseShiftR11_(pSetKF_.getParameter("BaseShiftR11")), - kfBaseShiftInvR11_(pSetKF_.getParameter("BaseShiftInvR11")), - kfBaseShiftChi21_(pSetKF_.getParameter("BaseShiftChi21")), - kfBaseShiftC22_(pSetKF_.getParameter("BaseShiftC22")), - kfBaseShiftC23_(pSetKF_.getParameter("BaseShiftC23")), - kfBaseShiftC33_(pSetKF_.getParameter("BaseShiftC33")), - kfBaseShiftChi2_(pSetKF_.getParameter("BaseShiftChi2")), + kfRangeFactor_(pSetKF_.getParameter("RangeFactor")), + // Parmeter specifying KalmanFilter Output Formatter + pSetKFOut_(iConfig.getParameter("KalmanFilterOut")), + kfoutchi2rphiBins_(pSetKFOut_.getParameter>("chi2rphiBins")), + kfoutchi2rzBins_(pSetKFOut_.getParameter>("chi2rzBins")), + kfoutchi2rphiConv_(pSetKFOut_.getParameter("chi2rphiConv")), + kfoutchi2rzConv_(pSetKFOut_.getParameter("chi2rzConv")), + tttrackBits_(pSetKFOut_.getParameter("TTTrackBits")), + weightBinFraction_(pSetKFOut_.getParameter("WeightBinFraction")), // Parmeter specifying DuplicateRemoval pSetDR_(iConfig.getParameter("DuplicateRemoval")), - drDepthMemory_(pSetDR_.getParameter("DepthMemory")), - drWidthPhi0_(pSetDR_.getParameter("WidthPhi0")), - drWidthQoverPt_(pSetDR_.getParameter("WidthQoverPt")), - drWidthCot_(pSetDR_.getParameter("WidthCot")), - drWidthZ0_(pSetDR_.getParameter("WidthZ0")) { + drDepthMemory_(pSetDR_.getParameter("DepthMemory")) { configurationSupported_ = true; // check if bField is supported checkMagneticField(); @@ -211,11 +227,10 @@ namespace trackerDTC { encodingsBend2S_.reserve(maxWindowSize_ + 1); encodeBend(encodingsBendPS_, true); encodeBend(encodingsBend2S_, false); - // create encodingsLayerId - encodingsLayerId_.reserve(numDTCsPerRegion_); - encodeLayerId(); // create sensor modules produceSensorModules(); + // configure TPSelector + configureTPSelector(); } // checks current configuration vs input sample configuration @@ -302,7 +317,29 @@ namespace trackerDTC { bool Setup::psModule(int dtcId) const { checkDTCId(dtcId); // from tklayout: first 3 are 10 gbps PS, next 3 are 5 gbps PS and residual 6 are 5 gbps 2S modules - return slot(dtcId) < numATCASlots_ / 2; + return slot(dtcId) < slotLimitPS_; + } + + // return sensor moduel type + SensorModule::Type Setup::type(const TTStubRef& ttStubRef) const { + const bool barrel = this->barrel(ttStubRef); + const bool psModule = this->psModule(ttStubRef); + SensorModule::Type type; + if (barrel && psModule) + type = SensorModule::BarrelPS; + if (barrel && !psModule) + type = SensorModule::Barrel2S; + if (!barrel && psModule) + type = SensorModule::DiskPS; + if (!barrel && !psModule) + type = SensorModule::Disk2S; + return type; + } + + // checks if given dtcId is connected via 10 gbps link + bool Setup::gbps10(int dtcId) const { + checkDTCId(dtcId); + return slot(dtcId) < slotLimit10gbps_; } // checks if given dtcId is connected to -z (false) or +z (true) @@ -337,12 +374,6 @@ namespace trackerDTC { return encodingsBend.at(windowSize); } - // index = encoded layerId, inner value = decoded layerId for given dtcId or tfp channel - const vector& Setup::encodingLayerId(int dtcId) const { - const int index = dtcId % numDTCsPerRegion_; - return encodingsLayerId_.at(index); - } - // check if bField is supported void Setup::checkMagneticField() { const double bFieldES = magneticField_->inTesla(GlobalPoint(0., 0., 0.)).z(); @@ -372,7 +403,7 @@ namespace trackerDTC { exception.addContext("tt::Setup::checkGeometry"); throw exception; } - if (find(sgXMLVersions_.begin(), sgXMLVersions_.end(), version) == sgXMLVersions_.end()) { + if (find(sgXMLVersions_.begin(), sgXMLVersions_.end(), version) != sgXMLVersions_.end()) { configurationSupported_ = false; LogWarning("ConfigurationNotSupported") << "Geometry Configuration " << sgXMLPath_ << version << "/" << sgXMLFile_ << " is not supported. "; @@ -409,46 +440,17 @@ namespace trackerDTC { } } - // create encodingsLayerId - void Setup::encodeLayerId() { - vector> dtcELinkIds(numDTCs_); - for (vector& dtcELinkId : dtcELinkIds) - dtcELinkId.reserve(numModulesPerDTC_); - for (const DTCELinkId& dtcLinkId : cablingMap_->getKnownDTCELinkIds()) - dtcELinkIds[dtcId(dtcLinkId.dtc_id())].push_back(dtcLinkId); - for (int dtcBoard = 0; dtcBoard < numDTCsPerRegion_; dtcBoard++) { - set encodingLayerId; - for (int region = 0; region < numRegions_; region++) { - const int dtcId = region * numDTCsPerRegion_ + dtcBoard; - for (const DTCELinkId& dtcLinkId : dtcELinkIds[dtcId]) { - const DetId& detId = cablingMap_->dtcELinkIdToDetId(dtcLinkId)->second; - const bool barrel = detId.subdetId() == StripSubdetector::TOB; - const int layerId = - barrel ? trackerTopology_->layer(detId) : trackerTopology_->tidWheel(detId) + offsetLayerDisks_; - encodingLayerId.insert(layerId); - } - } - // check configuration - if ((int)encodingLayerId.size() > hybridNumLayers_) { - cms::Exception exception("overflow"); - exception << "Cabling map connects more than " << hybridNumLayers_ << " layers to a DTC."; - exception.addContext("tt::Setup::Setup"); - throw exception; - } - encodingsLayerId_.emplace_back(encodingLayerId.begin(), encodingLayerId.end()); - } - } - // create sensor modules void Setup::produceSensorModules() { sensorModules_.reserve(numModules_); dtcModules_ = vector>(numDTCs_); for (vector& dtcModules : dtcModules_) dtcModules.reserve(numModulesPerDTC_); + enum SubDetId { pixelBarrel = 1, pixelDisks = 2 }; // loop over all tracker modules for (const DetId& detId : trackerGeometry_->detIds()) { // skip pixel detector - if (detId.subdetId() == PixelSubdetector::PixelBarrel || detId.subdetId() == PixelSubdetector::PixelEndcap) + if (detId.subdetId() == pixelBarrel || detId.subdetId() == pixelDisks) continue; // skip multiple detIds per module if (!trackerTopology_->isLower(detId)) @@ -462,7 +464,7 @@ namespace trackerDTC { // collection of so far connected modules to this dtc vector& dtcModules = dtcModules_[dtcId]; // construct sendor module - sensorModules_.emplace_back(*this, detId, dtcId, dtcModules.size()); + sensorModules_.emplace_back(this, detId, dtcId, dtcModules.size()); SensorModule* sensorModule = &sensorModules_.back(); // store connection between detId and sensor module detIdToSensorModule_.emplace(detId, sensorModule); @@ -481,6 +483,176 @@ namespace trackerDTC { } } + // configure TPSelector + void Setup::configureTPSelector() { + // configure TrackingParticleSelector + const double ptMin = tpMinPt_; + constexpr double ptMax = 9.e9; + const double etaMax = tpMaxEta_; + const double tip = tpMaxVertR_; + const double lip = tpMaxVertZ_; + constexpr int minHit = 0; + constexpr bool signalOnly = true; + constexpr bool intimeOnly = true; + constexpr bool chargedOnly = true; + constexpr bool stableOnly = false; + tpSelector_ = TrackingParticleSelector( + ptMin, ptMax, -etaMax, etaMax, tip, lip, minHit, signalOnly, intimeOnly, chargedOnly, stableOnly); + tpSelectorLoose_ = + TrackingParticleSelector(ptMin, ptMax, -etaMax, etaMax, tip, lip, minHit, false, false, false, stableOnly); + } + + // stub layer id (barrel: 1 - 6, endcap: 11 - 15) + int Setup::layerId(const TTStubRef& ttStubRef) const { + const DetId& detId = ttStubRef->getDetId(); + return detId.subdetId() == StripSubdetector::TOB ? trackerTopology_->layer(detId) + : trackerTopology_->tidWheel(detId) + offsetLayerDisks_; + } + + // return tracklet layerId (barrel: [0-5], endcap: [6-10]) for given TTStubRef + int Setup::trackletLayerId(const TTStubRef& ttStubRef) const { + static constexpr int offsetBarrel = 1; + static constexpr int offsetDisks = 5; + return this->layerId(ttStubRef) - (this->barrel(ttStubRef) ? offsetBarrel : offsetDisks); + } + + // return index layerId (barrel: [0-5], endcap: [0-6]) for given TTStubRef + int Setup::indexLayerId(const TTStubRef& ttStubRef) const { + static constexpr int offsetBarrel = 1; + static constexpr int offsetDisks = 11; + return this->layerId(ttStubRef) - (this->barrel(ttStubRef) ? offsetBarrel : offsetDisks); + } + + // true if stub from barrel module + bool Setup::barrel(const TTStubRef& ttStubRef) const { + const DetId& detId = ttStubRef->getDetId(); + return detId.subdetId() == StripSubdetector::TOB; + } + + // true if stub from barrel module + bool Setup::psModule(const TTStubRef& ttStubRef) const { + const DetId& detId = ttStubRef->getDetId(); + return trackerGeometry_->getDetectorType(detId) == TrackerGeometry::ModuleType::Ph2PSP; + } + + // + TTBV Setup::layerMap(const vector& ints) const { + TTBV ttBV; + for (int layer = numLayers_ - 1; layer >= 0; layer--) { + const int i = ints[layer]; + ttBV += TTBV(i, kfWidthLayerCount_); + } + return ttBV; + } + + // + TTBV Setup::layerMap(const TTBV& hitPattern, const vector& ints) const { + TTBV ttBV; + for (int layer = numLayers_ - 1; layer >= 0; layer--) { + const int i = ints[layer]; + ttBV += TTBV((hitPattern[layer] ? i - 1 : 0), kfWidthLayerCount_); + } + return ttBV; + } + + // + vector Setup::layerMap(const TTBV& hitPattern, const TTBV& ttBV) const { + TTBV bv(ttBV); + vector ints(numLayers_, 0); + for (int layer = 0; layer < numLayers_; layer++) { + const int i = bv.extract(kfWidthLayerCount_); + ints[layer] = i + (hitPattern[layer] ? 1 : 0); + } + return ints; + } + + // + vector Setup::layerMap(const TTBV& ttBV) const { + TTBV bv(ttBV); + vector ints(numLayers_, 0); + for (int layer = 0; layer < numLayers_; layer++) + ints[layer] = bv.extract(kfWidthLayerCount_); + return ints; + } + + // stub projected phi uncertainty + double Setup::dPhi(const TTStubRef& ttStubRef, double inv2R) const { + const DetId& detId = ttStubRef->getDetId(); + SensorModule* sm = sensorModule(detId + 1); + const double r = stubPos(ttStubRef).perp(); + const double sigma = sm->pitchRow() / r; + const double scat = scattering_ * abs(inv2R); + const double extra = sm->barrel() ? 0. : sm->pitchCol() * abs(inv2R); + const double digi = tmttBasePhi_; + const double dPhi = sigma + scat + extra + digi; + if (dPhi >= maxdPhi_ || dPhi < mindPhi_) { + cms::Exception exception("out_of_range"); + exception.addContext("tt::Setup::dPhi"); + exception << "Stub phi uncertainty " << dPhi << " " + << "is out of range " << mindPhi_ << " to " << maxdPhi_ << "."; + throw exception; + } + return dPhi; + } + + // stub projected z uncertainty + double Setup::dZ(const TTStubRef& ttStubRef, double cot) const { + const DetId& detId = ttStubRef->getDetId(); + SensorModule* sm = sensorModule(detId + 1); + const double sigma = sm->pitchCol() * sm->tiltCorrection(cot); + const double digi = tmttBaseZ_; + const double dZ = sigma + digi; + if (dZ >= maxdZ_ || dZ < mindZ_) { + cms::Exception exception("out_of_range"); + exception.addContext("tt::Setup::dZ"); + exception << "Stub z uncertainty " << dZ << " " + << "is out of range " << mindZ_ << " to " << maxdZ_ << "."; + throw exception; + } + return dZ; + } + + // stub projected chi2phi wheight + double Setup::v0(const TTStubRef& ttStubRef, double inv2R) const { + const DetId& detId = ttStubRef->getDetId(); + SensorModule* sm = sensorModule(detId + 1); + const double r = stubPos(ttStubRef).perp(); + const double sigma = pow(sm->pitchRow() / r, 2) / 12.; + const double scat = pow(scattering_ * inv2R, 2); + const double extra = sm->barrel() ? 0. : pow(sm->pitchCol() * inv2R, 2); + const double digi = pow(tmttBasePhi_ / 12., 2); + return sigma + scat + extra + digi; + } + + // stub projected chi2z wheight + double Setup::v1(const TTStubRef& ttStubRef, double cot) const { + const DetId& detId = ttStubRef->getDetId(); + SensorModule* sm = sensorModule(detId + 1); + const double sigma = pow(sm->pitchCol() * sm->tiltCorrection(cot), 2) / 12.; + const double digi = pow(tmttBaseZ_ / 12., 2); + return sigma + digi; + } + + // checks if stub collection is considered forming a reconstructable track + bool Setup::reconstructable(const vector& ttStubRefs) const { + set hitPattern; + for (const TTStubRef& ttStubRef : ttStubRefs) + hitPattern.insert(layerId(ttStubRef)); + return (int)hitPattern.size() >= tpMinLayers_; + } + + // checks if tracking particle is selected for efficiency measurements + bool Setup::useForAlgEff(const TrackingParticle& tp) const { + const bool selected = tpSelector_(tp); + const double cot = sinh(tp.eta()); + const double s = sin(tp.phi()); + const double c = cos(tp.phi()); + const TrackingParticle::Point& v = tp.vertex(); + const double z0 = v.z() - (v.x() * c + v.y() * s) * cot; + const double d0 = v.x() * s - v.y() * c; + return selected && (abs(d0) < tpMaxD0_) && (abs(z0) < tpMaxVertZ_); + } + // derive constants void Setup::calculateConstants() { // emp @@ -488,6 +660,16 @@ namespace trackerDTC { numFrames_ = numFramesPerBX * tmpTFP_ - 1; numFramesIO_ = numFramesPerBX * tmpTFP_ - numFramesInfra_; numFramesFE_ = numFramesPerBX * tmpFE_ - numFramesInfra_; + // dsp + widthDSPab_ = widthDSPa_ - 1; + widthDSPau_ = widthDSPab_ - 1; + widthDSPbb_ = widthDSPb_ - 1; + widthDSPbu_ = widthDSPbb_ - 1; + widthDSPcb_ = widthDSPc_ - 1; + widthDSPcu_ = widthDSPcb_ - 1; + // firmware + maxPitch_ = max(pitchPS_, pitch2S_); + maxLength_ = max(lengthPS_, length2S_); // common track finding invPtToDphi_ = speedOfLight_ * bField_ / 2000.; baseRegion_ = 2. * M_PI / numRegions_; @@ -496,35 +678,35 @@ namespace trackerDTC { maxCot_ = sinh(maxEta_); maxZT_ = maxCot_ * chosenRofZ_; numSectorsEta_ = boundariesEta_.size() - 1; - widthSectorEta_ = ceil(log2(numSectorsEta_)); - widthChiZ_ = ceil(log2(neededRangeChiZ_ / baseZ_)); - // ht - htWidthQoverPt_ = ceil(log2(htNumBinsQoverPt_)); - htWidthPhiT_ = ceil(log2(htNumBinsPhiT_)); - const double rangeQoverPt = 2. * invPtToDphi_ / minPt_; - htBaseQoverPt_ = rangeQoverPt / htNumBinsQoverPt_; - htBasePhiT_ = baseSector_ / htNumBinsPhiT_; + numSectors_ = numSectorsPhi_ * numSectorsEta_; + sectorCots_.reserve(numSectorsEta_); + for (int eta = 0; eta < numSectorsEta_; eta++) + sectorCots_.emplace_back((sinh(boundariesEta_.at(eta)) + sinh(boundariesEta_.at(eta + 1))) / 2.); // tmtt - widthLayer_ = ceil(log2(numLayers_)); - const double baseRgen = htBasePhiT_ / htBaseQoverPt_; + const double rangeInv2R = 2. * invPtToDphi_ / minPt_; + tmttBaseInv2R_ = rangeInv2R / htNumBinsInv2R_; + tmttBasePhiT_ = baseSector_ / htNumBinsPhiT_; + const double baseRgen = tmttBasePhiT_ / tmttBaseInv2R_; const double rangeR = 2. * max(abs(outerRadius_ - chosenRofPhi_), abs(innerRadius_ - chosenRofPhi_)); - const int baseShiftR = ceil(log2(rangeR / baseRgen / pow(2., widthR_))); - baseR_ = baseRgen * pow(2., baseShiftR); + const int baseShiftR = ceil(log2(rangeR / baseRgen / pow(2., tmttWidthR_))); + tmttBaseR_ = baseRgen * pow(2., baseShiftR); const double rangeZ = 2. * halfLength_; - const int baseShiftZ = ceil(log2(rangeZ / baseR_ / pow(2., widthZ_))); - baseZ_ = baseR_ * pow(2., baseShiftZ); - const double rangePhiDTC = baseRegion_ + rangeQoverPt * baseR_ * pow(2., widthR_) / 4.; - widthPhiDTC_ = widthPhi_ + ceil(log2(rangePhiDTC / baseRegion_)); - const int baseShiftPhi = ceil(log2(rangePhiDTC / htBasePhiT_ / pow(2., widthPhiDTC_))); - basePhi_ = htBasePhiT_ * pow(2., baseShiftPhi); - const double neededRangeChiPhi = 2. * htBasePhiT_; - widthChiPhi_ = ceil(log2(neededRangeChiPhi / basePhi_)); + const int baseShiftZ = ceil(log2(rangeZ / tmttBaseR_ / pow(2., tmttWidthZ_))); + tmttBaseZ_ = tmttBaseR_ * pow(2., baseShiftZ); + const double rangePhi = baseRegion_ + rangeInv2R * rangeR / 2.; + const int baseShiftPhi = ceil(log2(rangePhi / tmttBasePhiT_ / pow(2., tmttWidthPhi_))); + tmttBasePhi_ = tmttBasePhiT_ * pow(2., baseShiftPhi); + tmttWidthLayer_ = ceil(log2(numLayers_)); + tmttWidthSectorEta_ = ceil(log2(numSectorsEta_)); + tmttWidthInv2R_ = ceil(log2(htNumBinsInv2R_)); + tmttNumUnusedBits_ = TTBV::S_ - tmttWidthLayer_ - 2 * tmttWidthSectorEta_ - tmttWidthR_ - tmttWidthPhi_ - + tmttWidthZ_ - 2 * tmttWidthInv2R_ - numSectorsPhi_ - 1; // hybrid - const double hybridRangeQoverPt = 2. * invPtToDphi_ / hybridMinPt_; + const double hybridRangeInv2R = 2. * invPtToDphi_ / hybridMinPtStub_; const double hybridRangeR = 2. * max(abs(outerRadius_ - hybridChosenRofPhi_), abs(innerRadius_ - hybridChosenRofPhi_)); - const double hybridRangePhi = baseRegion_ + hybridRangeR * hybridRangeQoverPt / 2.; - hybridWidthLayer_ = ceil(log2(hybridNumLayers_)); + hybridRangePhi_ = baseRegion_ + (hybridRangeR * hybridRangeInv2R) / 2.; + hybridWidthLayerId_ = ceil(log2(hybridNumLayers_)); hybridBasesZ_.reserve(SensorModule::NumTypes); for (int type = 0; type < SensorModule::NumTypes; type++) hybridBasesZ_.emplace_back(hybridRangesZ_.at(type) / pow(2., hybridWidthsZ_.at(type))); @@ -534,15 +716,15 @@ namespace trackerDTC { hybridBasesR_[SensorModule::Disk2S] = 1.; hybridBasesPhi_.reserve(SensorModule::NumTypes); for (int type = 0; type < SensorModule::NumTypes; type++) - hybridBasesPhi_.emplace_back(hybridRangePhi / pow(2., hybridWidthsPhi_.at(type))); + hybridBasesPhi_.emplace_back(hybridRangePhi_ / pow(2., hybridWidthsPhi_.at(type))); hybridBasesAlpha_.reserve(SensorModule::NumTypes); for (int type = 0; type < SensorModule::NumTypes; type++) hybridBasesAlpha_.emplace_back(hybridRangesAlpha_.at(type) / pow(2., hybridWidthsAlpha_.at(type))); hybridNumsUnusedBits_.reserve(SensorModule::NumTypes); for (int type = 0; type < SensorModule::NumTypes; type++) - hybridNumsUnusedBits_.emplace_back(TTBV::S - hybridWidthsR_.at(type) - hybridWidthsZ_.at(type) - + hybridNumsUnusedBits_.emplace_back(TTBV::S_ - hybridWidthsR_.at(type) - hybridWidthsZ_.at(type) - hybridWidthsPhi_.at(type) - hybridWidthsAlpha_.at(type) - - hybridWidthsBend_.at(type) - hybridWidthLayer_ - 1); + hybridWidthsBend_.at(type) - hybridWidthLayerId_ - 1); hybridMaxCot_ = sinh(hybridMaxEta_); disk2SRs_.reserve(hybridDisk2SRsSet_.size()); for (const auto& pSet : hybridDisk2SRsSet_) @@ -553,92 +735,50 @@ namespace trackerDTC { numModules_ = numDTCs_ * numModulesPerDTC_; dtcNumModulesPerRoutingBlock_ = numModulesPerDTC_ / dtcNumRoutingBlocks_; dtcNumMergedRows_ = pow(2, widthRow_ - dtcWidthRowLUT_); - const double maxRangeQoverPt = max(rangeQoverPt, hybridRangeQoverPt); - const int baseShiftQoverPt = htWidthQoverPt_ - dtcWidthQoverPt_ + ceil(log2(maxRangeQoverPt / rangeQoverPt)); - dtcBaseQoverPt_ = htBaseQoverPt_ * pow(2., baseShiftQoverPt); + const double maxRangeInv2R = max(rangeInv2R, hybridRangeInv2R); + const int baseShiftInv2R = ceil(log2(htNumBinsInv2R_)) - dtcWidthInv2R_ + ceil(log2(maxRangeInv2R / rangeInv2R)); + dtcBaseInv2R_ = tmttBaseInv2R_ * pow(2., baseShiftInv2R); const int baseDiffM = dtcWidthRowLUT_ - widthRow_; - dtcBaseM_ = basePhi_ * pow(2., baseDiffM); + dtcBaseM_ = tmttBasePhi_ * pow(2., baseDiffM); const double x1 = pow(2, widthRow_) * baseRow_ * maxPitch_ / 2.; const double x0 = x1 - pow(2, dtcWidthRowLUT_) * baseRow_ * maxPitch_; const double maxM = atan2(x1, innerRadius_) - atan2(x0, innerRadius_); dtcWidthM_ = ceil(log2(maxM / dtcBaseM_)); - dtcNumUnusedBits_ = TTBV::S - 1 - widthR_ - widthPhiDTC_ - widthZ_ - 2 * htWidthQoverPt_ - 2 * widthSectorEta_ - - numSectorsPhi_ - widthLayer_; + dtcNumStreams_ = numDTCs_ * numOverlappingRegions_; // mht - mhtNumCells_ = mhtNumBinsQoverPt_ * mhtNumBinsPhiT_; - mhtWidthQoverPt_ = ceil(log2(htNumBinsQoverPt_ * mhtNumBinsQoverPt_)); - mhtWidthPhiT_ = ceil(log2(htNumBinsPhiT_ * mhtNumBinsPhiT_)); - mhtBaseQoverPt_ = htBaseQoverPt_ / mhtNumBinsQoverPt_; - mhtBasePhiT_ = htBasePhiT_ / mhtNumBinsPhiT_; - // SF - sfBaseCot_ = pow(2, sfPowerBaseCot_); - sfBaseZT_ = baseZ_ * pow(2, sfBaseDiffZ_); - // DR - drBaseQoverPt_ = htBaseQoverPt_ * pow(2, htWidthQoverPt_ - drWidthQoverPt_); - drBasePhi0_ = basePhi_ * pow(2, widthPhiDTC_ - drWidthPhi0_); - drBaseCot_ = floor(log2(2. * maxCot_ * pow(2, -drWidthCot_))); - drBaseZ0_ = baseZ_ * pow(2, ceil(log2(2. * beamWindowZ_ / baseZ_)) - drWidthZ0_); - // KF - kfBasex0_ = drBaseQoverPt_; - kfBasex1_ = drBasePhi0_; - kfBasex2_ = drBaseCot_; - kfBasex3_ = drBaseZ0_; - kfBasem0_ = basePhi_; - kfBasem1_ = baseZ_; - kfBaseH00_ = baseR_; - kfBaseH12_ = baseR_; - kfBaseChi2_ = pow(2, kfBaseShiftChi2_); - kfBaser0_ = pow(2, kfBaseShiftr0_) * kfBasex1_; - kfBaser02_ = pow(2, kfBaseShiftr02_) * kfBasex1_ * kfBasex1_; - kfBasev0_ = pow(2, kfBaseShiftv0_) * kfBasex1_ * kfBasex1_; - kfBaseS00_ = pow(2, kfBaseShiftS00_) * kfBasex0_ * kfBasex1_; - kfBaseS01_ = pow(2, kfBaseShiftS01_) * kfBasex1_ * kfBasex1_; - kfBaseK00_ = pow(2, kfBaseShiftK00_) * kfBasex0_ / kfBasex1_; - kfBaseK10_ = pow(2, kfBaseShiftK10_); - kfBaseR00_ = pow(2, kfBaseShiftR00_) * kfBasex1_ * kfBasex1_; - kfBaseInvR00_ = pow(2, kfBaseShiftInvR00_) / kfBasex1_ / kfBasex1_; - kfBaseChi20_ = pow(2, kfBaseShiftChi20_); - kfBaseC00_ = pow(2, kfBaseShiftC00_) * kfBasex0_ * kfBasex0_; - kfBaseC01_ = pow(2, kfBaseShiftC01_) * kfBasex0_ * kfBasex1_; - kfBaseC11_ = pow(2, kfBaseShiftC11_) * kfBasex1_ * kfBasex1_; - kfBaser1_ = pow(2, kfBaseShiftr1_) * kfBasex3_; - kfBaser12_ = pow(2, kfBaseShiftr12_) * kfBasex3_ * kfBasex3_; - kfBasev1_ = pow(2, kfBaseShiftv1_) * kfBasex3_ * kfBasex3_; - kfBaseS12_ = pow(2, kfBaseShiftS12_) * kfBasex2_ * kfBasex3_; - kfBaseS13_ = pow(2, kfBaseShiftS13_) * kfBasex3_ * kfBasex3_; - kfBaseK21_ = pow(2, kfBaseShiftK21_) * kfBasex2_ / kfBasex3_; - kfBaseK31_ = pow(2, kfBaseShiftK31_); - kfBaseR11_ = pow(2, kfBaseShiftR11_) * kfBasex3_ * kfBasex3_; - kfBaseInvR11_ = pow(2, kfBaseShiftInvR11_) / kfBasex3_ / kfBasex3_; - kfBaseChi21_ = pow(2, kfBaseShiftChi21_); - kfBaseC22_ = pow(2, kfBaseShiftC22_) * kfBasex2_ * kfBasex2_; - kfBaseC23_ = pow(2, kfBaseShiftC23_) * kfBasex2_ * kfBasex3_; - kfBaseC33_ = pow(2, kfBaseShiftC33_) * kfBasex3_ * kfBasex3_; - } - - // returns bit accurate position of a stub from a given tfp identifier region [0-8] channel [0-47] - GlobalPoint Setup::stubPos(bool hybrid, const TTDTC::Frame& frame, int tfpRegion, int tfpChannel) const { + mhtNumCells_ = mhtNumBinsInv2R_ * mhtNumBinsPhiT_; + // zht + zhtNumCells_ = zhtNumBinsCot_ * zhtNumBinsZT_; + // + kfWidthLayerCount_ = ceil(log2(zhtMaxStubsPerLayer_)); + } + + // returns bit accurate hybrid stub radius for given TTStubRef and h/w bit word + double Setup::stubR(const TTBV& hw, const TTStubRef& ttStubRef) const { + const bool barrel = this->barrel(ttStubRef); + const int layerId = this->indexLayerId(ttStubRef); + const SensorModule::Type type = this->type(ttStubRef); + const int widthR = hybridWidthsR_.at(type); + const double baseR = hybridBasesR_.at(type); + const TTBV hwR(hw, widthR, 0, barrel); + double r = hwR.val(baseR) + (barrel ? hybridLayerRs_.at(layerId) : 0.); + if (type == SensorModule::Disk2S) + r = disk2SRs_.at(layerId).at((int)r); + return r; + } + + // returns bit accurate position of a stub from a given tfp region [0-8] + GlobalPoint Setup::stubPos(bool hybrid, const FrameStub& frame, int region) const { GlobalPoint p; if (frame.first.isNull()) return p; TTBV bv(frame.second); if (hybrid) { - const DetId& detId = frame.first->getDetId(); - const int dtcId = Setup::dtcId(tfpRegion, tfpChannel); - const bool barrel = detId.subdetId() == StripSubdetector::TOB; - const bool psModule = Setup::psModule(dtcId); - const int layerId = - (barrel ? trackerTopology_->layer(detId) : trackerTopology_->tidWheel(detId)) - offsetLayerId_; - const bool side = Setup::side(dtcId); - SensorModule::Type type; - if (barrel && psModule) - type = SensorModule::BarrelPS; - if (barrel && !psModule) - type = SensorModule::Barrel2S; - if (!barrel && psModule) - type = SensorModule::DiskPS; - if (!barrel && !psModule) - type = SensorModule::Disk2S; + const bool barrel = this->barrel(frame.first); + const int layerId = this->indexLayerId(frame.first); + const GlobalPoint gp = this->stubPos(frame.first); + const bool side = gp.z() > 0.; + const SensorModule::Type type = this->type(frame.first); const int widthBend = hybridWidthsBend_.at(type); const int widthAlpha = hybridWidthsAlpha_.at(type); const int widthPhi = hybridWidthsPhi_.at(type); @@ -648,33 +788,32 @@ namespace trackerDTC { const double baseZ = hybridBasesZ_.at(type); const double baseR = hybridBasesR_.at(type); // parse bit vector - bv >>= 1 + hybridWidthLayer_ + widthBend + widthAlpha; - double phi = (bv.val(widthPhi, 0, true) + .5) * basePhi; + bv >>= 1 + hybridWidthLayerId_ + widthBend + widthAlpha; + double phi = bv.val(basePhi, widthPhi) - hybridRangePhi_ / 2.; bv >>= widthPhi; - double z = (bv.val(widthZ, 0, true) + .5) * baseZ; + double z = bv.val(baseZ, widthZ, 0, true); bv >>= widthZ; - double r = (bv.val(widthR, 0, barrel) + .5) * baseR; - if (barrel) { + double r = bv.val(baseR, widthR, 0, barrel); + if (barrel) r += hybridLayerRs_.at(layerId); - } else { + else z += hybridDiskZs_.at(layerId) * (side ? 1. : -1.); - } - phi = deltaPhi(phi + tfpRegion * baseRegion_); + phi = deltaPhi(phi + region * baseRegion_); if (type == SensorModule::Disk2S) { r = bv.val(widthR); r = disk2SRs_.at(layerId).at((int)r); } p = GlobalPoint(GlobalPoint::Cylindrical(r, phi, z)); } else { - bv >>= 2 * htWidthQoverPt_ + 2 * widthSectorEta_ + numSectorsPhi_ + widthLayer_; - double z = (bv.val(widthZ_, 0, true) + .5) * baseZ_; - bv >>= widthZ_; - double phi = (bv.val(widthPhiDTC_, 0, true) + .5) * basePhi_; - bv >>= widthPhiDTC_; - double r = (bv.val(widthR_, 0, true) + .5) * baseR_; - bv >>= widthR_; + bv >>= 2 * tmttWidthInv2R_ + 2 * tmttWidthSectorEta_ + numSectorsPhi_ + tmttWidthLayer_; + double z = (bv.val(tmttWidthZ_, 0, true) + .5) * tmttBaseZ_; + bv >>= tmttWidthZ_; + double phi = (bv.val(tmttWidthPhi_, 0, true) + .5) * tmttBasePhi_; + bv >>= tmttWidthPhi_; + double r = (bv.val(tmttWidthR_, 0, true) + .5) * tmttBaseR_; + bv >>= tmttWidthR_; r = r + chosenRofPhi_; - phi = deltaPhi(phi + tfpRegion * baseRegion_); + phi = deltaPhi(phi + region * baseRegion_); p = GlobalPoint(GlobalPoint::Cylindrical(r, phi, z)); } return p; @@ -695,7 +834,7 @@ namespace trackerDTC { void Setup::checkDTCId(int dtcId) const { if (dtcId < 0 || dtcId >= numDTCsPerRegion_ * numRegions_) { cms::Exception exception("out_of_range"); - exception.addContext("trackerDTC::Setup::checkDTCId"); + exception.addContext("tt::Setup::checkDTCId"); exception << "Used DTC Id (" << dtcId << ") " << "is out of range 0 to " << numDTCsPerRegion_ * numRegions_ - 1 << "."; throw exception; @@ -706,7 +845,7 @@ namespace trackerDTC { void Setup::checkTKLayoutId(int tkLayoutId) const { if (tkLayoutId <= 0 || tkLayoutId > numDTCsPerRegion_ * numRegions_) { cms::Exception exception("out_of_range"); - exception.addContext("trackerDTC::Setup::checkTKLayoutId"); + exception.addContext("tt::Setup::checkTKLayoutId"); exception << "Used TKLayout Id (" << tkLayoutId << ") " << "is out of range 1 to " << numDTCsPerRegion_ * numRegions_ << "."; throw exception; @@ -719,7 +858,7 @@ namespace trackerDTC { const bool oorChannel = tfpChannel >= numDTCsPerTFP_ || tfpChannel < 0; if (oorRegion || oorChannel) { cms::Exception exception("out_of_range"); - exception.addContext("trackerDTC::Setup::checkTFPIdentifier"); + exception.addContext("tt::Setup::checkTFPIdentifier"); if (oorRegion) exception << "Requested Processing Region " << "(" << tfpRegion << ") " @@ -731,5 +870,4 @@ namespace trackerDTC { throw exception; } } - -} // namespace trackerDTC +} // namespace tt diff --git a/L1Trigger/TrackTrigger/src/SetupRcd.cc b/L1Trigger/TrackTrigger/src/SetupRcd.cc new file mode 100644 index 0000000000000..b5ef0c4d81bd0 --- /dev/null +++ b/L1Trigger/TrackTrigger/src/SetupRcd.cc @@ -0,0 +1,4 @@ +#include "L1Trigger/TrackTrigger/interface/SetupRcd.h" +#include "FWCore/Framework/interface/eventsetuprecord_registration_macro.h" + +EVENTSETUP_RECORD_REG(tt::SetupRcd); \ No newline at end of file diff --git a/L1Trigger/TrackTrigger/test/AnalyzerClusterStub.cc b/L1Trigger/TrackTrigger/test/AnalyzerClusterStub.cc index 326af5c802ceb..507976a6d6c4a 100644 --- a/L1Trigger/TrackTrigger/test/AnalyzerClusterStub.cc +++ b/L1Trigger/TrackTrigger/test/AnalyzerClusterStub.cc @@ -8,7 +8,7 @@ */ #include "FWCore/Framework/interface/MakerMacros.h" -#include "FWCore/Framework/interface/EDAnalyzer.h" +#include "FWCore/Framework/interface/one/EDAnalyzer.h" #include "FWCore/Framework/interface/Event.h" #include "FWCore/Framework/interface/ESHandle.h" #include "FWCore/PluginManager/interface/ModuleDef.h" @@ -29,16 +29,18 @@ #include #include -class AnalyzerClusterStub : public edm::EDAnalyzer { +class AnalyzerClusterStub : public edm::one::EDAnalyzer { /// Public methods public: /// Constructor/destructor explicit AnalyzerClusterStub(const edm::ParameterSet& iConfig); - virtual ~AnalyzerClusterStub(); + ~AnalyzerClusterStub() override; // Typical methods used on Loops over events - virtual void beginJob(); - virtual void endJob(); - virtual void analyze(const edm::Event& iEvent, const edm::EventSetup& iSetup); + void beginJob() override; + void endJob() override; + void beginRun(const edm::Run& iEvent, const edm::EventSetup& iSetup) override {} + void endRun(const edm::Run& iEvent, const edm::EventSetup& iSetup) override {} + void analyze(const edm::Event& iEvent, const edm::EventSetup& iSetup) override; /// Private methods and variables private: @@ -180,6 +182,7 @@ class AnalyzerClusterStub : public edm::EDAnalyzer { // CONSTRUCTOR AnalyzerClusterStub::AnalyzerClusterStub(edm::ParameterSet const& iConfig) : config(iConfig) { /// Insert here what you need to initialize + usesResource("TFileService"); DebugMode = iConfig.getParameter("DebugMode"); } diff --git a/L1Trigger/TrackTrigger/test/AnalyzerPrintGeomInfo.cc b/L1Trigger/TrackTrigger/test/AnalyzerPrintGeomInfo.cc index 893a0d74077f4..6ed038b161b85 100644 --- a/L1Trigger/TrackTrigger/test/AnalyzerPrintGeomInfo.cc +++ b/L1Trigger/TrackTrigger/test/AnalyzerPrintGeomInfo.cc @@ -6,7 +6,7 @@ ////////////////////////////// #include "FWCore/Framework/interface/MakerMacros.h" -#include "FWCore/Framework/interface/EDAnalyzer.h" +#include "FWCore/Framework/interface/one/EDAnalyzer.h" #include "FWCore/Framework/interface/Event.h" #include "FWCore/Framework/interface/ESHandle.h" #include "FWCore/PluginManager/interface/ModuleDef.h" @@ -28,16 +28,18 @@ // // ////////////////////////////// -class AnalyzerPrintGeomInfo : public edm::EDAnalyzer { +class AnalyzerPrintGeomInfo : public edm::one::EDAnalyzer { /// Public methods public: /// Constructor/destructor explicit AnalyzerPrintGeomInfo(const edm::ParameterSet& iConfig); - virtual ~AnalyzerPrintGeomInfo(); + ~AnalyzerPrintGeomInfo() override; // Typical methods used on Loops over events - virtual void beginJob(); - virtual void endJob(); - virtual void analyze(const edm::Event& iEvent, const edm::EventSetup& iSetup); + void beginJob() override; + void endJob() override; + void beginRun(const edm::Run& iEvent, const edm::EventSetup& iSetup) override {} + void endRun(const edm::Run& iEvent, const edm::EventSetup& iSetup) override {} + void analyze(const edm::Event& iEvent, const edm::EventSetup& iSetup) override; /// Private methods and variables private: @@ -93,6 +95,7 @@ class AnalyzerPrintGeomInfo : public edm::EDAnalyzer { // CONSTRUCTOR AnalyzerPrintGeomInfo::AnalyzerPrintGeomInfo(edm::ParameterSet const& iConfig) : config(iConfig) { /// Insert here what you need to initialize + usesResource("TFileService"); TextOutput = iConfig.getParameter("TextOutput"); DebugMode = iConfig.getParameter("DebugMode"); diff --git a/L1Trigger/TrackTrigger/test/AnalyzerSimHitMaps.cc b/L1Trigger/TrackTrigger/test/AnalyzerSimHitMaps.cc index 0b8ba242c1bdc..c8daebac9d68d 100644 --- a/L1Trigger/TrackTrigger/test/AnalyzerSimHitMaps.cc +++ b/L1Trigger/TrackTrigger/test/AnalyzerSimHitMaps.cc @@ -6,7 +6,7 @@ //////////////////////////// #include "FWCore/Framework/interface/MakerMacros.h" -#include "FWCore/Framework/interface/EDAnalyzer.h" +#include "FWCore/Framework/interface/one/EDAnalyzer.h" #include "FWCore/Framework/interface/Event.h" #include "FWCore/Framework/interface/ESHandle.h" #include "FWCore/PluginManager/interface/ModuleDef.h" @@ -26,19 +26,23 @@ // // ////////////////////////////// -class AnalyzerSimHitMaps : public edm::EDAnalyzer { +class AnalyzerSimHitMaps : public edm::one::EDAnalyzer { /// Public methods public: /// Constructor/destructor explicit AnalyzerSimHitMaps(const edm::ParameterSet& iConfig); - virtual ~AnalyzerSimHitMaps(); + ~AnalyzerSimHitMaps() override; // Typical methods used on Loops over events - virtual void beginJob(); - virtual void endJob(); - virtual void analyze(const edm::Event& iEvent, const edm::EventSetup& iSetup); + void beginJob() override; + void endJob() override; + void beginRun(const edm::Run& iEvent, const edm::EventSetup& iSetup) override {} + void endRun(const edm::Run& iEvent, const edm::EventSetup& iSetup) override {} + void analyze(const edm::Event& iEvent, const edm::EventSetup& iSetup) override; /// Private methods and variables private: + edm::ESGetToken getTokenTrackerGeometry_; + /// Global Position of SimHits TH2D* hSimHit_Barrel_XY; TH2D* hSimHit_Barrel_XY_Zoom; @@ -60,8 +64,10 @@ class AnalyzerSimHitMaps : public edm::EDAnalyzer { ////////////// // CONSTRUCTOR -AnalyzerSimHitMaps::AnalyzerSimHitMaps(edm::ParameterSet const& iConfig) { +AnalyzerSimHitMaps::AnalyzerSimHitMaps(edm::ParameterSet const& iConfig) + : getTokenTrackerGeometry_(esConsumes()) { /// Insert here what you need to initialize + usesResource("TFileService"); } ///////////// @@ -161,13 +167,8 @@ void AnalyzerSimHitMaps::beginJob() { // ANALYZE void AnalyzerSimHitMaps::analyze(const edm::Event& iEvent, const edm::EventSetup& iSetup) { /// Geometry handles etc - edm::ESHandle geometryHandle; - const TrackerGeometry* theGeometry; - - /// Geometry setup - /// Set pointers to Geometry - iSetup.get().get(geometryHandle); - theGeometry = &(*geometryHandle); + edm::ESHandle geometryHandle = iSetup.getHandle(getTokenTrackerGeometry_); + const TrackerGeometry* theGeometry = &(*geometryHandle); ////////////////// // GET SIM HITS // diff --git a/L1Trigger/TrackerDTC/BuildFile.xml b/L1Trigger/TrackerDTC/BuildFile.xml index 3cf8c85e80fcc..2812c28514fd3 100644 --- a/L1Trigger/TrackerDTC/BuildFile.xml +++ b/L1Trigger/TrackerDTC/BuildFile.xml @@ -1,3 +1,4 @@ + diff --git a/L1Trigger/TrackerDTC/interface/DTC.h b/L1Trigger/TrackerDTC/interface/DTC.h index 145e2f906d0fc..0d1a6896a26d2 100644 --- a/L1Trigger/TrackerDTC/interface/DTC.h +++ b/L1Trigger/TrackerDTC/interface/DTC.h @@ -1,7 +1,9 @@ #ifndef L1Trigger_TrackerDTC_DTC_h #define L1Trigger_TrackerDTC_DTC_h -#include "L1Trigger/TrackerDTC/interface/Setup.h" +#include "DataFormats/L1TrackTrigger/interface/TTDTC.h" +#include "L1Trigger/TrackTrigger/interface/Setup.h" +#include "L1Trigger/TrackerDTC/interface/LayerEncoding.h" #include "L1Trigger/TrackerDTC/interface/Stub.h" #include @@ -9,7 +11,11 @@ namespace trackerDTC { - // representation of an outer tracker DTC board + /*! \class trackerDTC::DTC + * \brief Class to represent an outer tracker DTC board + * \author Thomas Schuh + * \date 2020, Jan + */ class DTC { private: typedef std::deque Stubs; @@ -18,7 +24,8 @@ namespace trackerDTC { public: DTC(const edm::ParameterSet& iConfig, - const Setup& setup, + const tt::Setup* setup, + const LayerEncoding* layerEncoding, int dtcId, const std::vector>& stubsDTC); ~DTC() {} @@ -36,7 +43,7 @@ namespace trackerDTC { Stub* pop_front(Stubs& stubs); // helper class to store configurations - const Setup* setup_; + const tt::Setup* setup_; // enables emulation of truncation bool enableTruncation_; // outer tracker detector region [0-8] @@ -44,7 +51,7 @@ namespace trackerDTC { // outer tracker dtc id in region [0-23] int board_; // container of modules connected to this DTC - std::vector modules_; + std::vector modules_; // container of stubs on this DTC std::vector stubs_; // input stubs organised in routing blocks [0..1] and channel [0..35] diff --git a/L1Trigger/TrackerDTC/interface/LayerEncoding.h b/L1Trigger/TrackerDTC/interface/LayerEncoding.h new file mode 100644 index 0000000000000..7e18cff679ba8 --- /dev/null +++ b/L1Trigger/TrackerDTC/interface/LayerEncoding.h @@ -0,0 +1,42 @@ +#ifndef L1Trigger_TrackerDTC_LayerEncoding_h +#define L1Trigger_TrackerDTC_LayerEncoding_h + +#include "FWCore/Framework/interface/data_default_record_trait.h" +#include "L1Trigger/TrackerDTC/interface/LayerEncodingRcd.h" +#include "L1Trigger/TrackTrigger/interface/Setup.h" +#include "L1Trigger/TrackTrigger/interface/SensorModule.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" + +#include + +namespace trackerDTC { + + /*! \class trackerDTC::LayerEncoding + * \brief Class to encode layer ids used between DTC and TFP in Hybrid + * \author Thomas Schuh + * \date 2021, April + */ + class LayerEncoding { + public: + LayerEncoding() {} + LayerEncoding(const edm::ParameterSet& iConfig, const tt::Setup* setup); + ~LayerEncoding() {} + // decode layer id for given sensor module + int decode(tt::SensorModule* sm) const; + // get encoded layers read by given DTC + const std::vector& layers(int dtcId) const { return encodingsLayerId_.at(dtcId % numDTCsPerRegion_); } + + private: + // helper class to store configurations + const tt::Setup* setup_; + // No. of DTCs per detector phi nonant + int numDTCsPerRegion_; + // outer index = dtc id in region, inner index = encoded layerId, inner value = decoded layerId + std::vector> encodingsLayerId_; + }; + +} // namespace trackerDTC + +EVENTSETUP_DATA_DEFAULT_RECORD(trackerDTC::LayerEncoding, trackerDTC::LayerEncodingRcd); + +#endif diff --git a/L1Trigger/TrackerDTC/interface/LayerEncodingRcd.h b/L1Trigger/TrackerDTC/interface/LayerEncodingRcd.h new file mode 100644 index 0000000000000..39d023eddaa0f --- /dev/null +++ b/L1Trigger/TrackerDTC/interface/LayerEncodingRcd.h @@ -0,0 +1,18 @@ +#ifndef L1Trigger_TrackerDTC_LayerEncodingRcd_h +#define L1Trigger_TrackerDTC_LayerEncodingRcd_h + +#include "FWCore/Framework/interface/DependentRecordImplementation.h" +#include "L1Trigger/TrackTrigger/interface/SetupRcd.h" +#include "FWCore/Utilities/interface/mplVector.h" + +namespace trackerDTC { + + typedef edm::mpl::Vector RcdsLayerEncoding; + + // record of trackerDTC::LayerEncoding + class LayerEncodingRcd : public edm::eventsetup::DependentRecordImplementation { + }; + +} // namespace trackerDTC + +#endif \ No newline at end of file diff --git a/L1Trigger/TrackerDTC/interface/Stub.h b/L1Trigger/TrackerDTC/interface/Stub.h index ecbb9fc5184eb..405c1011709de 100644 --- a/L1Trigger/TrackerDTC/interface/Stub.h +++ b/L1Trigger/TrackerDTC/interface/Stub.h @@ -1,17 +1,23 @@ #ifndef L1Trigger_TrackerDTC_Stub_h #define L1Trigger_TrackerDTC_Stub_h -#include "L1Trigger/TrackerDTC/interface/Setup.h" +#include "L1Trigger/TrackTrigger/interface/Setup.h" +#include "L1Trigger/TrackerDTC/interface/LayerEncoding.h" +#include "SimTracker/TrackTriggerAssociation/interface/TTTypes.h" #include #include namespace trackerDTC { - // representation of a stub + /*! \class trackerDTC::Stub + * \brief Class to represent an outer tracker Stub + * \author Thomas Schuh + * \date 2020, Jan + */ class Stub { public: - Stub(const edm::ParameterSet&, const Setup&, SensorModule*, const TTStubRef&); + Stub(const edm::ParameterSet&, const tt::Setup*, const LayerEncoding*, tt::SensorModule*, const TTStubRef&); ~Stub() {} // underlying TTStubRef @@ -21,7 +27,7 @@ namespace trackerDTC { // stub bend in quarter pitch units int bend() const { return bend_; } // bit accurate representation of Stub - TTDTC::BV frame(int region) const; + tt::Frame frame(int region) const; // checks stubs region assignment bool inRegion(int region) const; @@ -29,14 +35,16 @@ namespace trackerDTC { // truncates double precision to f/w integer equivalent double digi(double value, double precision) const; // 64 bit stub in hybrid data format - TTDTC::BV formatHybrid(int region) const; + tt::Frame formatHybrid(int region) const; // 64 bit stub in tmtt data format - TTDTC::BV formatTMTT(int region) const; + tt::Frame formatTMTT(int region) const; // stores, calculates and provides run-time constants - const Setup* setup_; + const tt::Setup* setup_; + // class to encode layer ids used between DTC and TFP in Hybrid + const LayerEncoding* layerEncoding_; // representation of an outer tracker sensormodule - SensorModule* sm_; + tt::SensorModule* sm_; // underlying TTStubRef TTStubRef ttStubRef_; // chosen TT algorithm @@ -65,8 +73,8 @@ namespace trackerDTC { double c_; // radius of a column of strips/pixel in cm double d_; - // range of stub qOverPt in 1/cm - std::pair qOverPt_; + // range of stub inv2R in 1/cm + std::pair inv2R_; // range of stub cot(theta) std::pair cot_; // range of stub extrapolated phi to radius chosenRofPhi in rad diff --git a/L1Trigger/TrackerDTC/plugins/BuildFile.xml b/L1Trigger/TrackerDTC/plugins/BuildFile.xml index 99f679a8a70aa..d02f4a981c62d 100644 --- a/L1Trigger/TrackerDTC/plugins/BuildFile.xml +++ b/L1Trigger/TrackerDTC/plugins/BuildFile.xml @@ -1,6 +1,4 @@ - - diff --git a/L1Trigger/TrackerDTC/plugins/ProducerED.cc b/L1Trigger/TrackerDTC/plugins/ProducerED.cc index 17878a7ef7bb0..46ad569e81355 100644 --- a/L1Trigger/TrackerDTC/plugins/ProducerED.cc +++ b/L1Trigger/TrackerDTC/plugins/ProducerED.cc @@ -12,8 +12,9 @@ #include "DataFormats/L1TrackTrigger/interface/TTTypes.h" #include "DataFormats/L1TrackTrigger/interface/TTDTC.h" -#include "L1Trigger/TrackerDTC/interface/Setup.h" -#include "L1Trigger/TrackerDTC/interface/SensorModule.h" +#include "L1Trigger/TrackTrigger/interface/Setup.h" +#include "L1Trigger/TrackTrigger/interface/SensorModule.h" +#include "L1Trigger/TrackerDTC/interface/LayerEncoding.h" #include "L1Trigger/TrackerDTC/interface/DTC.h" #include @@ -24,6 +25,7 @@ using namespace std; using namespace edm; +using namespace tt; namespace trackerDTC { @@ -42,7 +44,9 @@ namespace trackerDTC { void produce(Event&, const EventSetup&) override; void endJob() {} // helper class to store configurations - Setup setup_; + const Setup* setup_; + // class to encode layer ids used between DTC and TFP in Hybrid + const LayerEncoding* layerEncoding_; // ED input token of TTStubs EDGetTokenT edGetToken_; // ED output token for accepted stubs @@ -50,15 +54,14 @@ namespace trackerDTC { // ED output token for lost stubs EDPutTokenT edPutTokenLost_; // Setup token - ESGetToken esGetToken_; + ESGetToken esGetTokenSetup_; + // LayerEncoding token + ESGetToken esGetTokenLayerEncoding_; // configuration ParameterSet iConfig_; - // throws an exception if current configuration inconsitent with history - bool checkHistory_; }; - ProducerED::ProducerED(const ParameterSet& iConfig) - : iConfig_(iConfig), checkHistory_(iConfig.getParameter("CheckHistory")) { + ProducerED::ProducerED(const ParameterSet& iConfig) : iConfig_(iConfig) { // book in- and output ED products const auto& inputTag = iConfig.getParameter("InputTag"); const auto& branchAccepted = iConfig.getParameter("BranchAccepted"); @@ -66,35 +69,40 @@ namespace trackerDTC { edGetToken_ = consumes(inputTag); edPutTokenAccepted_ = produces(branchAccepted); edPutTokenLost_ = produces(branchLost); - // book ES product - esGetToken_ = esConsumes(); + // book ES products + esGetTokenSetup_ = esConsumes(); + esGetTokenLayerEncoding_ = esConsumes(); + // initial ES products + setup_ = nullptr; + layerEncoding_ = nullptr; } void ProducerED::beginRun(const Run& iRun, const EventSetup& iSetup) { - setup_ = iSetup.getData(esGetToken_); - if (!setup_.configurationSupported()) + setup_ = &iSetup.getData(esGetTokenSetup_); + if (!setup_->configurationSupported()) return; // check process history if desired - if (checkHistory_) - setup_.checkHistory(iRun.processHistory()); + if (iConfig_.getParameter("CheckHistory")) + setup_->checkHistory(iRun.processHistory()); + layerEncoding_ = &iSetup.getData(esGetTokenLayerEncoding_); } void ProducerED::produce(Event& iEvent, const EventSetup& iSetup) { // empty DTC products - TTDTC productAccepted = setup_.ttDTC(); - TTDTC productLost = setup_.ttDTC(); - if (setup_.configurationSupported()) { + TTDTC productAccepted = setup_->ttDTC(); + TTDTC productLost = setup_->ttDTC(); + if (setup_->configurationSupported()) { // read in stub collection Handle handle; iEvent.getByToken(edGetToken_, handle); // apply cabling map, reorganise stub collections - vector>> stubsDTCs(setup_.numDTCs(), - vector>(setup_.numModulesPerDTC())); + vector>> stubsDTCs(setup_->numDTCs(), + vector>(setup_->numModulesPerDTC())); for (auto module = handle->begin(); module != handle->end(); module++) { // DetSetVec->detId + 1 = tk layout det id - const DetId detId = module->detId() + setup_.offsetDetIdDSV(); + const DetId detId = module->detId() + setup_->offsetDetIdDSV(); // corresponding sensor module - SensorModule* sm = setup_.sensorModule(detId); + SensorModule* sm = setup_->sensorModule(detId); // empty stub collection vector& stubsModule = stubsDTCs[sm->dtcId()][sm->modId()]; stubsModule.reserve(module->size()); @@ -102,9 +110,9 @@ namespace trackerDTC { stubsModule.emplace_back(makeRefTo(handle, ttStub)); } // board level processing - for (int dtcId = 0; dtcId < setup_.numDTCs(); dtcId++) { + for (int dtcId = 0; dtcId < setup_->numDTCs(); dtcId++) { // create single outer tracker DTC board - DTC dtc(iConfig_, setup_, dtcId, stubsDTCs.at(dtcId)); + DTC dtc(iConfig_, setup_, layerEncoding_, dtcId, stubsDTCs.at(dtcId)); // route stubs and fill products dtc.produce(productAccepted, productLost); } diff --git a/L1Trigger/TrackerDTC/plugins/ProducerLayerEncoding.cc b/L1Trigger/TrackerDTC/plugins/ProducerLayerEncoding.cc new file mode 100644 index 0000000000000..10721acc3e8d8 --- /dev/null +++ b/L1Trigger/TrackerDTC/plugins/ProducerLayerEncoding.cc @@ -0,0 +1,45 @@ +#include "FWCore/Framework/interface/ESProducer.h" +#include "FWCore/Framework/interface/ESHandle.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/Utilities/interface/ESGetToken.h" +#include "FWCore/Utilities/interface/ESInputTag.h" +#include "DataFormats/Provenance/interface/ParameterSetID.h" +#include "L1Trigger/TrackerDTC/interface/LayerEncoding.h" + +#include + +using namespace std; +using namespace edm; +using namespace tt; + +namespace trackerDTC { + + /*! \class trackerDTC::ProducerLayerEncoding + * \brief Class to produce layer encoding used between DTC and TFP in Hybrid + * \author Thomas Schuh + * \date 2021, April + */ + class ProducerLayerEncoding : public ESProducer { + public: + ProducerLayerEncoding(const ParameterSet& iConfig); + ~ProducerLayerEncoding() override {} + unique_ptr produce(const LayerEncodingRcd& rcd); + + private: + const ParameterSet iConfig_; + ESGetToken esGetToken_; + }; + + ProducerLayerEncoding::ProducerLayerEncoding(const ParameterSet& iConfig) : iConfig_(iConfig) { + auto cc = setWhatProduced(this); + esGetToken_ = cc.consumes(); + } + + unique_ptr ProducerLayerEncoding::produce(const LayerEncodingRcd& rcd) { + const Setup* setup = &rcd.get(esGetToken_); + return make_unique(iConfig_, setup); + } + +} // namespace trackerDTC + +DEFINE_FWK_EVENTSETUP_MODULE(trackerDTC::ProducerLayerEncoding); \ No newline at end of file diff --git a/L1Trigger/TrackerDTC/python/AnalyzerDAQ_cff.py b/L1Trigger/TrackerDTC/python/AnalyzerDAQ_cff.py new file mode 100644 index 0000000000000..3ca3a169112ca --- /dev/null +++ b/L1Trigger/TrackerDTC/python/AnalyzerDAQ_cff.py @@ -0,0 +1,5 @@ +import FWCore.ParameterSet.Config as cms + +from L1Trigger.TrackerDTC.AnalyzerDAQ_cfi import TrackerDTCAnalyzerDAQ_params + +TrackerDTCAnalyzerDAQ = cms.EDAnalyzer('trackerDTC::AnalyzerDAQ', TrackerDTCAnalyzerDAQ_params) \ No newline at end of file diff --git a/L1Trigger/TrackerDTC/python/AnalyzerDAQ_cfi.py b/L1Trigger/TrackerDTC/python/AnalyzerDAQ_cfi.py new file mode 100644 index 0000000000000..8c03b9126c3e8 --- /dev/null +++ b/L1Trigger/TrackerDTC/python/AnalyzerDAQ_cfi.py @@ -0,0 +1,7 @@ +import FWCore.ParameterSet.Config as cms + +TrackerDTCAnalyzerDAQ_params = cms.PSet ( + + InputTagTTClusterDetSetVec = cms.InputTag( "TTClustersFromPhase2TrackerDigis", "ClusterInclusive" ) # original TTCluster selection + +) diff --git a/L1Trigger/TrackerDTC/python/Analyzer_cfi.py b/L1Trigger/TrackerDTC/python/Analyzer_cfi.py index d365c85d60e8e..4b6a091d0884f 100644 --- a/L1Trigger/TrackerDTC/python/Analyzer_cfi.py +++ b/L1Trigger/TrackerDTC/python/Analyzer_cfi.py @@ -2,10 +2,11 @@ TrackerDTCAnalyzer_params = cms.PSet ( - InputTagAccepted = cms.InputTag( "TrackerDTCProducer", "StubAccepted" ), # dtc passed stubs selection - InputTagLost = cms.InputTag( "TrackerDTCProducer", "StubLost" ), # dtc lost stubs selection - InputTagTTStubDetSetVec = cms.InputTag( "TTStubsFromPhase2TrackerDigis", "StubAccepted" ), # original TTStub selection - InputTagTTClusterAssMap = cms.InputTag( "TTClusterAssociatorFromPixelDigis", "ClusterAccepted" ), # tag of AssociationMap between TTCluster and TrackingParticles - UseMCTruth = cms.bool( True ) # eneables analyze of TPs + InputTagAccepted = cms.InputTag( "TrackerDTCProducer", "StubAccepted" ), # dtc passed stubs selection + InputTagLost = cms.InputTag( "TrackerDTCProducer", "StubLost" ), # dtc lost stubs selection + InputTagTTStubDetSetVec = cms.InputTag( "TTStubsFromPhase2TrackerDigis", "StubAccepted" ), # original TTStub selection + InputTagTTClusterDetSetVec = cms.InputTag( "TTClustersFromPhase2TrackerDigis", "ClusterInclusive" ), # original TTCluster selection + InputTagTTClusterAssMap = cms.InputTag( "TTClusterAssociatorFromPixelDigis", "ClusterAccepted" ), # tag of AssociationMap between TTCluster and TrackingParticles + UseMCTruth = cms.bool( True ) # eneables analyze of TPs # eneables analyze of TPs ) diff --git a/L1Trigger/TrackerDTC/python/ProducerED_cff.py b/L1Trigger/TrackerDTC/python/ProducerED_cff.py index 766c8430534f5..cb5eae180e97f 100644 --- a/L1Trigger/TrackerDTC/python/ProducerED_cff.py +++ b/L1Trigger/TrackerDTC/python/ProducerED_cff.py @@ -7,6 +7,7 @@ #=== Import default values for all parameters & define EDProducer. from L1Trigger.TrackerDTC.ProducerED_cfi import TrackerDTCProducer_params -from L1Trigger.TrackerDTC.ProducerES_cff import TrackTriggerSetup +from L1Trigger.TrackTrigger.ProducerSetup_cff import TrackTriggerSetup +from L1Trigger.TrackerDTC.ProducerLayerEncoding_cff import TrackerDTCLayerEncoding TrackerDTCProducer = cms.EDProducer('trackerDTC::ProducerED', TrackerDTCProducer_params) \ No newline at end of file diff --git a/L1Trigger/TrackerDTC/python/ProducerES_cfi.py b/L1Trigger/TrackerDTC/python/ProducerES_cfi.py deleted file mode 100644 index dae8d2f1a0133..0000000000000 --- a/L1Trigger/TrackerDTC/python/ProducerES_cfi.py +++ /dev/null @@ -1,201 +0,0 @@ -import FWCore.ParameterSet.Config as cms - -TrackTrigger_params = cms.PSet ( - - fromDD4hep = cms.bool(False), - - # Parameter to check if configured Tracker Geometry is supported - SupportedGeometry = cms.PSet ( - XMLLabel = cms.string ("geomXMLFiles" ), # label of ESProducer/ESSource - XMLPath = cms.string ("Geometry/TrackerCommonData/data/PhaseII/" ), # compared path - XMLFile = cms.string ("tracker.xml" ), # compared filen ame - XMLVersions = cms.vstring("TiltedTracker613", "TiltedTracker613_MB_2019_04", "OuterTracker616_2020_04", "OuterTracker800_2020_07", "Tracker_DD4hep_compatible_2021_02", "Tracker_DD4hep_compatible_OT801_IT640" ) # list of supported versions - ), - - # Parameter to check if Process History is consistent with process configuration - ProcessHistory = cms.PSet ( - GeometryConfiguration = cms.string( "XMLIdealGeometryESSource@" ), # label of compared GeometryConfiguration - TTStubAlgorithm = cms.string( "TTStubAlgorithm_official_Phase2TrackerDigi_@" ) # label of compared TTStubAlgorithm - ), - - # Common track finding parameter - TrackFinding = cms.PSet ( - BeamWindowZ = cms.double( 15. ), # half lumi region size in cm - MatchedLayers = cms.int32 ( 4 ), # required number of layers a found track has to have in common with a TP to consider it matched to it - MatchedLayersPS = cms.int32 ( 0 ), # required number of ps layers a found track has to have in common with a TP to consider it matched to it - UnMatchedStubs = cms.int32 ( 1 ), # allowed number of stubs a found track may have not in common with its matched TP - UnMatchedStubsPS = cms.int32 ( 0 ) # allowed number of PS stubs a found track may have not in common with its matched TP - ), - - # TMTT specific parameter - TMTT = cms.PSet ( - MinPt = cms.double( 3. ), # cut on stub and TP pt, also defines region overlap shape in GeV - MaxEta = cms.double( 2.4 ), # cut on stub eta - ChosenRofPhi = cms.double( 67.24 ), # critical radius defining region overlap shape in cm - NumLayers = cms.int32 ( 7 ), # number of detector layers a reconstructbale particle may cross - WidthR = cms.int32 ( 12 ), # number of bits used for stub r - ChosenRofPhi - WidthPhi = cms.int32 ( 14 ), # number of bits used for stub phi w.r.t. phi sector centre - WidthZ = cms.int32 ( 14 ) # number of bits used for stub z - ), - - # Hybrid specific parameter - Hybrid = cms.PSet ( - MinPt = cms.double( 2. ), # cut on stub and TP pt, also defines region overlap shape in GeV - MaxEta = cms.double( 2.5 ), # cut on stub eta - ChosenRofPhi = cms.double( 55. ), # critical radius defining region overlap shape in cm - NumLayers = cms.int32 ( 4 ), # max number of detector layer connected to one DTC - NumRingsPS = cms.vint32 ( 11, 11, 8, 8, 8 ), # number of outer PS rings for disk 1, 2, 3, 4, 5 - WidthsR = cms.vint32 ( 7, 7, 12, 7 ), # number of bits used for stub r w.r.t layer/disk centre for module types (barrelPS, barrel2S, diskPS, disk2S) - WidthsZ = cms.vint32 ( 12, 8, 7, 7 ), # number of bits used for stub z w.r.t layer/disk centre for module types (barrelPS, barrel2S, diskPS, disk2S) - WidthsPhi = cms.vint32 ( 14, 17, 14, 14 ), # number of bits used for stub phi w.r.t. region centre for module types (barrelPS, barrel2S, diskPS, disk2S) - WidthsAlpha = cms.vint32 ( 0, 0, 0, 4 ), # number of bits used for stub row number for module types (barrelPS, barrel2S, diskPS, disk2S) - WidthsBend = cms.vint32 ( 3, 4, 3, 4 ), # number of bits used for stub bend number for module types (barrelPS, barrel2S, diskPS, disk2S) - RangesR = cms.vdouble( 7.5, 7.5, 120. , 0. ), # range in stub r which needs to be covered for module types (barrelPS, barrel2S, diskPS, disk2S) - RangesZ = cms.vdouble( 240., 240., 7.5, 7.5 ), # range in stub z which needs to be covered for module types (barrelPS, barrel2S, diskPS, disk2S) - RangesAlpha = cms.vdouble( 0., 0., 0., 1024. ), # range in stub row which needs to be covered for module types (barrelPS, barrel2S, diskPS, disk2S) - LayerRs = cms.vdouble( 24.9316, 37.1777, 52.2656, 68.7598, 86.0156, 108.3105 ), # mean radius of outer tracker barrel layer - DiskZs = cms.vdouble( 131.1914, 154.9805, 185.3320, 221.6016, 265.0195 ), # mean z of outer tracker endcap disks - Disk2SRsSet = cms.VPSet( # center radius of outer tracker endcap 2S diks strips - cms.PSet( Disk2SRs = cms.vdouble( 66.4391, 71.4391, 76.2750, 81.2750, 82.9550, 87.9550, 93.8150, 98.8150, 99.8160, 104.8160 ) ), # disk 1 - cms.PSet( Disk2SRs = cms.vdouble( 66.4391, 71.4391, 76.2750, 81.2750, 82.9550, 87.9550, 93.8150, 98.8150, 99.8160, 104.8160 ) ), # disk 2 - cms.PSet( Disk2SRs = cms.vdouble( 63.9903, 68.9903, 74.2750, 79.2750, 81.9562, 86.9562, 92.4920, 97.4920, 99.8160, 104.8160 ) ), # disk 3 - cms.PSet( Disk2SRs = cms.vdouble( 63.9903, 68.9903, 74.2750, 79.2750, 81.9562, 86.9562, 92.4920, 97.4920, 99.8160, 104.8160 ) ), # disk 4 - cms.PSet( Disk2SRs = cms.vdouble( 63.9903, 68.9903, 74.2750, 79.2750, 81.9562, 86.9562, 92.4920, 97.4920, 99.8160, 104.8160 ) ) # disk 5 - ) - ), - - # Parameter specifying TrackingParticle used for Efficiency measurements - TrackingParticle = cms.PSet ( - MaxEta = cms.double( 2.4 ), # eta cut - MaxVertR = cms.double( 1. ), # cut on vertex pos r in cm - MaxVertZ = cms.double( 30. ), # cut on vertex pos z in cm - MaxD0 = cms.double( 5. ), # cut on impact parameter in cm - MinLayers = cms.int32 ( 4 ), # required number of associated layers to a TP to consider it reconstruct-able - MinLayersPS = cms.int32 ( 0 ) # required number of associated ps layers to a TP to consider it reconstruct-able - ), - - # Fimrware specific Parameter - Firmware = cms.PSet ( - NumFramesInfra = cms.int32 ( 6 ), # needed gap between events of emp-infrastructure firmware - FreqLHC = cms.double( 40. ), # LHC bunch crossing rate in MHz - FreqBE = cms.double( 360. ), # processing Frequency of DTC & TFP in MHz, has to be integer multiple of FreqLHC - TMP_FE = cms.int32 ( 8 ), # number of events collected in front-end - TMP_TFP = cms.int32 ( 18 ), # time multiplexed period of track finding processor - SpeedOfLight = cms.double( 2.99792458 ), # in e8 m/s - BField = cms.double( 3.81120228767395 ), # in T - BFieldError = cms.double( 1.e-6 ), # accepted difference to EventSetup in T - OuterRadius = cms.double( 112.7 ), # outer radius of outer tracker in cm - InnerRadius = cms.double( 21.8 ), # inner radius of outer tracker in cm - HalfLength = cms.double( 270. ), # half length of outer tracker in cm - MaxPitch = cms.double( .01 ) # max strip/pixel pitch of outer tracker sensors in cm - ), - - # Parmeter specifying front-end - FrontEnd = cms.PSet ( - WidthBend = cms.int32 ( 6 ), # number of bits used for internal stub bend - WidthCol = cms.int32 ( 5 ), # number of bits used for internal stub column - WidthRow = cms.int32 ( 11 ), # number of bits used for internal stub row - BaseBend = cms.double( .25 ), # precision of internal stub bend in pitch units - BaseCol = cms.double( 1. ), # precision of internal stub column in pitch units - BaseRow = cms.double( .5 ), # precision of internal stub row in pitch units - BaseWindowSize = cms.double( .5 ), # precision of window sizes in pitch units - BendCut = cms.double( 1.3125 ) # used stub bend uncertainty in pitch units - ), - - # Parmeter specifying DTC - DTC = cms.PSet ( - NumRegions = cms.int32 ( 9 ), # number of phi slices the outer tracker readout is organized in - NumOverlappingRegions = cms.int32 ( 2 ), # number of regions a reconstructable particles may cross - NumATCASlots = cms.int32 ( 12 ), # number of Slots in used ATCA crates - NumDTCsPerRegion = cms.int32 ( 24 ), # number of DTC boards used to readout a detector region, likely constructed to be an integerer multiple of NumSlots_ - NumModulesPerDTC = cms.int32 ( 72 ), # max number of sensor modules connected to one DTC board - NumRoutingBlocks = cms.int32 ( 2 ), # number of systiloic arrays in stub router firmware - DepthMemory = cms.int32 ( 64 ), # fifo depth in stub router firmware - WidthRowLUT = cms.int32 ( 4 ), # number of row bits used in look up table - WidthQoverPt = cms.int32 ( 9 ), # number of bits used for stub qOverPt. lut addr is col + bend = 11 => 1 BRAM -> 18 bits for min and max val -> 9 - OffsetDetIdDSV = cms.int32 ( 1 ), # tk layout det id minus DetSetVec->detId - OffsetDetIdTP = cms.int32 ( -1 ), # tk layout det id minus TrackerTopology lower det id - OffsetLayerDisks = cms.int32 ( 10 ), # offset in layer ids between barrel layer and endcap disks - OffsetLayerId = cms.int32 ( 1 ) # offset between 0 and smallest layer id (barrel layer 1) - ), - - # Parmeter specifying GeometricProcessor - GeometricProcessor = cms.PSet ( - NumSectorsPhi = cms.int32 ( 2 ), # number of phi sectors used in hough transform - ChosenRofZ = cms.double( 50. ), # critical radius defining r-z sector shape in cm - RangeChiZ = cms.double( 90. ), # range of stub z residual w.r.t. sector center which needs to be covered - DepthMemory = cms.int32 ( 64 ), # fifo depth in stub router firmware - BoundariesEta = cms.vdouble( -2.40, -2.08, -1.68, -1.26, -0.90, -0.62, -0.41, -0.20, 0.0, 0.20, 0.41, 0.62, 0.90, 1.26, 1.68, 2.08, 2.40 ) # defining r-z sector shape - ), - - # Parmeter specifying HoughTransform - HoughTransform = cms.PSet ( - NumBinsQoverPt = cms.int32( 16 ), # number of used qOverPt bins - NumBinsPhiT = cms.int32( 32 ), # number of used phiT bins - MinLayers = cms.int32( 5 ), # required number of stub layers to form a candidate - DepthMemory = cms.int32( 32 ) # internal fifo depth - ), - - # Parmeter specifying MiniHoughTransform - MiniHoughTransform = cms.PSet ( - NumBinsQoverPt = cms.int32( 2 ), # number of finer qOverPt bins inside HT bin - NumBinsPhiT = cms.int32( 2 ), # number of finer phiT bins inside HT bin - NumDLB = cms.int32( 2 ), # number of dynamic load balancing steps - MinLayers = cms.int32( 5 ) # required number of stub layers to form a candidate - ), - - # Parmeter specifying SeedFilter - SeedFilter = cms.PSet ( - PowerBaseCot = cms.int32( -6 ), # used cot(Theta) bin width = 2 ** this - BaseDiffZ = cms.int32( 4 ), # used zT bin width = baseZ * 2 ** this - MinLayers = cms.int32( 4 ) # required number of stub layers to form a candidate - ), - - # Parmeter specifying KalmanFilter - KalmanFilter = cms.PSet ( - WidthLutInvPhi = cms.int32( 10 ), # number of bits for internal reciprocal look up - WidthLutInvZ = cms.int32( 10 ), # number of bits for internal reciprocal look up - NumTracks = cms.int32( 16 ), # cut on number of input candidates - MinLayers = cms.int32( 4 ), # required number of stub layers to form a track - MaxLayers = cms.int32( 4 ), # maximum number of layers added to a track - MaxStubsPerLayer = cms.int32( 4 ), # cut on number of stub per layer for input candidates - MaxSkippedLayers = cms.int32( 2 ), # maximum allowed skipped layers from inside to outside to form a track - BaseShiftr0 = cms.int32( -3 ), - BaseShiftr02 = cms.int32( -5 ), - BaseShiftv0 = cms.int32( -2 ), - BaseShiftS00 = cms.int32( -1 ), - BaseShiftS01 = cms.int32( -7 ), - BaseShiftK00 = cms.int32( -9 ), - BaseShiftK10 = cms.int32( -15 ), - BaseShiftR00 = cms.int32( -2 ), - BaseShiftInvR00 = cms.int32( -19 ), - BaseShiftChi20 = cms.int32( -5 ), - BaseShiftC00 = cms.int32( 5 ), - BaseShiftC01 = cms.int32( -3 ), - BaseShiftC11 = cms.int32( -7 ), - BaseShiftr1 = cms.int32( 2 ), - BaseShiftr12 = cms.int32( 5 ), - BaseShiftv1 = cms.int32( 3 ), - BaseShiftS12 = cms.int32( -3 ), - BaseShiftS13 = cms.int32( -3 ), - BaseShiftK21 = cms.int32( -13 ), - BaseShiftK31 = cms.int32( -14 ), - BaseShiftR11 = cms.int32( 3 ), - BaseShiftInvR11 = cms.int32( -21 ), - BaseShiftChi21 = cms.int32( -5 ), - BaseShiftC22 = cms.int32( -3 ), - BaseShiftC23 = cms.int32( -5 ), - BaseShiftC33 = cms.int32( -3 ), - BaseShiftChi2 = cms.int32( -5 ) - ), - - # Parmeter specifying DuplicateRemoval - DuplicateRemoval = cms.PSet ( - DepthMemory = cms.int32( 16 ), # internal memory depth - WidthPhi0 = cms.int32( 12 ), # number of bist used for phi0 - WidthQoverPt = cms.int32( 15 ), # number of bist used for qOverPt - WidthCot = cms.int32( 16 ), # number of bist used for cot(theta) - WidthZ0 = cms.int32( 12 ) # number of bist used for z0 - ) - -) diff --git a/L1Trigger/TrackerDTC/python/ProducerLayerEncoding_cff.py b/L1Trigger/TrackerDTC/python/ProducerLayerEncoding_cff.py new file mode 100644 index 0000000000000..fe8e6a8fad99a --- /dev/null +++ b/L1Trigger/TrackerDTC/python/ProducerLayerEncoding_cff.py @@ -0,0 +1,5 @@ +import FWCore.ParameterSet.Config as cms + +from L1Trigger.TrackerDTC.ProducerLayerEncoding_cfi import TrackerDTCLayerEncoding_params + +TrackerDTCLayerEncoding = cms.ESProducer("trackerDTC::ProducerLayerEncoding", TrackerDTCLayerEncoding_params) \ No newline at end of file diff --git a/L1Trigger/TrackerDTC/python/ProducerLayerEncoding_cfi.py b/L1Trigger/TrackerDTC/python/ProducerLayerEncoding_cfi.py new file mode 100644 index 0000000000000..5a7ee124bf7d8 --- /dev/null +++ b/L1Trigger/TrackerDTC/python/ProducerLayerEncoding_cfi.py @@ -0,0 +1,7 @@ +import FWCore.ParameterSet.Config as cms + +TrackerDTCLayerEncoding_params = cms.PSet ( + + + +) \ No newline at end of file diff --git a/L1Trigger/TrackerDTC/src/DTC.cc b/L1Trigger/TrackerDTC/src/DTC.cc index dbd4138046706..80674eed2581b 100644 --- a/L1Trigger/TrackerDTC/src/DTC.cc +++ b/L1Trigger/TrackerDTC/src/DTC.cc @@ -7,39 +7,41 @@ using namespace std; using namespace edm; +using namespace tt; namespace trackerDTC { DTC::DTC(const ParameterSet& iConfig, - const Setup& setup, + const Setup* setup, + const LayerEncoding* layerEncoding, int dtcId, const std::vector>& stubsDTC) - : setup_(&setup), + : setup_(setup), enableTruncation_(iConfig.getParameter("EnableTruncation")), - region_(dtcId / setup.numDTCsPerRegion()), - board_(dtcId % setup.numDTCsPerRegion()), - modules_(setup.dtcModules(dtcId)), - input_(setup.dtcNumRoutingBlocks(), Stubss(setup.dtcNumModulesPerRoutingBlock())), - lost_(setup.numOverlappingRegions()) { + region_(dtcId / setup->numDTCsPerRegion()), + board_(dtcId % setup->numDTCsPerRegion()), + modules_(setup->dtcModules(dtcId)), + input_(setup->dtcNumRoutingBlocks(), Stubss(setup->dtcNumModulesPerRoutingBlock())), + lost_(setup->numOverlappingRegions()) { // count number of stubs on this dtc auto acc = [](int& sum, const vector& stubsModule) { return sum += stubsModule.size(); }; const int nStubs = accumulate(stubsDTC.begin(), stubsDTC.end(), 0, acc); stubs_.reserve(nStubs); // convert and assign Stubs to DTC routing block channel - for (int modId = 0; modId < setup.numModulesPerDTC(); modId++) { + for (int modId = 0; modId < setup->numModulesPerDTC(); modId++) { const vector& ttStubRefs = stubsDTC[modId]; if (ttStubRefs.empty()) continue; // Module which produced this ttStubRefs SensorModule* module = modules_.at(modId); // DTC routing block id [0-1] - const int blockId = modId / setup.dtcNumModulesPerRoutingBlock(); + const int blockId = modId / setup->dtcNumModulesPerRoutingBlock(); // DTC routing blockc channel id [0-35] - const int channelId = modId % setup.dtcNumModulesPerRoutingBlock(); + const int channelId = modId % setup->dtcNumModulesPerRoutingBlock(); // convert TTStubs and fill input channel Stubs& stubs = input_[blockId][channelId]; for (const TTStubRef& ttStubRef : ttStubRefs) { - stubs_.emplace_back(iConfig, setup, module, ttStubRef); + stubs_.emplace_back(iConfig, setup, layerEncoding, module, ttStubRef); Stub& stub = stubs_.back(); if (stub.valid()) // passed pt and eta cut @@ -48,12 +50,12 @@ namespace trackerDTC { // sort stubs by bend sort(stubs.begin(), stubs.end(), [](Stub* lhs, Stub* rhs) { return abs(lhs->bend()) < abs(rhs->bend()); }); // truncate stubs if desired - if (!enableTruncation_ || (int)stubs.size() <= setup.numFramesFE()) + if (!enableTruncation_ || (int)stubs.size() <= setup->numFramesFE()) continue; // begin of truncated stubs - const auto limit = next(stubs.begin(), setup.numFramesFE()); + const auto limit = next(stubs.begin(), setup->numFramesFE()); // copy truncated stubs into lost output channel - for (int region = 0; region < setup.numOverlappingRegions(); region++) + for (int region = 0; region < setup->numOverlappingRegions(); region++) copy_if( limit, stubs.end(), back_inserter(lost_[region]), [region](Stub* stub) { return stub->inRegion(region); }); // remove truncated stubs form input channel @@ -150,10 +152,10 @@ namespace trackerDTC { void DTC::produce(const Stubss& stubss, TTDTC& product) { int channel(0); auto toFrame = [&channel](Stub* stub) { - return stub ? make_pair(stub->ttStubRef(), stub->frame(channel)) : TTDTC::Frame(); + return stub ? make_pair(stub->ttStubRef(), stub->frame(channel)) : FrameStub(); }; for (const Stubs& stubs : stubss) { - TTDTC::Stream stream; + StreamStub stream; stream.reserve(stubs.size()); transform(stubs.begin(), stubs.end(), back_inserter(stream), toFrame); product.setStream(region_, board_, channel++, stream); diff --git a/L1Trigger/TrackerDTC/src/ES_LayerEncoding.cc b/L1Trigger/TrackerDTC/src/ES_LayerEncoding.cc new file mode 100644 index 0000000000000..da440378a9661 --- /dev/null +++ b/L1Trigger/TrackerDTC/src/ES_LayerEncoding.cc @@ -0,0 +1,4 @@ +#include "FWCore/Utilities/interface/typelookup.h" +#include "L1Trigger/TrackerDTC/interface/LayerEncoding.h" + +TYPELOOKUP_DATA_REG(trackerDTC::LayerEncoding); \ No newline at end of file diff --git a/L1Trigger/TrackerDTC/src/ES_Setup.cc b/L1Trigger/TrackerDTC/src/ES_Setup.cc deleted file mode 100644 index 5ff94b4b86f12..0000000000000 --- a/L1Trigger/TrackerDTC/src/ES_Setup.cc +++ /dev/null @@ -1,4 +0,0 @@ -#include "FWCore/Utilities/interface/typelookup.h" -#include "L1Trigger/TrackerDTC/interface/Setup.h" - -TYPELOOKUP_DATA_REG(trackerDTC::Setup); \ No newline at end of file diff --git a/L1Trigger/TrackerDTC/src/LayerEncoding.cc b/L1Trigger/TrackerDTC/src/LayerEncoding.cc new file mode 100644 index 0000000000000..c72d8968c038e --- /dev/null +++ b/L1Trigger/TrackerDTC/src/LayerEncoding.cc @@ -0,0 +1,45 @@ +#include "L1Trigger/TrackerDTC/interface/LayerEncoding.h" +#include "L1Trigger/TrackTrigger/interface/SensorModule.h" +#include "FWCore/Utilities/interface/Exception.h" + +#include +#include +#include +#include + +using namespace std; +using namespace edm; +using namespace tt; + +namespace trackerDTC { + + LayerEncoding::LayerEncoding(const ParameterSet& iConfig, const Setup* setup) + : setup_(setup), numDTCsPerRegion_(setup->numDTCsPerRegion()) { + encodingsLayerId_.reserve(numDTCsPerRegion_); + for (int dtcInRegion = 0; dtcInRegion < setup->numDTCsPerRegion(); dtcInRegion++) { + set encodingLayerId; + for (int region = 0; region < setup->numRegions(); region++) { + const int dtcId = dtcInRegion + region * setup->numDTCsPerRegion(); + const vector& modules = setup->dtcModules(dtcId); + for (SensorModule* sm : modules) + encodingLayerId.insert(sm->layerId()); + } + // check configuration + if ((int)encodingLayerId.size() > setup->hybridNumLayers()) { + cms::Exception exception("overflow"); + exception << "Cabling map connects more than " << setup->hybridNumLayers() << " layers to a DTC."; + exception.addContext("trackerDTC::LayerEncoding::LayerEncoding"); + throw exception; + } + encodingsLayerId_.emplace_back(encodingLayerId.begin(), encodingLayerId.end()); + } + } + + // decode layer id for given sensor module + int LayerEncoding::decode(SensorModule* sm) const { + const vector& encoding = encodingsLayerId_.at(sm->dtcId() % setup_->numDTCsPerRegion()); + const auto pos = find(encoding.begin(), encoding.end(), sm->layerId()); + return distance(encoding.begin(), pos); + } + +} // namespace trackerDTC diff --git a/L1Trigger/TrackerDTC/src/LayerEncodingRcd.cc b/L1Trigger/TrackerDTC/src/LayerEncodingRcd.cc new file mode 100644 index 0000000000000..01042310e6c56 --- /dev/null +++ b/L1Trigger/TrackerDTC/src/LayerEncodingRcd.cc @@ -0,0 +1,4 @@ +#include "L1Trigger/TrackerDTC/interface/LayerEncodingRcd.h" +#include "FWCore/Framework/interface/eventsetuprecord_registration_macro.h" + +EVENTSETUP_RECORD_REG(trackerDTC::LayerEncodingRcd); \ No newline at end of file diff --git a/L1Trigger/TrackerDTC/src/SetupRcd.cc b/L1Trigger/TrackerDTC/src/SetupRcd.cc deleted file mode 100644 index b407074e82c2b..0000000000000 --- a/L1Trigger/TrackerDTC/src/SetupRcd.cc +++ /dev/null @@ -1,4 +0,0 @@ -#include "L1Trigger/TrackerDTC/interface/SetupRcd.h" -#include "FWCore/Framework/interface/eventsetuprecord_registration_macro.h" - -EVENTSETUP_RECORD_REG(trackerDTC::SetupRcd); \ No newline at end of file diff --git a/L1Trigger/TrackerDTC/src/Stub.cc b/L1Trigger/TrackerDTC/src/Stub.cc index 5647a6a74027d..b10f4a1c56f87 100644 --- a/L1Trigger/TrackerDTC/src/Stub.cc +++ b/L1Trigger/TrackerDTC/src/Stub.cc @@ -7,106 +7,116 @@ using namespace edm; using namespace std; +using namespace tt; namespace trackerDTC { - Stub::Stub(const ParameterSet& iConfig, const Setup& setup, SensorModule* sm, const TTStubRef& ttStubRef) - : setup_(&setup), sm_(sm), ttStubRef_(ttStubRef), hybrid_(iConfig.getParameter("UseHybrid")), valid_(true) { - regions_.reserve(setup.numOverlappingRegions()); + Stub::Stub(const ParameterSet& iConfig, + const Setup* setup, + const LayerEncoding* layerEncoding, + SensorModule* sm, + const TTStubRef& ttStubRef) + : setup_(setup), + layerEncoding_(layerEncoding), + sm_(sm), + ttStubRef_(ttStubRef), + hybrid_(iConfig.getParameter("UseHybrid")), + valid_(true) { + regions_.reserve(setup->numOverlappingRegions()); // get stub local coordinates const MeasurementPoint& mp = ttStubRef->clusterRef(0)->findAverageLocalCoordinatesCentered(); // convert to uniformed local coordinates // column number in pitch units - col_ = (int)floor(pow(-1, sm->signCol()) * (mp.y() - sm->numColumns() / 2) / setup.baseCol()); + col_ = (int)floor(pow(-1, sm->signCol()) * (mp.y() - sm->numColumns() / 2) / setup->baseCol()); // row number in half pitch units - row_ = (int)floor(pow(-1, sm->signRow()) * (mp.x() - sm->numRows() / 2) / setup.baseRow()); + row_ = (int)floor(pow(-1, sm->signRow()) * (mp.x() - sm->numRows() / 2) / setup->baseRow()); // bend number in quarter pitch units - bend_ = (int)floor(pow(-1, sm->signBend()) * (ttStubRef->bendBE()) / setup.baseBend()); + bend_ = (int)floor(pow(-1, sm->signBend()) * (ttStubRef->bendBE()) / setup->baseBend()); // reduced row number for look up - rowLUT_ = (int)floor((double)row_ / pow(2., setup.widthRow() - setup.dtcWidthRowLUT())); + rowLUT_ = (int)floor((double)row_ / pow(2., setup->widthRow() - setup->dtcWidthRowLUT())); // sub row number inside reduced row number - rowSub_ = row_ - (rowLUT_ + .5) * pow(2, setup.widthRow() - setup.dtcWidthRowLUT()); + rowSub_ = row_ - (rowLUT_ + .5) * pow(2, setup->widthRow() - setup->dtcWidthRowLUT()); // convert local to global coordinates - const double y = (col_ + .5) * setup.baseCol() * sm->pitchCol(); + const double y = (col_ + .5) * setup->baseCol() * sm->pitchCol(); // radius of a column of strips/pixel in cm - d_ = sm->r() + y * sm->sin(); + d_ = sm->r() + y * sm->sinTilt(); // stub z in cm - z_ = digi(sm->z() + y * sm->cos(), setup.baseZ()); + z_ = digi(sm->z() + y * sm->cosTilt(), setup->tmttBaseZ()); - const double x0 = rowLUT_ * setup.baseRow() * setup.dtcNumMergedRows() * sm->pitchRow(); - const double x1 = (rowLUT_ + 1) * setup.baseRow() * setup.dtcNumMergedRows() * sm->pitchRow(); - const double x = (rowLUT_ + .5) * setup.baseRow() * setup.dtcNumMergedRows() * sm->pitchRow(); + const double x0 = rowLUT_ * setup->baseRow() * setup->dtcNumMergedRows() * sm->pitchRow(); + const double x1 = (rowLUT_ + 1) * setup->baseRow() * setup->dtcNumMergedRows() * sm->pitchRow(); + const double x = (rowLUT_ + .5) * setup->baseRow() * setup->dtcNumMergedRows() * sm->pitchRow(); // stub r in cm r_ = sqrt(d_ * d_ + x * x); const double phi0 = sm->phi() + atan2(x0, d_); const double phi1 = sm->phi() + atan2(x1, d_); const double c = (phi0 + phi1) / 2.; - const double m = (phi1 - phi0) / setup.dtcNumMergedRows(); + const double m = (phi1 - phi0) / setup->dtcNumMergedRows(); // intercept of linearized stub phi in rad - c_ = digi(c, setup.basePhi()); + c_ = digi(c, setup->tmttBasePhi()); // slope of linearized stub phi in rad / strip - m_ = digi(m, setup.dtcBaseM()); + m_ = digi(m, setup->dtcBaseM()); if (hybrid_) { - if (abs(z_ / r_) > setup.hybridMaxCot()) + if (abs(z_ / r_) > setup->hybridMaxCot()) // did not pass eta cut valid_ = false; } else { // extrapolated z at radius T assuming z0=0 - const double zT = setup.chosenRofZ() * z_ / r_; + const double zT = setup->chosenRofZ() * z_ / r_; // extrapolated z0 window at radius T - const double dZT = setup.beamWindowZ() * abs(1. - setup.chosenRofZ() / r_); + const double dZT = setup->beamWindowZ() * abs(1. - setup->chosenRofZ() / r_); double zTMin = zT - dZT; double zTMax = zT + dZT; - if (zTMin >= setup.maxZT() || zTMax < -setup.maxZT()) + if (zTMin >= setup->maxZT() || zTMax < -setup->maxZT()) // did not pass "eta" cut valid_ = false; else { - zTMin = max(zTMin, -setup.maxZT()); - zTMax = min(zTMax, setup.maxZT()); + zTMin = max(zTMin, -setup->maxZT()); + zTMax = min(zTMax, setup->maxZT()); } // range of stub cot(theta) - cot_ = {zTMin / setup.chosenRofZ(), zTMax / setup.chosenRofZ()}; + cot_ = {zTMin / setup->chosenRofZ(), zTMax / setup->chosenRofZ()}; } // stub r w.r.t. chosenRofPhi in cm - static const double chosenRofPhi = hybrid_ ? setup.hybridChosenRofPhi() : setup.chosenRofPhi(); - r_ = digi(r_ - chosenRofPhi, setup.baseR()); + static const double chosenRofPhi = hybrid_ ? setup->hybridChosenRofPhi() : setup->chosenRofPhi(); + r_ = digi(r_ - chosenRofPhi, setup->tmttBaseR()); // radial (cylindrical) component of sensor separation - const double dr = sm->sep() / (sm->cos() - sm->sin() * z_ / d_); - // converts bend into qOverPt in 1/cm - const double qOverPtOverBend = sm->pitchRow() / dr / d_; - // qOverPt in 1/cm - const double qOverPt = bend_ * setup.baseBend() * qOverPtOverBend; - // qOverPt uncertainty in 1/cm - const double dQoverPt = setup.bendCut() * qOverPtOverBend; - const double minPt = hybrid_ ? setup.hybridMinPt() : setup.minPt(); - const double maxQoverPt = setup.invPtToDphi() / minPt - setup.dtcBaseQoverPt() / 2.; - double qOverPtMin = digi(qOverPt - dQoverPt, setup.dtcBaseQoverPt()); - double qOverPtMax = digi(qOverPt + dQoverPt, setup.dtcBaseQoverPt()); - if (qOverPtMin >= maxQoverPt || qOverPtMax < -maxQoverPt) + const double dr = sm->sep() / (sm->cosTilt() - sm->sinTilt() * z_ / d_); + // converts bend into inv2R in 1/cm + const double inv2ROverBend = sm->pitchRow() / dr / d_; + // inv2R in 1/cm + const double inv2R = -bend_ * setup->baseBend() * inv2ROverBend; + // inv2R uncertainty in 1/cm + const double dInv2R = setup->bendCut() * inv2ROverBend; + const double minPt = hybrid_ ? setup->hybridMinPtStub() : setup->minPt(); + const double maxInv2R = setup->invPtToDphi() / minPt - setup->dtcBaseInv2R() / 2.; + double inv2RMin = digi(inv2R - dInv2R, setup->dtcBaseInv2R()); + double inv2RMax = digi(inv2R + dInv2R, setup->dtcBaseInv2R()); + if (inv2RMin > maxInv2R || inv2RMax < -maxInv2R) { // did not pass pt cut valid_ = false; - else { - qOverPtMin = max(qOverPtMin, -maxQoverPt); - qOverPtMax = min(qOverPtMax, maxQoverPt); + } else { + inv2RMin = max(inv2RMin, -maxInv2R); + inv2RMax = min(inv2RMax, maxInv2R); } - // range of stub qOverPt in 1/cm - qOverPt_ = {qOverPtMin, qOverPtMax}; + // range of stub inv2R in 1/cm + inv2R_ = {inv2RMin, inv2RMax}; // stub phi w.r.t. detector region centre in rad phi_ = c_ + rowSub_ * m_; // range of stub extrapolated phi to radius chosenRofPhi in rad - phiT_.first = phi_ + r_ * qOverPt_.first; - phiT_.second = phi_ + r_ * qOverPt_.second; + phiT_.first = phi_ - r_ * inv2R_.first; + phiT_.second = phi_ - r_ * inv2R_.second; if (phiT_.first > phiT_.second) swap(phiT_.first, phiT_.second); @@ -126,18 +136,18 @@ namespace trackerDTC { if (sm->type() == SensorModule::Disk2S) { // encoded r r_ = sm->encodedR() + (sm->side() ? -col_ : (col_ + sm->numColumns() / 2)); - r_ = (r_ + 0.5) * setup.hybridBaseR(sm->type()); + r_ = (r_ + 0.5) * setup->hybridBaseR(sm->type()); } // encode bend - const vector& encodingBend = setup.encodingBend(sm->windowSize(), sm->psModule()); + const vector& encodingBend = setup->encodingBend(sm->windowSize(), sm->psModule()); const auto pos = find(encodingBend.begin(), encodingBend.end(), abs(ttStubRef->bendBE())); const int uBend = distance(encodingBend.begin(), pos); bend_ = pow(-1, signbit(bend_)) * uBend; } // returns bit accurate representation of Stub - TTDTC::BV Stub::frame(int region) const { return hybrid_ ? formatHybrid(region) : formatTMTT(region); } + Frame Stub::frame(int region) const { return hybrid_ ? formatHybrid(region) : formatTMTT(region); } // returns true if stub belongs to region bool Stub::inRegion(int region) const { return find(regions_.begin(), regions_.end(), region) != regions_.end(); } @@ -146,27 +156,29 @@ namespace trackerDTC { double Stub::digi(double value, double precision) const { return (floor(value / precision) + .5) * precision; } // returns 64 bit stub in hybrid data format - TTDTC::BV Stub::formatHybrid(int region) const { + Frame Stub::formatHybrid(int region) const { const SensorModule::Type type = sm_->type(); - // stub phi w.r.t. processing region centre in rad - const double phi = phi_ - (region - .5) * setup_->baseRegion() + - 0.5 * setup_->hybridBasePhi(type) * (1 << setup_->hybridWidthPhi(type)); - + // layer encoding + const int decodedLayerId = layerEncoding_->decode(sm_); + // stub phi w.r.t. processing region border in rad + double phi = phi_ - (region - .5) * setup_->baseRegion() + setup_->hybridRangePhi() / 2.; + if (phi >= setup_->hybridRangePhi()) + phi = setup_->hybridRangePhi() - setup_->hybridBasePhi(type) / 2.; // convert stub variables into bit vectors const TTBV hwR(r_, setup_->hybridBaseR(type), setup_->hybridWidthR(type), true); const TTBV hwPhi(phi, setup_->hybridBasePhi(type), setup_->hybridWidthPhi(type), true); const TTBV hwZ(z_, setup_->hybridBaseZ(type), setup_->hybridWidthZ(type), true); const TTBV hwAlpha(row_, setup_->hybridBaseAlpha(type), setup_->hybridWidthAlpha(type), true); const TTBV hwBend(bend_, setup_->hybridWidthBend(type), true); - const TTBV hwLayer(sm_->encodedLayerId(), setup_->hybridWidthLayer()); + const TTBV hwLayer(decodedLayerId, setup_->hybridWidthLayerId()); const TTBV hwGap(0, setup_->hybridNumUnusedBits(type)); const TTBV hwValid(1, 1); // assemble final bitset - return TTDTC::BV(hwGap.str() + hwR.str() + hwZ.str() + hwPhi.str() + hwAlpha.str() + hwBend.str() + hwLayer.str() + - hwValid.str()); + return Frame(hwGap.str() + hwR.str() + hwZ.str() + hwPhi.str() + hwAlpha.str() + hwBend.str() + hwLayer.str() + + hwValid.str()); } - TTDTC::BV Stub::formatTMTT(int region) const { + Frame Stub::formatTMTT(int region) const { int layerM = sm_->layerId(); // convert unique layer id [1-6,11-15] into reduced layer id [0-6] // a fiducial track may not cross more then 7 detector layers, for stubs from a given track the reduced layer id is actually unique @@ -204,37 +216,37 @@ namespace trackerDTC { sectorsPhi.set(2); } // assign stub to eta sectors within a processing region - pair setcorEta({0, setup_->numSectorsEta() - 1}); + pair sectorEta({0, setup_->numSectorsEta() - 1}); for (int bin = 0; bin < setup_->numSectorsEta(); bin++) if (asinh(cot_.first) < setup_->boundarieEta(bin + 1)) { - setcorEta.first = bin; + sectorEta.first = bin; break; } - for (int bin = setcorEta.first; bin < setup_->numSectorsEta(); bin++) + for (int bin = sectorEta.first; bin < setup_->numSectorsEta(); bin++) if (asinh(cot_.second) < setup_->boundarieEta(bin + 1)) { - setcorEta.second = bin; + sectorEta.second = bin; break; } // stub phi w.r.t. processing region centre in rad const double phi = phi_ - (region - .5) * setup_->baseRegion(); // convert stub variables into bit vectors const TTBV hwValid(1, 1); - const TTBV hwGap(0, setup_->dtcNumUnusedBits()); - const TTBV hwLayer(layer, setup_->widthLayer()); - const TTBV hwSectorEtaMin(setcorEta.first, setup_->widthSectorEta()); - const TTBV hwSectorEtaMax(setcorEta.second, setup_->widthSectorEta()); - const TTBV hwR(r_, setup_->baseR(), setup_->widthR(), true); - const TTBV hwPhi(phi, setup_->basePhi(), setup_->widthPhiDTC(), true); - const TTBV hwZ(z_, setup_->baseZ(), setup_->widthZ(), true); - const TTBV hwQoverPtMin(qOverPt_.first, setup_->htBaseQoverPt(), setup_->htWidthQoverPt(), true); - const TTBV hwQoverPtMax(qOverPt_.second, setup_->htBaseQoverPt(), setup_->htWidthQoverPt(), true); + const TTBV hwGap(0, setup_->tmttNumUnusedBits()); + const TTBV hwLayer(layer, setup_->tmttWidthLayer()); + const TTBV hwSectorEtaMin(sectorEta.first, setup_->tmttWidthSectorEta()); + const TTBV hwSectorEtaMax(sectorEta.second, setup_->tmttWidthSectorEta()); + const TTBV hwR(r_, setup_->tmttBaseR(), setup_->tmttWidthR(), true); + const TTBV hwPhi(phi, setup_->tmttBasePhi(), setup_->tmttWidthPhi(), true); + const TTBV hwZ(z_, setup_->tmttBaseZ(), setup_->tmttWidthZ(), true); + const TTBV hwInv2RMin(inv2R_.first, setup_->tmttBaseInv2R(), setup_->tmttWidthInv2R(), true); + const TTBV hwInv2RMax(inv2R_.second, setup_->tmttBaseInv2R(), setup_->tmttWidthInv2R(), true); TTBV hwSectorPhis(0, setup_->numSectorsPhi()); for (int sectorPhi = 0; sectorPhi < setup_->numSectorsPhi(); sectorPhi++) hwSectorPhis[sectorPhi] = sectorsPhi[region * setup_->numSectorsPhi() + sectorPhi]; - // assemble final bitsetTTDTC::BV(hwGap.str() + hwValid.str() + hwR.str() + hwPhi.str() + hwZ.str() + hwQoverPtMin.str() + - return TTDTC::BV(hwGap.str() + hwValid.str() + hwR.str() + hwPhi.str() + hwZ.str() + hwQoverPtMin.str() + - hwQoverPtMax.str() + hwSectorEtaMin.str() + hwSectorEtaMax.str() + hwSectorPhis.str() + - hwLayer.str()); + // assemble final bitset + return Frame(hwGap.str() + hwValid.str() + hwR.str() + hwPhi.str() + hwZ.str() + hwLayer.str() + + hwSectorPhis.str() + hwSectorEtaMin.str() + hwSectorEtaMax.str() + hwInv2RMin.str() + + hwInv2RMax.str()); } -} // namespace trackerDTC +} // namespace trackerDTC \ No newline at end of file diff --git a/L1Trigger/TrackerDTC/test/Analyzer.cc b/L1Trigger/TrackerDTC/test/Analyzer.cc index 1ca3af86f9b45..59251f4819114 100644 --- a/L1Trigger/TrackerDTC/test/Analyzer.cc +++ b/L1Trigger/TrackerDTC/test/Analyzer.cc @@ -22,7 +22,8 @@ #include "DataFormats/GeometrySurface/interface/Plane.h" #include "DataFormats/SiStripDetId/interface/StripSubdetector.h" -#include "L1Trigger/TrackerDTC/interface/Setup.h" +#include "L1Trigger/TrackTrigger/interface/Setup.h" +#include "L1Trigger/TrackerDTC/interface/LayerEncoding.h" #include #include @@ -43,6 +44,7 @@ using namespace std; using namespace edm; +using namespace tt; namespace trackerDTC { @@ -61,7 +63,7 @@ namespace trackerDTC { inline string name(Efficiency e) { return string(*(NameEfficiency.begin() + e)); } /*! \class trackerDTC::Analyzer - * \brief Class to analyze hardware like structured TTStub Collection used by Track Trigger emulators + * \brief Class to analyze hardware like structured TTStub Collection used by Track Trigger emulators, runs DTC stub emulation, plots performance & stub occupancy * \author Thomas Schuh * \date 2020, Apr */ @@ -92,7 +94,7 @@ namespace trackerDTC { // analyze DTC products and find still reconstrucable TrackingParticles void analyzeStubs(const TTDTC*, const TTDTC*, const map>&, map>&); // fill stub related histograms - void analyzeStream(const TTDTC::Stream& stream, int region, int channel, int& sum, TH2F* th2f); + void analyzeStream(const StreamStub& stream, int region, int channel, int& sum, TH2F* th2f); // returns layerId [1-6, 11-15] of stub int layerId(const TTStubRef& ttStubRef) const; // analyze survived TPs @@ -108,18 +110,24 @@ namespace trackerDTC { EDGetTokenT getTokenTTDTCLost_; // ED input token of TT stubs EDGetTokenT getTokenTTStubDetSetVec_; + // ED input token of TTClsuter + EDGetTokenT getTokenTTClusterDetSetVec_; // ED input token of TTCluster to TPPtr association EDGetTokenT getTokenTTClusterAssMap_; // Setup token ESGetToken esGetToken_; // stores, calculates and provides run-time constants - Setup setup_; + const Setup* setup_; // selector to partly select TPs for efficiency measurements TrackingParticleSelector tpSelector_; + // + TrackingParticleSelector tpSelectorLoose_; // enables analyze of TPs bool useMCTruth_; // specifies used TT algorithm bool hybrid_; + // + int nEvents_; // Histograms @@ -141,7 +149,9 @@ namespace trackerDTC { }; Analyzer::Analyzer(const ParameterSet& iConfig) - : useMCTruth_(iConfig.getParameter("UseMCTruth")), hybrid_(iConfig.getParameter("UseHybrid")) { + : useMCTruth_(iConfig.getParameter("UseMCTruth")), + hybrid_(iConfig.getParameter("UseHybrid")), + nEvents_(0) { usesResource("TFileService"); // book in- and output ED products const auto& inputTagAccepted = iConfig.getParameter("InputTagAccepted"); @@ -150,12 +160,16 @@ namespace trackerDTC { getTokenTTDTCLost_ = consumes(inputTagLost); if (useMCTruth_) { const auto& inputTagTTStubDetSetVec = iConfig.getParameter("InputTagTTStubDetSetVec"); + const auto& inputTagTTClusterDetSetVec = iConfig.getParameter("InputTagTTClusterDetSetVec"); const auto& inputTagTTClusterAssMap = iConfig.getParameter("InputTagTTClusterAssMap"); getTokenTTStubDetSetVec_ = consumes(inputTagTTStubDetSetVec); + getTokenTTClusterDetSetVec_ = consumes(inputTagTTClusterDetSetVec); getTokenTTClusterAssMap_ = consumes(inputTagTTClusterAssMap); } // book ES product esGetToken_ = esConsumes(); + //initial ES product + setup_ = nullptr; // log config log_.setf(ios::fixed, ios::floatfield); log_.precision(4); @@ -163,7 +177,7 @@ namespace trackerDTC { void Analyzer::beginRun(const Run& iEvent, const EventSetup& iSetup) { // helper class to store configurations - setup_ = iSetup.getData(esGetToken_); + setup_ = &iSetup.getData(esGetToken_); // configuring track particle selector configTPSelector(); // book histograms @@ -183,6 +197,12 @@ namespace trackerDTC { assoc(handleTTStubDetSetVec, handleTTClusterAssMap, mapAllTPsAllStubs); // organize reconstrucable TrackingParticles used for efficiency measurements convert(mapAllTPsAllStubs, mapAllStubsTPs); + Handle handleTTClusterDetSetVec; + iEvent.getByToken(getTokenTTClusterDetSetVec_, handleTTClusterDetSetVec); + int nCluster(0); + for (const auto& detSet : *handleTTClusterDetSetVec) + nCluster += detSet.size(); + profMC_->Fill(6, nCluster / (double)setup_->numRegions()); } // read in dtc products Handle handleTTDTCAccepted; @@ -194,9 +214,12 @@ namespace trackerDTC { analyzeStubs(handleTTDTCAccepted.product(), handleTTDTCLost.product(), mapAllStubsTPs, mapTPsTTStubs); // analyze survived TPs analyzeTPs(mapTPsTTStubs); + nEvents_++; } void Analyzer::endJob() { + if (nEvents_ == 0) + return; // create r-z stub fraction plot TH2F th2f("", ";;", 400, -300, 300., 400, 0., 120.); th2f.Add(hisRZStubsLost_); @@ -210,11 +233,12 @@ namespace trackerDTC { eff_[e]->SetTotalHistogram(*hisEffMC_[e], "f"); } } + log_ << "'Lost' below refers to truncation losses" << endl; // printout MC summary endJobMC(); // printout DTC summary endJobDTC(); - log_ << "=============================================================" << endl; + log_ << "============================================================="; LogPrint("L1Trigger/TrackerDTC") << log_.str(); } @@ -242,8 +266,8 @@ namespace trackerDTC { nStubsMatched++; } } - profMC_->Fill(1, nStubs / (double)setup_.numRegions()); - profMC_->Fill(2, nStubsMatched / (double)setup_.numRegions()); + profMC_->Fill(1, nStubs / (double)setup_->numRegions()); + profMC_->Fill(2, nStubsMatched / (double)setup_->numRegions()); } // organize reconstrucable TrackingParticles used for efficiency measurements @@ -251,10 +275,10 @@ namespace trackerDTC { int nTPsReco(0); int nTPsEff(0); for (const auto& mapTPStubs : mapTPsStubs) { - if (!reconstructable(mapTPStubs.second)) + if (!tpSelectorLoose_(*mapTPStubs.first) || !reconstructable(mapTPStubs.second)) continue; nTPsReco++; - const bool useForAlgEff = select(*mapTPStubs.first.get()); + const bool useForAlgEff = select(*mapTPStubs.first); if (useForAlgEff) { nTPsEff++; fill(mapTPStubs.first, hisEffMC_); @@ -262,14 +286,15 @@ namespace trackerDTC { mapStubsTPs[ttStubRef].insert(mapTPStubs.first); } } - profMC_->Fill(3, nTPsReco); - profMC_->Fill(4, nTPsEff); + profMC_->Fill(3, nTPsReco / (double)setup_->numRegions()); + profMC_->Fill(4, nTPsEff / (double)setup_->numRegions()); + profMC_->Fill(5, nTPsEff); } // checks if a stub selection is considered reconstructable bool Analyzer::reconstructable(const set& ttStubRefs) const { - const TrackerGeometry* trackerGeometry = setup_.trackerGeometry(); - const TrackerTopology* trackerTopology = setup_.trackerTopology(); + const TrackerGeometry* trackerGeometry = setup_->trackerGeometry(); + const TrackerTopology* trackerTopology = setup_->trackerTopology(); set hitPattern; set hitPatternPS; for (const TTStubRef& ttStubRef : ttStubRefs) { @@ -281,7 +306,7 @@ namespace trackerDTC { if (psModule) hitPatternPS.insert(layerId); } - return (int)hitPattern.size() >= setup_.tpMinLayers() && (int)hitPatternPS.size() >= setup_.tpMinLayersPS(); + return (int)hitPattern.size() >= setup_->tpMinLayers() && (int)hitPatternPS.size() >= setup_->tpMinLayersPS(); } // checks if TrackingParticle is selected for efficiency measurements @@ -293,7 +318,7 @@ namespace trackerDTC { const TrackingParticle::Point& v = tp.vertex(); const double z0 = v.z() - (v.x() * c + v.y() * s) * cot; const double d0 = v.x() * s - v.y() * c; - return selected && (fabs(d0) < setup_.tpMaxD0()) && (fabs(z0) < setup_.tpMaxVertZ()); + return selected && (fabs(d0) < setup_->tpMaxD0()) && (fabs(z0) < setup_->tpMaxVertZ()); } // fills kinematic tp histograms @@ -316,14 +341,14 @@ namespace trackerDTC { const TTDTC* lost, const map>& mapStubsTPs, map>& mapTPsStubs) { - for (int region = 0; region < setup_.numRegions(); region++) { + for (int region = 0; region < setup_->numRegions(); region++) { int nStubs(0); int nLost(0); - for (int channel = 0; channel < setup_.numDTCsPerTFP(); channel++) { - const TTDTC::Stream& stream = accepted->stream(region, channel); + for (int channel = 0; channel < setup_->numDTCsPerTFP(); channel++) { + const StreamStub& stream = accepted->stream(region, channel); hisChannel_->Fill(stream.size()); - profChannel_->Fill(region * setup_.numDTCsPerTFP() + channel, stream.size()); - for (const TTDTC::Frame& frame : stream) { + profChannel_->Fill(region * setup_->numDTCsPerTFP() + channel, stream.size()); + for (const FrameStub& frame : stream) { if (frame.first.isNull()) continue; const auto it = mapStubsTPs.find(frame.first); @@ -341,13 +366,13 @@ namespace trackerDTC { } // fill stub related histograms - void Analyzer::analyzeStream(const TTDTC::Stream& stream, int region, int channel, int& sum, TH2F* th2f) { - for (const TTDTC::Frame& frame : stream) { + void Analyzer::analyzeStream(const StreamStub& stream, int region, int channel, int& sum, TH2F* th2f) { + for (const FrameStub& frame : stream) { if (frame.first.isNull()) continue; sum++; - const GlobalPoint& pos = setup_.stubPos(hybrid_, frame, region, channel); - const GlobalPoint& ttPos = setup_.stubPos(frame.first); + const GlobalPoint& pos = setup_->stubPos(hybrid_, frame, region); + const GlobalPoint& ttPos = setup_->stubPos(frame.first); const vector resolutions = { ttPos.perp() - pos.perp(), deltaPhi(ttPos.phi() - pos.phi()), ttPos.z() - pos.z()}; for (Resolution r : AllResolution) { @@ -355,22 +380,15 @@ namespace trackerDTC { profResolution_[r]->Fill(ttPos.z(), ttPos.perp(), abs(resolutions[r])); } th2f->Fill(ttPos.z(), ttPos.perp()); - // check layerId encoding - if (!hybrid_) - continue; - const vector& encodingLayerId = setup_.encodingLayerId(channel); - const auto it = find(encodingLayerId.begin(), encodingLayerId.end(), layerId(frame.first)); - if (it == encodingLayerId.end()) - throw cms::Exception("LogicError") << "Stub send from a DTC which is not connected to stub's layer."; } } // returns layerId [1-6, 11-15] of stub int Analyzer::layerId(const TTStubRef& ttStubRef) const { - const TrackerTopology* trackerTopology = setup_.trackerTopology(); - const DetId detId = ttStubRef->getDetId() + setup_.offsetDetIdDSV(); + const TrackerTopology* trackerTopology = setup_->trackerTopology(); + const DetId detId = ttStubRef->getDetId() + setup_->offsetDetIdDSV(); const bool barrel = detId.subdetId() == StripSubdetector::TOB; - return barrel ? trackerTopology->layer(detId) : trackerTopology->tidWheel(detId) + setup_.offsetLayerDisks(); + return barrel ? trackerTopology->layer(detId) : trackerTopology->tidWheel(detId) + setup_->offsetLayerDisks(); } // analyze survived TPs @@ -395,12 +413,16 @@ namespace trackerDTC { const double errStubsMatched = profMC_->GetBinError(2); const double errTPsReco = profMC_->GetBinError(3); const double errTPsEff = profMC_->GetBinError(4); - const vector nums = {numStubs, numStubsMatched, numTPsReco, numTPsEff}; - const vector errs = {errStubs, errStubsMatched, errTPsReco, errTPsEff}; + const double numCluster = profMC_->GetBinContent(6); + const double errCluster = profMC_->GetBinError(6); + const vector nums = {numStubs, numStubsMatched, numTPsReco, numTPsEff, numCluster}; + const vector errs = {errStubs, errStubsMatched, errTPsReco, errTPsEff, errCluster}; const int wNums = ceil(log10(*max_element(nums.begin(), nums.end()))) + 5; const int wErrs = ceil(log10(*max_element(errs.begin(), errs.end()))) + 5; log_ << "=============================================================" << endl; log_ << " MC SUMMARY " << endl; + log_ << "number of cluster per TFP = " << setw(wNums) << numCluster << " +- " << setw(wErrs) << errCluster + << endl; log_ << "number of stubs per TFP = " << setw(wNums) << numStubs << " +- " << setw(wErrs) << errStubs << endl; log_ << "number of matched stubs per TFP = " << setw(wNums) << numStubsMatched << " +- " << setw(wErrs) @@ -418,9 +440,9 @@ namespace trackerDTC { const double numTPs = profDTC_->GetBinContent(3); const double errStubs = profDTC_->GetBinError(1); const double errStubsLost = profDTC_->GetBinError(2); - const double totalTPs = profMC_->GetBinContent(4); + const double totalTPs = profMC_->GetBinContent(5); const double eff = numTPs / totalTPs; - const double errEff = sqrt(eff * (1. - eff) / totalTPs); + const double errEff = sqrt(eff * (1. - eff) / totalTPs / nEvents_); const vector nums = {numStubs, numStubsLost}; const vector errs = {errStubs, errStubsLost}; const int wNums = ceil(log10(*max_element(nums.begin(), nums.end()))) + 5; @@ -435,11 +457,11 @@ namespace trackerDTC { // configuring track particle selector void Analyzer::configTPSelector() { - const double ptMin = hybrid_ ? setup_.hybridMinPt() : setup_.minPt(); + const double ptMin = hybrid_ ? setup_->hybridMinPtStub() : setup_->minPt(); constexpr double ptMax = 9999999999.; - const double etaMax = setup_.tpMaxEta(); - const double tip = setup_.tpMaxVertR(); - const double lip = setup_.tpMaxVertZ(); + const double etaMax = setup_->tpMaxEta(); + const double tip = setup_->tpMaxVertR(); + const double lip = setup_->tpMaxVertZ(); constexpr int minHit = 0; constexpr bool signalOnly = true; constexpr bool intimeOnly = true; @@ -447,6 +469,8 @@ namespace trackerDTC { constexpr bool stableOnly = false; tpSelector_ = TrackingParticleSelector( ptMin, ptMax, -etaMax, etaMax, tip, lip, minHit, signalOnly, intimeOnly, chargedOnly, stableOnly); + tpSelectorLoose_ = + TrackingParticleSelector(ptMin, ptMax, -etaMax, etaMax, tip, lip, minHit, false, false, false, stableOnly); } // book histograms @@ -455,11 +479,13 @@ namespace trackerDTC { TFileDirectory dir; // mc dir = fs->mkdir("MC"); - profMC_ = dir.make("Counts", ";", 4, 0.5, 4.5); + profMC_ = dir.make("Counts", ";", 6, 0.5, 6.5); profMC_->GetXaxis()->SetBinLabel(1, "Stubs"); profMC_->GetXaxis()->SetBinLabel(2, "Matched Stubs"); profMC_->GetXaxis()->SetBinLabel(3, "reco TPs"); profMC_->GetXaxis()->SetBinLabel(4, "eff TPs"); + profMC_->GetXaxis()->SetBinLabel(5, "total eff TPs"); + profMC_->GetXaxis()->SetBinLabel(6, "Cluster"); constexpr array binsEff{{9 * 8, 10, 16, 10, 30, 24}}; constexpr array, NumEfficiency> rangesEff{ {{-M_PI, M_PI}, {0., 100.}, {-1. / 3., 1. / 3.}, {-5., 5.}, {-15., 15.}, {-2.4, 2.4}}}; @@ -477,7 +503,7 @@ namespace trackerDTC { profDTC_->GetXaxis()->SetBinLabel(3, "TPs"); // channel occupancy constexpr int maxOcc = 180; - const int numChannels = setup_.numDTCs() * setup_.numOverlappingRegions(); + const int numChannels = setup_->numDTCs() * setup_->numOverlappingRegions(); hisChannel_ = dir.make("His Channel Occupancy", ";", maxOcc, -.5, maxOcc - .5); profChannel_ = dir.make("Prof Channel Occupancy", ";", numChannels, -.5, numChannels - .5); // max tracking efficiencies diff --git a/L1Trigger/TrackerDTC/test/AnalyzerDAQ.cc b/L1Trigger/TrackerDTC/test/AnalyzerDAQ.cc new file mode 100644 index 0000000000000..ebfa0708ccb62 --- /dev/null +++ b/L1Trigger/TrackerDTC/test/AnalyzerDAQ.cc @@ -0,0 +1,131 @@ +#include "FWCore/Framework/interface/one/EDAnalyzer.h" +#include "FWCore/Framework/interface/Run.h" +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/EventSetup.h" +#include "FWCore/Framework/interface/MakerMacros.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/ServiceRegistry/interface/Service.h" +#include "FWCore/MessageLogger/interface/MessageLogger.h" +#include "FWCore/Utilities/interface/EDGetToken.h" +#include "FWCore/Utilities/interface/InputTag.h" +#include "FWCore/Utilities/interface/Exception.h" +#include "CommonTools/UtilAlgos/interface/TFileService.h" +#include "DataFormats/Common/interface/Handle.h" + +#include "L1Trigger/TrackTrigger/interface/Setup.h" + +#include +#include + +#include +#include + +using namespace std; +using namespace edm; +using namespace tt; + +namespace trackerDTC { + + /*! \class trackerDTC::AnalyzerDAQ + * \brief Class to analyze TTCluster Occupancies on DTCs, plots cluster occupancy + * \author Thomas Schuh + * \date 2020, Oct + */ + class AnalyzerDAQ : public one::EDAnalyzer { + public: + AnalyzerDAQ(const ParameterSet& iConfig); + void beginJob() override {} + void beginRun(const Run& iEvent, const EventSetup& iSetup) override; + void analyze(const Event& iEvent, const EventSetup& iSetup) override; + void endRun(const Run& iEvent, const EventSetup& iSetup) override {} + void endJob() override {} + + private: + // ED input token of accepted TTClusters + EDGetTokenT edGetToken_; + // Setup token + ESGetToken esGetTokenSetup_; + // stores, calculates and provides run-time constants + const Setup* setup_; + + // Histograms + + TProfile* profModules_; + TH1F* hisModules_; + TProfile* profDTCs_; + TH1F* hisDTCs_; + TH1F* hisTracker_; + }; + + AnalyzerDAQ::AnalyzerDAQ(const ParameterSet& iConfig) { + usesResource("TFileService"); + // book input ED products + const auto& inputTag = iConfig.getParameter("InputTagTTClusterDetSetVec"); + edGetToken_ = consumes(inputTag); + // book ES products + esGetTokenSetup_ = esConsumes(); + // initial ES products + setup_ = nullptr; + } + + void AnalyzerDAQ::beginRun(const Run& iEvent, const EventSetup& iSetup) { + // helper class to store configurations + setup_ = &iSetup.getData(esGetTokenSetup_); + // book histograms + Service fs; + TFileDirectory dir; + dir = fs->mkdir("Modules"); + int maxOcc = 150; + int numChannels = setup_->numDTCs() * setup_->numModulesPerDTC(); + hisModules_ = dir.make("His Module Occupancy", ";", maxOcc, -.5, maxOcc - .5); + profModules_ = dir.make("Prof Module Occupancy", ";", numChannels, -.5, numChannels - .5); + dir = fs->mkdir("DTCs"); + maxOcc = 3456; + numChannels = setup_->numDTCs(); + hisDTCs_ = dir.make("His DTC Occupancy", ";", maxOcc / 16, -.5, maxOcc - .5); + profDTCs_ = dir.make("Prof DTC Occupancy", ";", numChannels, -.5, numChannels - .5); + dir = fs->mkdir("Tracker"); + maxOcc = pow(2, 29); + hisTracker_ = dir.make("His Tracker Occupancy", ";", maxOcc * pow(2., -12), -.5, maxOcc - .5); + } + + void AnalyzerDAQ::analyze(const Event& iEvent, const EventSetup& iSetup) { + // read in original TTCluster collection + Handle handle; + iEvent.getByToken(edGetToken_, handle); + // apply cabling map, reorganise cluster collections + vector>> dtcs(setup_->numDTCs(), + vector>(setup_->numModulesPerDTC())); + for (auto itModule = handle->begin(); itModule != handle->end(); itModule++) { + // DetSetVec->detId - 1 or + 0 = tk layout det id depending from which of both sensor planes the cluster has been constructed + const DetId& detIdModule = itModule->detId(); + const int offset = setup_->trackerTopology()->isLower(detIdModule) ? 0 : setup_->offsetDetIdTP(); + const DetId detId = detIdModule + offset; + // corresponding sensor module + SensorModule* sm = setup_->sensorModule(detId); + // empty cluster collection + deque& module = dtcs[sm->dtcId()][sm->modId()]; + for (TTClusterDetSet::const_iterator itCluster = itModule->begin(); itCluster != itModule->end(); itCluster++) + module.emplace_back(makeRefTo(handle, itCluster)); + } + // analyze organized TTCluster collections + int iDTC(0); + int iModule(0); + int nAll(0); + for (const vector>& dtc : dtcs) { + int nCluster(0); + for (const deque& module : dtc) { + nCluster += module.size(); + hisModules_->Fill(module.size()); + profModules_->Fill(iModule++, module.size()); + } + nAll += nCluster; + hisDTCs_->Fill(nCluster); + profDTCs_->Fill(iDTC++, nCluster); + } + hisTracker_->Fill(nAll); + } + +} // namespace trackerDTC + +DEFINE_FWK_MODULE(trackerDTC::AnalyzerDAQ); \ No newline at end of file diff --git a/L1Trigger/TrackerDTC/test/BuildFile.xml b/L1Trigger/TrackerDTC/test/BuildFile.xml index 7d91dc2e4b195..90591991cf254 100644 --- a/L1Trigger/TrackerDTC/test/BuildFile.xml +++ b/L1Trigger/TrackerDTC/test/BuildFile.xml @@ -1,6 +1,4 @@ - - diff --git a/L1Trigger/TrackerDTC/test/testDAQ_cfg.py b/L1Trigger/TrackerDTC/test/testDAQ_cfg.py new file mode 100644 index 0000000000000..760b4fe33a831 --- /dev/null +++ b/L1Trigger/TrackerDTC/test/testDAQ_cfg.py @@ -0,0 +1,60 @@ +################################################################################################ +# plots cluster occupancy +# To run execute do +# cmsRun L1Trigger/TrackerDTC/test/testDAQ.py +# where the arguments take default values if you don't specify them. You can change defaults below. +################################################################################################# + +import FWCore.ParameterSet.Config as cms + +process = cms.Process( "Demo" ) +process.load( 'FWCore.MessageService.MessageLogger_cfi' ) +process.load( 'Configuration.Geometry.GeometryExtended2026D76Reco_cff' ) +process.load( 'Configuration.Geometry.GeometryExtended2026D76_cff' ) +process.load( 'Configuration.StandardSequences.MagneticField_cff' ) +process.load( 'Configuration.StandardSequences.FrontierConditions_GlobalTag_cff' ) +process.load( 'L1Trigger.TrackTrigger.TrackTrigger_cff' ) + +from Configuration.AlCa.GlobalTag import GlobalTag +process.GlobalTag = GlobalTag(process.GlobalTag, 'auto:phase2_realistic', '') + +# load code that analyzes TTCluster +process.load( 'L1Trigger.TrackerDTC.AnalyzerDAQ_cff' ) + +# build schedule +process.path = cms.Path( process.TrackerDTCAnalyzerDAQ ) +process.schedule = cms.Schedule( process.path ) + +# create options +import FWCore.ParameterSet.VarParsing as VarParsing +options = VarParsing.VarParsing( 'analysis' ) +# specify input MC +Samples = [ + #'/store/relval/CMSSW_11_3_0_pre6/RelValSingleMuFlatPt2To100/GEN-SIM-DIGI-RAW/113X_mcRun4_realistic_v6_2026D76noPU-v1/10000/05f802b7-b0b3-4cca-8b70-754682c3bb4c.root' + #'/store/relval/CMSSW_11_3_0_pre6/RelValDisplacedMuPt2To100Dxy100/GEN-SIM-DIGI-RAW/113X_mcRun4_realistic_v6_2026D76noPU-v1/00000/011da61a-9524-4a96-b91f-03e8690af3bd.root' + '/store/relval/CMSSW_11_3_0_pre6/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/00000/00026541-6200-4eed-b6f8-d3a1fd720e9c.root', + '/store/relval/CMSSW_11_3_0_pre6/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/00000/013d0125-8f6e-496b-8335-614398c9210d.root', + '/store/relval/CMSSW_11_3_0_pre6/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/00000/058bd134-86de-47e1-bcde-379ed9b79e1b.root', + '/store/relval/CMSSW_11_3_0_pre6/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/00000/0915d66c-cbd4-4ef6-9971-7dd59e198b56.root', + '/store/relval/CMSSW_11_3_0_pre6/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/00000/09823c8d-e443-4066-8347-8c704929cb2b.root', + '/store/relval/CMSSW_11_3_0_pre6/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/00000/0c39a1aa-93ee-41c1-8543-6d90c09114a7.root', + '/store/relval/CMSSW_11_3_0_pre6/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/00000/0fcdcc53-fb9f-4f0b-8529-a4d60d914c14.root', + '/store/relval/CMSSW_11_3_0_pre6/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/00000/16760a5c-9cd2-41c3-82e5-399bb962d537.root', + '/store/relval/CMSSW_11_3_0_pre6/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/00000/1752640f-2001-4d14-9276-063ec07cea92.root', + '/store/relval/CMSSW_11_3_0_pre6/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/00000/180712c9-31a5-4f2a-bf92-a7fbee4dabad.root' +] +options.register( 'inputMC', Samples, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.string, "Files to be processed" ) +# specify number of events to process. +options.register( 'Events',100,VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.int, "Number of Events to analyze" ) +options.parseArguments() + +process.options = cms.untracked.PSet( wantSummary = cms.untracked.bool(False) ) +process.maxEvents = cms.untracked.PSet( input = cms.untracked.int32(options.Events) ) +process.source = cms.Source( + "PoolSource", + fileNames = cms.untracked.vstring( options.inputMC ), + secondaryFileNames = cms.untracked.vstring(), + duplicateCheckMode = cms.untracked.string( 'noDuplicateCheck' ) +) +process.Timing = cms.Service( "Timing", summaryOnly = cms.untracked.bool( True ) ) +process.TFileService = cms.Service( "TFileService", fileName = cms.string( "Hist.root" ) ) \ No newline at end of file diff --git a/L1Trigger/TrackerDTC/test/test_cfg.py b/L1Trigger/TrackerDTC/test/test_cfg.py index 3a08d88cf0bee..ff7d85e51a7df 100644 --- a/L1Trigger/TrackerDTC/test/test_cfg.py +++ b/L1Trigger/TrackerDTC/test/test_cfg.py @@ -1,4 +1,5 @@ ################################################################################################ +# runs DTC stub emulation, plots performance & stub occupancy # To run execute do # cmsRun L1Trigger/TrackerDTC/test/test.py # where the arguments take default values if you don't specify them. You can change defaults below. @@ -7,14 +8,15 @@ import FWCore.ParameterSet.Config as cms process = cms.Process( "Demo" ) -process.load( 'Configuration.Geometry.GeometryExtended2026D49Reco_cff' ) +process.load( 'FWCore.MessageService.MessageLogger_cfi' ) +process.load( 'Configuration.Geometry.GeometryExtended2026D76Reco_cff' ) +process.load( 'Configuration.Geometry.GeometryExtended2026D76_cff' ) process.load( 'Configuration.StandardSequences.MagneticField_cff' ) process.load( 'Configuration.StandardSequences.FrontierConditions_GlobalTag_cff' ) -process.load( 'Configuration.StandardSequences.L1TrackTrigger_cff' ) -process.load( "FWCore.MessageLogger.MessageLogger_cfi" ) +process.load( 'L1Trigger.TrackTrigger.TrackTrigger_cff' ) from Configuration.AlCa.GlobalTag import GlobalTag -process.GlobalTag = GlobalTag( process.GlobalTag, 'auto:phase2_realistic', '' ) +process.GlobalTag = GlobalTag(process.GlobalTag, 'auto:phase2_realistic', '') # load code that produces DTCStubs process.load( 'L1Trigger.TrackerDTC.ProducerED_cff' ) @@ -34,9 +36,20 @@ import FWCore.ParameterSet.VarParsing as VarParsing options = VarParsing.VarParsing( 'analysis' ) # specify input MC -Samples = { - '/store/relval/CMSSW_11_2_0_pre6/RelValSingleMuFlatPt1p5To8/GEN-SIM-DIGI-RAW/112X_mcRun4_realistic_v2_2026D49noPU_L1T-v1/20000/4E15C795-152F-A040-8AF4-5AF5F97EB996.root' -} +Samples = [ + #'/store/relval/CMSSW_11_3_0_pre6/RelValSingleMuFlatPt2To100/GEN-SIM-DIGI-RAW/113X_mcRun4_realistic_v6_2026D76noPU-v1/10000/05f802b7-b0b3-4cca-8b70-754682c3bb4c.root' + #'/store/relval/CMSSW_11_3_0_pre6/RelValDisplacedMuPt2To100Dxy100/GEN-SIM-DIGI-RAW/113X_mcRun4_realistic_v6_2026D76noPU-v1/00000/011da61a-9524-4a96-b91f-03e8690af3bd.root' + '/store/relval/CMSSW_11_3_0_pre6/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/00000/00026541-6200-4eed-b6f8-d3a1fd720e9c.root', + '/store/relval/CMSSW_11_3_0_pre6/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/00000/013d0125-8f6e-496b-8335-614398c9210d.root', + '/store/relval/CMSSW_11_3_0_pre6/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/00000/058bd134-86de-47e1-bcde-379ed9b79e1b.root', + '/store/relval/CMSSW_11_3_0_pre6/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/00000/0915d66c-cbd4-4ef6-9971-7dd59e198b56.root', + '/store/relval/CMSSW_11_3_0_pre6/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/00000/09823c8d-e443-4066-8347-8c704929cb2b.root', + '/store/relval/CMSSW_11_3_0_pre6/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/00000/0c39a1aa-93ee-41c1-8543-6d90c09114a7.root', + '/store/relval/CMSSW_11_3_0_pre6/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/00000/0fcdcc53-fb9f-4f0b-8529-a4d60d914c14.root', + '/store/relval/CMSSW_11_3_0_pre6/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/00000/16760a5c-9cd2-41c3-82e5-399bb962d537.root', + '/store/relval/CMSSW_11_3_0_pre6/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/00000/1752640f-2001-4d14-9276-063ec07cea92.root', + '/store/relval/CMSSW_11_3_0_pre6/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/00000/180712c9-31a5-4f2a-bf92-a7fbee4dabad.root' +] options.register( 'inputMC', Samples, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.string, "Files to be processed" ) # specify number of events to process. options.register( 'Events',100,VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.int, "Number of Events to analyze" ) diff --git a/L1Trigger/TrackerTFP/BuildFile.xml b/L1Trigger/TrackerTFP/BuildFile.xml new file mode 100644 index 0000000000000..0b4c18bf51c15 --- /dev/null +++ b/L1Trigger/TrackerTFP/BuildFile.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/L1Trigger/TrackerTFP/README.md b/L1Trigger/TrackerTFP/README.md new file mode 100644 index 0000000000000..434b589553b04 --- /dev/null +++ b/L1Trigger/TrackerTFP/README.md @@ -0,0 +1,28 @@ +This directory contains L1 tracking code used by the TMTT & Hybrid algorithms. + +=== Run Instructions === + + cmsRun L1Trigger/TrackerTFP/test/test_cfg.py Events= + +runs the clock and bit accurate emulation of the TMTT chain. In the run script one may want to change the used event files or tracker geometry. The option CheckHistory in L1Trigger/TrackerTFP/python/Producer_cfi.py is set to false by default but is highly recommended to be set to true if one runs the emulator. This will automatically test if the configuration of the emulation run is consistent with the configuration of the input evevnt production and points out for example if one chooses a different tracker geometry. + +Apart from producing TTTrack collection as the f/w will, test_cfg.py analyses the results. It provides a end-of-job summary, which reports data rates and tracking efficiencies at the end of each processing step. The definition of which Tracking Particles are taken into account for this efficiency measurements are described here: L1Trigger/TrackTrigger/python/ProducerSetup_cfi.py in the PSet TrackTrigger_params.TrackingParticle. The "maximal possible tracking efficiency" reported for tracking steps part way through the chain is derived assuming zero efficiency loss in subsequent steps. This method allows to assess which processing steps cause most inefficiency. Additionally a "lost tracking efficiency" is reported, which is the loss due to truncation as a result of bottlenecks in the data throughput of the implemented design. Beside this end job summary test_cfg.py produces Hist.root which contains histograms with more details like efficiencies over certain tracking particle parameter. + + cmsRun L1Trigger/TrackerTFP/test/demonstrator_cfg.py Events= + +runs the clock-and-bit-accurate emulation of the TMTT chain, calls questasim to simulate the f/w and compares the results of both. A single bit error interrupts the run. This script is used to validate the clock and bit accurate emulation code. In L1Trigger/TrackerTFP/python/Demonstrator_cfi.py one has to specify the input and output stage of the chain one wants to test, the location where the IPBB (https://ipbus.web.cern.ch/doc/user/html/firmware/ipbb-primer.html) project is located and the runtime of the f/w simulator. Additionally one needs to ensure that the system variable PATH contains the questasim executables. + +=== Configuration === + +All configuration params to manipulate the algorithms one may want to play with can be found in L1Trigger/TrackTrigger/python/ProducerSetup_cfi.py which is also be used by L1Trigger/TrackerDTC/, which emulates the DTC, (which is bit-accurate but not clock-accurate (since one would need to interfere events which is not possible with EDProducer)). + +=== Code structure === + +There are 6 TMTT algorithm steps: GP (Geometric Process), HT (Hough Transform), MHT (Mini Hough Transform), ZHT (r-z Hough Transform), KF (Kalman Filter), DR (Duplicate Removal). Each comes with one EDProducer, one EDAnalyzer and one class which contains the actual emulation of this step for one nonant (1/9 phi slice of outer tracker). Their EDProducts combine the connection to MCTruth (and does not conatain MCTruth) via edm::Refs of either TTStubs or TTTracks with the actual bits used in h/w via std::bitset<64> using a std::pair of those objects. +The track-finding firmware is described in a highly parallel fashion. On the one hand, one has multiple worker nodes for each step and on the other hand is the process pipelined in a way to receive potentially one product per clock tick. This parallelism is reflected by a two dimensional vector of the earlier mentioned pairs. The inner vector describes the output (also called Frame) of one working node per clock tick. If the f/w produces no valid product in a given clock tick, then the bitset will be all '0' and the edm:ref will be null. Valid products do not necessarily form a contiguous block of valid products. The outer vector will have one entry per worker node (also called channel) where all nodes for the whole tracker are counted. Each EDProducer will produce two branches: Accepted Track or Stub and Lost Track or Stub. The Lost branch contains the Tracks or Stubs which are lost since they got not processed in time. Since the KF uses Tracks and Stubs as input the EDProducer ProducerZHTout is used to form TTTracks after the ZHT and ProducerKFin to create the edm::ref to this TTTracks. Finally ProducerTT takes the h/w liked structured output from the KF and produces one collection of TTTracks and ProducerAS creates a map between KF input TTracks to KF output TTTracks. + +There are 5 additional classes in L1Trigger/TrackerTFP. DataFormats describes Stubs and Tracks for each process step and automates the conversion from floating points to bits as used in h/w and vice versa. Demonstrator allows one to compare s/w with f/w. KalmanFilterFormats describes the used precisions in the Kalman Filter. LayerEncoding allows one to transform the layer encoding used before the KF into the encoding after KF. State is a helper class to simplify the KalmanFilter code. + +In order to simplify the conversion of floating point values into arbitrary long (within 64 bit) binary or twos-complement number, the class DataFormats/L1TrackTrigger/interface/TTBV.h has been created. + +In order to simplify the tracking efficiency measurement the class StubAssociator in SimTracker/TrackTriggerAssociation/ has been created. diff --git a/L1Trigger/TrackerTFP/interface/DataFormats.h b/L1Trigger/TrackerTFP/interface/DataFormats.h new file mode 100644 index 0000000000000..5e983db881436 --- /dev/null +++ b/L1Trigger/TrackerTFP/interface/DataFormats.h @@ -0,0 +1,1058 @@ +#ifndef L1Trigger_TrackerTFP_DataFormats_h +#define L1Trigger_TrackerTFP_DataFormats_h + +/*---------------------------------------------------------------------- +Classes to calculate and provide dataformats used by Track Trigger emulator +enabling automated conversions from frames to stubs/tracks and vice versa +In data members of classes Stub* & Track* below, the variables describing +stubs/tracks are stored both in digitial format as a 64b word in frame_, +and in undigitized format in an std::tuple. (This saves CPU) +----------------------------------------------------------------------*/ + +#include "FWCore/Framework/interface/data_default_record_trait.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "L1Trigger/TrackerTFP/interface/DataFormatsRcd.h" +#include "L1Trigger/TrackTrigger/interface/Setup.h" +#include "DataFormats/L1TrackTrigger/interface/TTBV.h" + +#include +#include +#include +#include +#include +#include + +namespace trackerTFP { + + // track trigger processes + enum class Process { begin, fe = begin, dtc, pp, gp, ht, mht, zht, kfin, kf, dr, end, x }; + // track trigger variables + enum class Variable { + begin, + r = begin, + phi, + z, + layer, + sectorsPhi, + sectorEta, + sectorPhi, + phiT, + inv2R, + zT, + cot, + dPhi, + dZ, + match, + hitPattern, + phi0, + z0, + end, + x + }; + // track trigger process order + constexpr std::initializer_list Processes = {Process::fe, + Process::dtc, + Process::pp, + Process::gp, + Process::ht, + Process::mht, + Process::zht, + Process::kfin, + Process::kf, + Process::dr}; + // conversion: Process to int + inline constexpr int operator+(Process p) { return static_cast(p); } + // conversion: Variable to int + inline constexpr int operator+(Variable v) { return static_cast(v); } + // increment of Process + inline constexpr Process operator++(Process p) { return Process(+p + 1); } + // increment of Variable + inline constexpr Variable operator++(Variable v) { return Variable(+v + 1); } + + //Base class representing format of a variable + class DataFormat { + public: + DataFormat(bool twos) : twos_(twos), width_(0), base_(1.), range_(0.) {} + ~DataFormat() {} + // converts int to bitvector + TTBV ttBV(int i) const { return TTBV(i, width_, twos_); } + // converts double to bitvector + TTBV ttBV(double d) const { return TTBV(d, base_, width_, twos_); } + // extracts int from bitvector, removing these bits from bitvector + void extract(TTBV& in, int& out) const { out = in.extract(width_, twos_); } + // extracts double from bitvector, removing these bits from bitvector + void extract(TTBV& in, double& out) const { out = in.extract(base_, width_, twos_); } + // extracts double from bitvector, removing these bits from bitvector + void extract(TTBV& in, TTBV& out) const { out = in.slice(width_, twos_); } + // attaches integer to bitvector + void attach(const int i, TTBV& ttBV) const { ttBV += TTBV(i, width_, twos_); } + // attaches double to bitvector + void attach(const double d, TTBV& ttBV) const { ttBV += TTBV(d, base_, width_, twos_); } + // attaches bitvector to bitvector + void attach(const TTBV bv, TTBV& ttBV) const { ttBV += bv; } + // converts int to double + double floating(int i) const { return (i + .5) * base_; } + // converts double to int + int integer(double d) const { return std::floor(d / base_ + 1.e-12); } + // converts double to int and back to double + double digi(double d) const { return floating(integer(d)); } + // converts binary integer value to twos complement integer value + int toSigned(int i) const { return i - std::pow(2, width_) / 2; } + // converts twos complement integer value to binary integer value + int toUnsigned(int i) const { return i + std::pow(2, width_) / 2; } + // converts floating point value to binary integer value + int toUnsigned(double d) const { return this->integer(d) + std::pow(2, width_) / 2; } + // returns false if data format would oferflow for this double value + bool inRange(double d, bool digi = false) const { + const double range = digi ? base_ * pow(2, width_) : range_; + return d >= -range / 2. && d < range / 2.; + } + // returns false if data format would oferflow for this int value + bool inRange(int i) const { return inRange(floating(i)); } + // true if twos'complement or false if binary representation is chosen + bool twos() const { return twos_; } + // number of used bits + int width() const { return width_; } + // precision + double base() const { return base_; } + // covered range + double range() const { return range_; } + + protected: + // true if twos'complement or false if binary representation is chosen + bool twos_; + // number of used bits + int width_; + // precision + double base_; + // covered range + double range_; + }; + + // class representing format of a specific variable + template + class Format : public DataFormat { + public: + Format(const edm::ParameterSet& iConfig, const tt::Setup* setup); + ~Format() {} + }; + + template <> + Format::Format(const edm::ParameterSet& iConfig, const tt::Setup* setup); + template <> + Format::Format(const edm::ParameterSet& iConfig, const tt::Setup* setup); + template <> + Format::Format(const edm::ParameterSet& iConfig, const tt::Setup* setup); + template <> + Format::Format(const edm::ParameterSet& iConfig, const tt::Setup* setup); + template <> + Format::Format(const edm::ParameterSet& iConfig, const tt::Setup* setup); + template <> + Format::Format(const edm::ParameterSet& iConfig, const tt::Setup* setup); + template <> + Format::Format(const edm::ParameterSet& iConfig, const tt::Setup* setup); + template <> + Format::Format(const edm::ParameterSet& iConfig, const tt::Setup* setup); + template <> + Format::Format(const edm::ParameterSet& iConfig, const tt::Setup* setup); + template <> + Format::Format(const edm::ParameterSet& iConfig, const tt::Setup* setup); + template <> + Format::Format(const edm::ParameterSet& iConfig, const tt::Setup* setup); + template <> + Format::Format(const edm::ParameterSet& iConfig, const tt::Setup* setup); + template <> + Format::Format(const edm::ParameterSet& iConfig, const tt::Setup* setup); + template <> + Format::Format(const edm::ParameterSet& iConfig, const tt::Setup* setup); + template <> + Format::Format(const edm::ParameterSet& iConfig, const tt::Setup* setup); + template <> + Format::Format(const edm::ParameterSet& iConfig, const tt::Setup* setup); + template <> + Format::Format(const edm::ParameterSet& iConfig, const tt::Setup* setup); + template <> + Format::Format(const edm::ParameterSet& iConfig, const tt::Setup* setup); + template <> + Format::Format(const edm::ParameterSet& iConfig, const tt::Setup* setup); + template <> + Format::Format(const edm::ParameterSet& iConfig, const tt::Setup* setup); + template <> + Format::Format(const edm::ParameterSet& iConfig, const tt::Setup* setup); + template <> + Format::Format(const edm::ParameterSet& iConfig, const tt::Setup* setup); + template <> + Format::Format(const edm::ParameterSet& iConfig, const tt::Setup* setup); + template <> + Format::Format(const edm::ParameterSet& iConfig, const tt::Setup* setup); + template <> + Format::Format(const edm::ParameterSet& iConfig, const tt::Setup* setup); + template <> + Format::Format(const edm::ParameterSet& iConfig, const tt::Setup* setup); + template <> + Format::Format(const edm::ParameterSet& iConfig, const tt::Setup* setup); + template <> + Format::Format(const edm::ParameterSet& iConfig, const tt::Setup* setup); + template <> + Format::Format(const edm::ParameterSet& iConfig, const tt::Setup* setup); + template <> + Format::Format(const edm::ParameterSet& iConfig, const tt::Setup* setup); + template <> + Format::Format(const edm::ParameterSet& iConfig, const tt::Setup* setup); + template <> + Format::Format(const edm::ParameterSet& iConfig, const tt::Setup* setup); + template <> + Format::Format(const edm::ParameterSet& iConfig, const tt::Setup* setup); + template <> + Format::Format(const edm::ParameterSet& iConfig, const tt::Setup* setup); + template <> + Format::Format(const edm::ParameterSet& iConfig, const tt::Setup* setup); + + /*! \class trackerTFP::DataFormats + * \brief Class to calculate and provide dataformats used by Track Trigger emulator + * \author Thomas Schuh + * \date 2020, June + */ + class DataFormats { + private: + // variable flavour mapping, Each row below declares which processing steps use the variable named in the comment at the end of the row + static constexpr std::array, +Variable::end> config_ = {{ + // Process::fe Process::dtc Process::pp Process::gp Process::ht Process::mht Process::zht Process::kfin Process::kf Process::dr + {{Process::x, + Process::ht, + Process::ht, + Process::ht, + Process::ht, + Process::ht, + Process::ht, + Process::ht, + Process::ht, + Process::x}}, // Variable::r + {{Process::x, + Process::dtc, + Process::dtc, + Process::gp, + Process::ht, + Process::mht, + Process::zht, + Process::kfin, + Process::kfin, + Process::x}}, // Variable::phi + {{Process::x, + Process::dtc, + Process::dtc, + Process::gp, + Process::gp, + Process::gp, + Process::zht, + Process::kfin, + Process::kfin, + Process::x}}, // Variable::z + {{Process::x, + Process::ht, + Process::ht, + Process::ht, + Process::ht, + Process::ht, + Process::ht, + Process::x, + Process::x, + Process::x}}, // Variable::layer + {{Process::x, + Process::dtc, + Process::dtc, + Process::x, + Process::x, + Process::x, + Process::x, + Process::x, + Process::x, + Process::x}}, // Variable::sectorsPhi + {{Process::x, + Process::gp, + Process::gp, + Process::gp, + Process::gp, + Process::gp, + Process::gp, + Process::gp, + Process::gp, + Process::x}}, // Variable::sectorEta + {{Process::x, + Process::x, + Process::x, + Process::gp, + Process::gp, + Process::gp, + Process::gp, + Process::gp, + Process::gp, + Process::x}}, // Variable::sectorPhi + {{Process::x, + Process::ht, + Process::ht, + Process::ht, + Process::ht, + Process::mht, + Process::mht, + Process::mht, + Process::kf, + Process::x}}, // Variable::phiT + {{Process::x, + Process::ht, + Process::ht, + Process::ht, + Process::ht, + Process::mht, + Process::mht, + Process::mht, + Process::kf, + Process::dr}}, // Variable::inv2R + {{Process::x, + Process::x, + Process::x, + Process::x, + Process::x, + Process::x, + Process::zht, + Process::zht, + Process::kf, + Process::x}}, // Variable::zT + {{Process::x, + Process::x, + Process::x, + Process::x, + Process::x, + Process::x, + Process::zht, + Process::zht, + Process::kf, + Process::dr}}, // Variable::cot + {{Process::x, + Process::x, + Process::x, + Process::x, + Process::x, + Process::x, + Process::x, + Process::kfin, + Process::kfin, + Process::x}}, // Variable::dPhi + {{Process::x, + Process::x, + Process::x, + Process::x, + Process::x, + Process::x, + Process::x, + Process::kfin, + Process::kfin, + Process::x}}, // Variable::dZ + {{Process::x, + Process::x, + Process::x, + Process::x, + Process::x, + Process::x, + Process::x, + Process::x, + Process::kf, + Process::x}}, // Variable::match + {{Process::x, + Process::x, + Process::x, + Process::x, + Process::x, + Process::x, + Process::x, + Process::kfin, + Process::x, + Process::x}}, // Variable::hitPattern + {{Process::x, + Process::x, + Process::x, + Process::x, + Process::x, + Process::x, + Process::x, + Process::x, + Process::x, + Process::dr}}, // Variable::phi0 + {{Process::x, + Process::x, + Process::x, + Process::x, + Process::x, + Process::x, + Process::x, + Process::x, + Process::x, + Process::dr}} // Variable::z0 + }}; + // stub word assembly, shows which stub variables are used by each process + static constexpr std::array, +Process::end> stubs_ = {{ + {}, // Process::fe + {Variable::r, + Variable::phi, + Variable::z, + Variable::layer, + Variable::sectorsPhi, + Variable::sectorEta, + Variable::sectorEta, + Variable::inv2R, + Variable::inv2R}, // Process::dtc + {Variable::r, + Variable::phi, + Variable::z, + Variable::layer, + Variable::sectorsPhi, + Variable::sectorEta, + Variable::sectorEta, + Variable::inv2R, + Variable::inv2R}, // Process::pp + {Variable::r, Variable::phi, Variable::z, Variable::layer, Variable::inv2R, Variable::inv2R}, // Process::gp + {Variable::r, + Variable::phi, + Variable::z, + Variable::layer, + Variable::sectorPhi, + Variable::sectorEta, + Variable::phiT}, // Process::ht + {Variable::r, + Variable::phi, + Variable::z, + Variable::layer, + Variable::sectorPhi, + Variable::sectorEta, + Variable::phiT, + Variable::inv2R}, // Process::mht + {Variable::r, + Variable::phi, + Variable::z, + Variable::layer, + Variable::sectorPhi, + Variable::sectorEta, + Variable::phiT, + Variable::inv2R, + Variable::zT, + Variable::cot}, // Process::zht + {Variable::r, Variable::phi, Variable::z, Variable::dPhi, Variable::dZ}, // Process::kfin + {Variable::r, Variable::phi, Variable::z, Variable::dPhi, Variable::dZ}, // Process::kf + {} // Process::dr + }}; + // track word assembly, shows which track variables are used by each process + static constexpr std::array, +Process::end> tracks_ = {{ + {}, // Process::fe + {}, // Process::dtc + {}, // Process::pp + {}, // Process::gp + {}, // Process::ht + {}, // Process::mht + {}, // Process::zht + {Variable::hitPattern, + Variable::sectorPhi, + Variable::sectorEta, + Variable::phiT, + Variable::inv2R, + Variable::zT, + Variable::cot}, // Process::kfin + {Variable::match, + Variable::sectorPhi, + Variable::sectorEta, + Variable::phiT, + Variable::inv2R, + Variable::cot, + Variable::zT}, // Process::kf + {Variable::phi0, Variable::inv2R, Variable::z0, Variable::cot} // Process::dr + }}; + + public: + DataFormats(); + DataFormats(const edm::ParameterSet& iConfig, const tt::Setup* setup); + ~DataFormats() {} + // bool indicating if hybrid or tmtt being used + bool hybrid() const { return iConfig_.getParameter("UseHybrid"); } + // converts bits to ntuple of variables + template + void convertStub(Process p, const tt::Frame& bv, std::tuple& data) const; + // converts ntuple of variables to bits + template + void convertStub(Process p, const std::tuple& data, tt::Frame& bv) const; + // converts bits to ntuple of variables + template + void convertTrack(Process p, const tt::Frame& bv, std::tuple& data) const; + // converts ntuple of variables to bits + template + void convertTrack(Process p, const std::tuple& data, tt::Frame& bv) const; + // access to run-time constants + const tt::Setup* setup() const { return setup_; } + // number of bits being used for specific variable flavour + int width(Variable v, Process p) const { return formats_[+v][+p]->width(); } + // precision being used for specific variable flavour + double base(Variable v, Process p) const { return formats_[+v][+p]->base(); } + // number of unused frame bits for a given Stub flavour + int numUnusedBitsStubs(Process p) const { return numUnusedBitsStubs_[+p]; } + // number of unused frame bits for a given Track flavour + int numUnusedBitsTracks(Process p) const { return numUnusedBitsTracks_[+p]; } + // number of channels of a given process on a TFP + int numChannel(Process p) const { return numChannel_[+p]; } + // number of channels of a given process for whole system + int numStreams(Process p) const { return numStreams_[+p]; } + // + int numStreamsStubs(Process p) const { return numStreamsStubs_[+p]; } + // + int numStreamsTracks(Process p) const { return numStreamsTracks_[+p]; } + // access to spedific format + const DataFormat& format(Variable v, Process p) const { return *formats_[+v][+p]; } + // critical radius defining region overlap shape in cm + double chosenRofPhi() const { return hybrid() ? setup_->hybridChosenRofPhi() : setup_->chosenRofPhi(); } + + private: + // number of unique data formats + int numDataFormats_; + // method to count number of unique data formats + template + void countFormats(); + // constructs data formats of all unique used variables and flavours + template + void fillDataFormats(); + // helper (loop) data formats of all unique used variables and flavours + template + void fillFormats(); + // helper (loop) to convert bits to ntuple of variables + template + void extractStub(Process p, TTBV& ttBV, std::tuple& data) const; + // helper (loop) to convert bits to ntuple of variables + template + void extractTrack(Process p, TTBV& ttBV, std::tuple& data) const; + // helper (loop) to convert ntuple of variables to bits + template + void attachStub(Process p, const std::tuple& data, TTBV& ttBV) const; + // helper (loop) to convert ntuple of variables to bits + template + void attachTrack(Process p, const std::tuple& data, TTBV& ttBV) const; + // configuration during construction + edm::ParameterSet iConfig_; + // stored run-time constants + const tt::Setup* setup_; + // collection of unique formats + std::vector dataFormats_; + // variable flavour mapping + std::vector> formats_; + // number of unused frame bits for a all Stub flavours + std::vector numUnusedBitsStubs_; + // number of unused frame bits for a all Track flavours + std::vector numUnusedBitsTracks_; + // number of channels of all processes on a TFP + std::vector numChannel_; + // number of channels of all processes for whole system + std::vector numStreams_; + // + std::vector numStreamsStubs_; + // + std::vector numStreamsTracks_; + }; + + // base class to represent stubs + template + class Stub { + public: + // construct Stub from Frame + Stub(const tt::FrameStub& frame, const DataFormats* dataFormats, Process p); + template + // construct Stub from other Stub + Stub(const Stub& stub, Ts... data); + // construct Stub from TTStubRef + Stub(const TTStubRef& ttStubRef, const DataFormats* dataFormats, Process p, Ts... data); + Stub() {} + ~Stub() {} + // true if frame valid, false if gap in data stream + explicit operator bool() const { return frame_.first.isNonnull(); } + // access to DataFormats + const DataFormats* dataFormats() const { return dataFormats_; } + // stub flavour + Process p() const { return p_; } + // acess to frame + tt::FrameStub frame() const { return frame_; } + // access to TTStubRef + TTStubRef ttStubRef() const { return frame_.first; } + // access to bitvector + tt::Frame bv() const { return frame_.second; } + // id of collection this stub belongs to + int trackId() const { return trackId_; } + + protected: + // number of used bits for given variable + int width(Variable v) const { return dataFormats_->width(v, p_); } + // precision of given variable + double base(Variable v) const { return dataFormats_->base(v, p_); } + // format of given variable + DataFormat format(Variable v) const { return dataFormats_->format(v, p_); } + // all dataformats + const DataFormats* dataFormats_; + // stub flavour + Process p_; + // underlying TTStubRef and bitvector + tt::FrameStub frame_; + // ntuple of variables this stub is assemled of + std::tuple data_; + // id of collection this stub belongs to + int trackId_; + }; + + // class to represent stubs generated by process patch pannel + class StubPP : public Stub { + public: + // construct StubPP from Frame + StubPP(const tt::FrameStub& frame, const DataFormats* dataFormats); + ~StubPP() {} + // true if stub belongs to given sector + bool inSector(int sector) const { return sectors_[sector]; } + // sectors this stub belongs to + std::vector sectors() const { return sectors_.ids(); } + // stub radius wrt chosenRofPhi + double r() const { return std::get<0>(data_); } + // stub phi wrt processing nonant centre + double phi() const { return std::get<1>(data_); } + // stub z + double z() const { return std::get<2>(data_); } + // reduced layer id + int layer() const { return std::get<3>(data_); } + // phi sector map to which this stub belongs to + TTBV sectorsPhi() const { return std::get<4>(data_); } + // first eta sector this stub belongs to + int sectorEtaMin() const { return std::get<5>(data_); } + // last eta sector this stub belongs to + int sectorEtaMax() const { return std::get<6>(data_); } + // first inv2R bin this stub belongs to + int inv2RMin() const { return std::get<7>(data_); } + // last inv2R bin this stub belongs to + int inv2RMax() const { return std::get<8>(data_); } + + private: + // sectors this stub belongs to + TTBV sectors_; + }; + + // class to represent stubs generated by process geometric processor + class StubGP : public Stub { + public: + // construct StubGP from Frame + StubGP(const tt::FrameStub& frame, const DataFormats* dataFormats, int sectorPhi, int sectorEta); + // construct StubGO from StubPP + StubGP(const StubPP& stub, int sectorPhi, int sectorEta); + ~StubGP() {} + // true if stub belongs to given inv2R bin + bool inInv2RBin(int inv2RBin) const { return inv2RBins_[inv2RBin]; } + // inv2R bins this stub belongs to + std::vector inv2RBins() const { return inv2RBins_.ids(); } + // stub phi sector + int sectorPhi() const { return sectorPhi_; } + // stub eta sector + int sectorEta() const { return sectorEta_; } + // stub radius wrt chosenRofPhi + double r() const { return std::get<0>(data_); } + // stub phi wrt phi sector centre + double phi() const { return std::get<1>(data_); } + // stub z residual wrt eta sector + double z() const { return std::get<2>(data_); } + // reduced layer id + int layer() const { return std::get<3>(data_); } + // first inv2R bin this stub belongs to + int inv2RMin() const { return std::get<4>(data_); } + // last inv2R bin this stub belongs to + int inv2RMax() const { return std::get<5>(data_); } + + private: + // inv2R bins this stub belongs to + TTBV inv2RBins_; + // stub phi sector + int sectorPhi_; + // stub eta sector + int sectorEta_; + }; + + // class to represent stubs generated by process hough transform + class StubHT : public Stub { + public: + // construct StubHT from Frame + StubHT(const tt::FrameStub& frame, const DataFormats* dataFormats, int inv2R); + // construct StubHT from StubGP and HT cell assignment + StubHT(const StubGP& stub, int phiT, int inv2R); + ~StubHT() {} + // stub qOver pt + int inv2R() const { return inv2R_; } + // stub radius wrt chosenRofPhi + double r() const { return std::get<0>(data_); }; + // stub phi residual wrt track parameter + double phi() const { return std::get<1>(data_); }; + // stub z residual wrt eta sector + double z() const { return std::get<2>(data_); }; + // reduced layer id + int layer() const { return std::get<3>(data_); }; + // phi sector + int sectorPhi() const { return std::get<4>(data_); }; + // eta sector + int sectorEta() const { return std::get<5>(data_); }; + // stub phi at radius chosenRofPhi wrt phi sector centre + int phiT() const { return std::get<6>(data_); }; + + private: + // fills track id + void fillTrackId(); + // stub qOver pt + int inv2R_; + }; + + // class to represent stubs generated by process mini hough transform + class StubMHT : public Stub { + public: + // construct StubMHT from Frame + StubMHT(const tt::FrameStub& frame, const DataFormats* dataFormats); + // construct StubMHT from StubHT and MHT cell assignment + StubMHT(const StubHT& stub, int phiT, int inv2R); + ~StubMHT() {} + // stub radius wrt choenRofPhi + double r() const { return std::get<0>(data_); } + // stub phi residual wrt finer track parameter + double phi() const { return std::get<1>(data_); } + // stub z rsidual wrt eta sector + double z() const { return std::get<2>(data_); } + // reduced layer id + int layer() const { return std::get<3>(data_); } + // phi sector + int sectorPhi() const { return std::get<4>(data_); } + // eta sector + int sectorEta() const { return std::get<5>(data_); } + // stub phi at radius chosenRofPhi wrt phi sector centre + int phiT() const { return std::get<6>(data_); } + // stub inv2R + int inv2R() const { return std::get<7>(data_); } + + private: + // fills track id + void fillTrackId(); + }; + + // class to represent stubs generated by process z hough transform + class StubZHT : public Stub { + public: + // construct StubZHT from Frame + StubZHT(const tt::FrameStub& frame, const DataFormats* dataFormats); + // construct StubZHT from StubMHT + StubZHT(const StubMHT& stub); + // + StubZHT(const StubZHT& stub, double zT, double cot, int id); + // + StubZHT(const StubZHT& stub, int cot, int zT); + ~StubZHT() {} + // stub radius wrt chonseRofPhi + double r() const { return std::get<0>(data_); } + // stub phiresiudal wrt finer track parameter + double phi() const { return std::get<1>(data_); } + // stub z residual to track parameter + double z() const { return std::get<2>(data_); } + // reduced layer id + int layer() const { return std::get<3>(data_); } + // phi sector + int sectorPhi() const { return std::get<4>(data_); } + // eta sector + int sectorEta() const { return std::get<5>(data_); } + // stub phi at radius chosenRofPhi wrt phi sector centre + int phiT() const { return std::get<6>(data_); } + // stub inv2R + int inv2R() const { return std::get<7>(data_); } + // stub z at radius chosenRofZ wrt eta sector centre + int zT() const { return std::get<8>(data_); } + // stub cotTheta wrt eta sector cotTheta + int cot() const { return std::get<9>(data_); } + double cotf() const { return cot_; } + double ztf() const { return zT_; } + double chi() const { return chi_; } + + private: + // fills track id + void fillTrackId(); + double r_; + double chi_; + double cot_; + double zT_; + }; + + // class to represent stubs generated by process kfin + class StubKFin : public Stub { + public: + // construct StubKFin from Frame + StubKFin(const tt::FrameStub& frame, const DataFormats* dataFormats, int layer); + // construct StubKFin from StubZHT + StubKFin(const StubZHT& stub, double dPhi, double dZ, int layer); + // construct StubKFin from TTStubRef + StubKFin(const TTStubRef& ttStubRef, + const DataFormats* dataFormats, + double r, + double phi, + double z, + double dPhi, + double dZ, + int layer); + ~StubKFin() {} + // kf layer id + int layer() const { return layer_; } + // stub radius wrt chosenRofPhi + double r() const { return std::get<0>(data_); } + // stub phi residual wrt finer track parameter + double phi() const { return std::get<1>(data_); } + // stub z residual wrt track parameter + double z() const { return std::get<2>(data_); } + // stub phi uncertainty + double dPhi() const { return std::get<3>(data_); } + // stub z uncertainty + double dZ() const { return std::get<4>(data_); } + + private: + // kf layer id + int layer_; + }; + + // class to represent stubs generated by process kalman filter + class StubKF : public Stub { + public: + // construct StubKF from Frame + StubKF(const tt::FrameStub& frame, const DataFormats* dataFormats, int layer); + // construct StubKF from StubKFin + StubKF(const StubKFin& stub, double inv2R, double phiT, double cot, double zT); + ~StubKF() {} + // kf layer id + int layer() const { return layer_; } + // stub radius wrt choenRofPhi + double r() const { return std::get<0>(data_); } + // stub phi residual wrt fitted parameter + double phi() const { return std::get<1>(data_); } + // stub z residual wrt fitted parameter + double z() const { return std::get<2>(data_); } + // stub phi uncertainty + double dPhi() const { return std::get<3>(data_); } + // stub z uncertainty + double dZ() const { return std::get<4>(data_); } + + private: + // kf layer id + int layer_; + }; + + // base class to represent tracks + template + class Track { + public: + // construct Track from Frame + Track(const tt::FrameTrack& frame, const DataFormats* dataFormats, Process p); + // construct Track from other Track + template + Track(const Track& track, Ts... data); + // construct Track from Stub + template + Track(const Stub& stub, const TTTrackRef& ttTrackRef, Ts... data); + // construct Track from TTTrackRef + Track(const TTTrackRef& ttTrackRef, const DataFormats* dataFormats, Process p, Ts... data); + ~Track() {} + // true if frame valid, false if gap in data stream + explicit operator bool() const { return frame_.first.isNonnull(); } + // access to DataFormats + const DataFormats* dataFormats() const { return dataFormats_; } + // track flavour + Process p() const { return p_; } + // acces to frame + tt::FrameTrack frame() const { return frame_; } + // access to TTTrackRef + TTTrackRef ttTrackRef() const { return frame_.first; } + // access to bitvector + tt::Frame bv() const { return frame_.second; } + // access to ntuple of variables this track is assemled of + std::tuple data() const { return data_; } + + protected: + //number of bits uesd of given variable + int width(Variable v) const { return dataFormats_->width(v, p_); } + // precision of given variable + double base(Variable v) const { return dataFormats_->base(v, p_); } + // access to run-time constants + const tt::Setup* setup() const { return dataFormats_->setup(); } + // format of given variable + DataFormat format(Variable v) const { return dataFormats_->format(v, p_); } + // format of given variable and process + DataFormat format(Variable v, Process p) const { return dataFormats_->format(v, p); } + // all data formats + const DataFormats* dataFormats_; + // track flavour + Process p_; + // underlying TTTrackRef and bitvector + tt::FrameTrack frame_; + // ntuple of variables this track is assemled of + std::tuple data_; + }; + + class TrackKFin : public Track { + public: + // construct TrackKFin from Frame + TrackKFin(const tt::FrameTrack& frame, const DataFormats* dataFormats, const std::vector& stubs); + // construct TrackKFin from StubKFin + TrackKFin(const StubZHT& stub, const TTTrackRef& ttTrackRef, const TTBV& maybePattern); + // construct TrackKFin from TTTrackRef + TrackKFin(const TTTrackRef& ttTrackRef, + const DataFormats* dataFormats, + const TTBV& maybePattern, + double phiT, + double qOverPt, + double zT, + double cot, + int sectorPhi, + int sectorEta); + ~TrackKFin() {} + // pattern of layers which are only maybe crossed by found candidate + const TTBV& maybePattern() const { return std::get<0>(data_); } + // phi sector + int sectorPhi() const { return std::get<1>(data_); } + // eta sector + int sectorEta() const { return std::get<2>(data_); } + // track phi at radius chosenRofPhi wrt phi sector centre + double phiT() const { return std::get<3>(data_); } + // track inv2R + double inv2R() const { return std::get<4>(data_); } + // track z at radius chosenRofZ wrt eta sector centre + double zT() const { return std::get<5>(data_); } + // track cotTheta wrt seta sector cotTheta + double cot() const { return std::get<6>(data_); } + // + TTBV hitPattern() const { return hitPattern_; } + // true if given layer has a hit + bool hitPattern(int index) const { return hitPattern_[index]; } + // true if given layer has a hit or is a maybe layer + bool maybePattern(int index) const { return hitPattern_[index] || maybePattern()[index]; } + // stubs on a given layer + std::vector layerStubs(int layer) const { return stubs_[layer]; } + // firts stub on a given layer + StubKFin* layerStub(int layer) const { return stubs_[layer].front(); } + // selection of ttStubRefs for given hit ids on given layers + std::vector ttStubRefs(const TTBV& hitPattern, const std::vector& layerMap) const; + // stubs organized in layer + std::vector> stubs() const { return stubs_; } + // global cotTheta + double cotGlobal() const { return cot() + setup()->sectorCot(sectorEta()); } + + private: + // stubs organized in layer + std::vector> stubs_; + // + TTBV hitPattern_; + }; + + // class to represent tracks generated by process kalman filter + class TrackKF : public Track { + public: + // construct TrackKF from Frame + TrackKF(const tt::FrameTrack& frame, const DataFormats* dataFormats); + // construct TrackKF from TrackKFKFin + TrackKF(const TrackKFin& track, double phiT, double inv2R, double zT, double cot); + ~TrackKF() {} + // true if kf prameter consistent with mht parameter + bool match() const { return std::get<0>(data_); } + // phi sector + int sectorPhi() const { return std::get<1>(data_); } + // eta sector + int sectorEta() const { return std::get<2>(data_); } + // track phi at radius chosenRofPhi wrt phi sector centre + double phiT() const { return std::get<3>(data_); } + // track qOver pt + double inv2R() const { return std::get<4>(data_); } + // track cotTheta wrt eta sector cotTheta + double cot() const { return std::get<5>(data_); } + // track z at radius chosenRofZ wrt eta sector centre + double zT() const { return std::get<6>(data_); } + // global cotTheta + double cotGlobal() const { return cot() + setup()->sectorCot(sectorEta()); } + // conversion to TTTrack with given stubs + TTTrack ttTrack(const std::vector& stubs) const; + + private: + }; + + //Class to represent KFout 96-bit track for use in distribution server + class TrackKFOut { + public: + TrackKFOut() : TrackKFOut(0, 0, 0, 0, tt::FrameTrack(), 0, 0, false) {} + // construct TrackKF from Partial Tracks + TrackKFOut(TTBV PartialTrack1, + TTBV PartialTrack2, + TTBV PartialTrack3, + int sortKey, + const tt::FrameTrack& track, + int trackID, + int linkID, + bool valid) + : PartialTrack1_(PartialTrack1), + PartialTrack2_(PartialTrack2), + PartialTrack3_(PartialTrack3), + sortKey_(sortKey), + track_(track), + trackID_(trackID), + linkID_(linkID), + valid_(valid){}; + + ~TrackKFOut() {} + + int sortKey() const { return sortKey_; } + + bool dataValid() const { return valid_; } + + int trackID() const { return trackID_; } + int linkID() const { return linkID_; } + + TTBV PartialTrack1() const { return PartialTrack1_; } + TTBV PartialTrack2() const { return PartialTrack2_; } + TTBV PartialTrack3() const { return PartialTrack3_; } + + tt::FrameTrack track() const { return track_; } + + private: + TTBV PartialTrack1_; + TTBV PartialTrack2_; + TTBV PartialTrack3_; + int sortKey_; + tt::FrameTrack track_; + int trackID_; + int linkID_; + bool valid_; + }; + + typedef std::vector TrackKFOutSACollection; + typedef std::shared_ptr TrackKFOutSAPtr; + typedef std::vector TrackKFOutSAPtrCollection; + typedef std::vector>> TrackKFOutSAPtrCollections; + typedef std::vector>>> TrackKFOutSAPtrCollectionss; + // class to represent tracks generated by process duplicate removal + class TrackDR : public Track { + public: + // construct TrackDR from Frame + TrackDR(const tt::FrameTrack& frame, const DataFormats* dataFormats); + // construct TrackDR from TrackKF + TrackDR(const TrackKF& track); + ~TrackDR() {} + // track phi at radius 0 wrt processing nonant centre + double phi0() const { return std::get<0>(data_); } + // track inv2R + double inv2R() const { return std::get<1>(data_); } + // track z at radius 0 + double z0() const { return std::get<2>(data_); } + // track cotThea + double cot() const { return std::get<3>(data_); } + // conversion to TTTrack + TTTrack ttTrack() const; + + private: + }; + +} // namespace trackerTFP + +EVENTSETUP_DATA_DEFAULT_RECORD(trackerTFP::DataFormats, trackerTFP::DataFormatsRcd); + +#endif \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/interface/DataFormatsRcd.h b/L1Trigger/TrackerTFP/interface/DataFormatsRcd.h new file mode 100644 index 0000000000000..163d86c89da15 --- /dev/null +++ b/L1Trigger/TrackerTFP/interface/DataFormatsRcd.h @@ -0,0 +1,17 @@ +#ifndef L1Trigger_TrackerTFP_DataFormatsRcd_h +#define L1Trigger_TrackerTFP_DataFormatsRcd_h + +#include "FWCore/Framework/interface/DependentRecordImplementation.h" +#include "L1Trigger/TrackTrigger/interface/SetupRcd.h" +#include "FWCore/Utilities/interface/mplVector.h" + +namespace trackerTFP { + + typedef edm::mpl::Vector RcdsDataFormats; + + // record of trackerTFP::DataFormats + class DataFormatsRcd : public edm::eventsetup::DependentRecordImplementation {}; + +} // namespace trackerTFP + +#endif \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/interface/Demonstrator.h b/L1Trigger/TrackerTFP/interface/Demonstrator.h new file mode 100644 index 0000000000000..73799b10816fd --- /dev/null +++ b/L1Trigger/TrackerTFP/interface/Demonstrator.h @@ -0,0 +1,68 @@ +#ifndef L1Trigger_TrackerTFP_Demonstrator_h +#define L1Trigger_TrackerTFP_Demonstrator_h + +#include "FWCore/Framework/interface/data_default_record_trait.h" +#include "L1Trigger/TrackerTFP/interface/DemonstratorRcd.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "L1Trigger/TrackTrigger/interface/Setup.h" + +#include +#include + +namespace trackerTFP { + + /*! \class trackerTFP::Demonstrator + * \brief Compares emulator with f/w + * \author Thomas Schuh + * \date 2021, April + */ + class Demonstrator { + public: + Demonstrator() {} + Demonstrator(const edm::ParameterSet& iConfig, const tt::Setup* setup); + ~Demonstrator() {} + // plays input through modelsim and compares result with output + bool analyze(const std::vector>& input, + const std::vector>& output) const; + + private: + // converts streams of bv into stringstream + void convert(const std::vector>& bits, std::stringstream& ss) const; + // plays stringstream through modelsim + void sim(const std::stringstream& ss) const; + // compares stringstream with modelsim output + bool compare(std::stringstream& ss) const; + // creates emp file header + std::string header(int numChannel) const; + // creates 6 frame gap between packets + std::string infraGap(int& nFrame, int numChannel) const; + // creates frame number + std::string frame(int& nFrame) const; + // converts bv into hex + std::string hex(const tt::Frame& bv) const; + + // path to ipbb proj area + std::string dirIPBB_; + // runtime in ms + double runTime_; + // path to input text file + std::string dirIn_; + // path to output text file + std::string dirOut_; + // path to expected output text file + std::string dirPre_; + // path to diff text file + std::string dirDiff_; + // number of frames per event (161) + int numFrames_; + // number of emp reset frames per event (6) + int numFramesInfra_; + // number of TFPs per time node (9) + int numRegions_; + }; + +} // namespace trackerTFP + +EVENTSETUP_DATA_DEFAULT_RECORD(trackerTFP::Demonstrator, trackerTFP::DemonstratorRcd); + +#endif \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/interface/DemonstratorRcd.h b/L1Trigger/TrackerTFP/interface/DemonstratorRcd.h new file mode 100644 index 0000000000000..929d3706ac6f9 --- /dev/null +++ b/L1Trigger/TrackerTFP/interface/DemonstratorRcd.h @@ -0,0 +1,17 @@ +#ifndef L1Trigger_TrackerTFP_DemonstratorRcd_h +#define L1Trigger_TrackerTFP_DemonstratorRcd_h + +#include "FWCore/Framework/interface/DependentRecordImplementation.h" +#include "L1Trigger/TrackTrigger/interface/SetupRcd.h" +#include "FWCore/Utilities/interface/mplVector.h" + +namespace trackerTFP { + + typedef edm::mpl::Vector RcdsDemonstrator; + + // record of trackerTFP::Demonstrator + class DemonstratorRcd : public edm::eventsetup::DependentRecordImplementation {}; + +} // namespace trackerTFP + +#endif \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/interface/DistServer.h b/L1Trigger/TrackerTFP/interface/DistServer.h new file mode 100644 index 0000000000000..5c093ab796b06 --- /dev/null +++ b/L1Trigger/TrackerTFP/interface/DistServer.h @@ -0,0 +1,33 @@ +#ifndef L1Trigger_TrackerTFP_DistServer_h__ +#define L1Trigger_TrackerTFP_DistServer_h__ + +#include "L1Trigger/TrackerTFP/interface/DataFormats.h" + +#include + +namespace trackerTFP { + + class DistServer { + public: + DistServer(unsigned int nInputs, unsigned int nOutputs, unsigned int nInterleaving); + ~DistServer() {} + + TrackKFOutSAPtrCollection clock(TrackKFOutSAPtrCollection& inputs); + + unsigned int nInputs() const { return nInputs_; } + unsigned int nOutputs() const { return nOutputs_; } + unsigned int nInterleaving() const { return nInterleaving_; } + std::vector >& addr() { return addr_; } + TrackKFOutSAPtrCollections& inputs() { return inputs_; } + + private: + unsigned int nInputs_; + unsigned int nOutputs_; + unsigned int nInterleaving_; + + TrackKFOutSAPtrCollections inputs_; + std::vector > addr_; + }; +} // namespace trackerTFP + +#endif \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/interface/GeometricProcessor.h b/L1Trigger/TrackerTFP/interface/GeometricProcessor.h new file mode 100644 index 0000000000000..0cf1279c64bea --- /dev/null +++ b/L1Trigger/TrackerTFP/interface/GeometricProcessor.h @@ -0,0 +1,50 @@ +#ifndef L1Trigger_TrackerTFP_GeometricProcessor_h +#define L1Trigger_TrackerTFP_GeometricProcessor_h + +#include "L1Trigger/TrackTrigger/interface/Setup.h" +#include "L1Trigger/TrackerTFP/interface/DataFormats.h" +#include "DataFormats/L1TrackTrigger/interface/TTDTC.h" + +#include +#include + +namespace trackerTFP { + + // Class to route Stubs of one region to one stream per sector + class GeometricProcessor { + public: + GeometricProcessor(const edm::ParameterSet& iConfig, + const tt::Setup* setup_, + const DataFormats* dataFormats, + int region); + ~GeometricProcessor() {} + + // read in and organize input product (fill vector input_) + void consume(const TTDTC& ttDTC); + // fill output products + void produce(tt::StreamsStub& accepted, tt::StreamsStub& lost); + + private: + // remove and return first element of deque, returns nullptr if empty + template + T* pop_front(std::deque& ts) const; + + // true if truncation is enbaled + bool enableTruncation_; + // provides run-time constants + const tt::Setup* setup_; + // provides dataformats + const DataFormats* dataFormats_; + // processing region (0 - 8) + const int region_; + // storage of input stubs + std::vector stubsPP_; + // storage of output stubs + std::vector stubsGP_; + // h/w liked organized pointer to input stubs + std::vector>> input_; + }; + +} // namespace trackerTFP + +#endif \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/interface/HoughTransform.h b/L1Trigger/TrackerTFP/interface/HoughTransform.h new file mode 100644 index 0000000000000..50ab325782f3d --- /dev/null +++ b/L1Trigger/TrackerTFP/interface/HoughTransform.h @@ -0,0 +1,66 @@ +#ifndef L1Trigger_TrackerTFP_HoughTransform_h +#define L1Trigger_TrackerTFP_HoughTransform_h + +#include "L1Trigger/TrackTrigger/interface/Setup.h" +#include "L1Trigger/TrackerTFP/interface/DataFormats.h" +#include "DataFormats/L1TrackTrigger/interface/TTTypes.h" + +#include +#include +#include + +namespace trackerTFP { + + // Class to find initial rough candidates in r-phi in a region + class HoughTransform { + public: + HoughTransform(const edm::ParameterSet& iConfig, const tt::Setup* setup, const DataFormats* dataFormats, int region); + ~HoughTransform() {} + + // read in and organize input product + void consume(const tt::StreamsStub& streams); + // fill output products + void produce(tt::StreamsStub& accepted, tt::StreamsStub& lost); + + private: + // remove and return first element of deque, returns nullptr if empty + template + T* pop_front(std::deque& ts) const; + // associate stubs with phiT bins in this inv2R column + void fillIn(int inv2R, + std::deque& inputSector, + std::vector& acceptedSector, + std::vector& lostSector); + // identify tracks + void readOut(const std::vector& acceptedSector, + const std::vector& lostSector, + std::deque& acceptedAll, + std::deque& lostAll) const; + // identify lost tracks + void analyze(); + // store tracks + void put() const; + + // true if truncation is enbaled + bool enableTruncation_; + // provides run-time constants + const tt::Setup* setup_; + // provides dataformats + const DataFormats* dataFormats_; + // data format of inv2R + DataFormat inv2R_; + // data format of phiT + DataFormat phiT_; + // processing region (0 - 8) + int region_; + // container of input stubs + std::vector stubsGP_; + // container of output stubs + std::vector stubsHT_; + // h/w liked organized pointer to input stubs + std::vector>> input_; + }; + +} // namespace trackerTFP + +#endif \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/interface/KalmanFilter.h b/L1Trigger/TrackerTFP/interface/KalmanFilter.h new file mode 100644 index 0000000000000..535677b01e535 --- /dev/null +++ b/L1Trigger/TrackerTFP/interface/KalmanFilter.h @@ -0,0 +1,114 @@ +#ifndef L1Trigger_TrackerTFP_KalmanFilter_h +#define L1Trigger_TrackerTFP_KalmanFilter_h + +#include "L1Trigger/TrackTrigger/interface/Setup.h" +#include "L1Trigger/TrackerTFP/interface/DataFormats.h" +#include "L1Trigger/TrackerTFP/interface/KalmanFilterFormats.h" +#include "L1Trigger/TrackerTFP/interface/State.h" +#include "DataFormats/L1TrackTrigger/interface/TTTypes.h" + +#include + +namespace trackerTFP { + + // Class to do helix fit to all tracks in a region. + class KalmanFilter { + public: + KalmanFilter(const edm::ParameterSet& iConfig, + const tt::Setup* setup, + const DataFormats* dataFormats, + KalmanFilterFormats* kalmanFilterFormats, + int region); + ~KalmanFilter() {} + + // read in and organize input tracks and stubs + void consume(const tt::StreamsTrack& streamsTrack, const tt::StreamsStub& streamsStub); + // fill output products + void produce(tt::StreamsStub& accpetedStubs, + tt::StreamsTrack& acceptedTracks, + tt::StreamsStub& lostStubs, + tt::StreamsTrack& lostTracks, + int& numAcceptedStates, + int& numLostStates); + + private: + // remove and return first element of deque, returns nullptr if empty + template + T* pop_front(std::deque& ts) const; + // remove and return first element of vector, returns nullptr if empty + template + T* pop_front(std::vector& ts) const; + + // adds a layer to states + void addLayer(std::deque& stream); + // Assign next combinatoric (i.e. not first in layer) stub to state + void comb(State*& state); + // best state selection + void accumulator(std::deque& stream); + // updates state + void update(State*& state); + + // true if truncation is enbaled + bool enableTruncation_; + // provides run-time constants + const tt::Setup* setup_; + // provides dataformats + const DataFormats* dataFormats_; + // provides dataformats of Kalman filter internals + KalmanFilterFormats* kalmanFilterFormats_; + // processing region (0 - 8) + int region_; + // container of input stubs + std::vector stubs_; + // container of input tracks + std::vector tracks_; + // container of all Kalman Filter states + std::deque states_; + // h/w liked organized pointer to input stubs + std::vector> input_; + // current layer used during state propagation + int layer_; + + // dataformats of Kalman filter internals + + DataFormatKF* x0_; + DataFormatKF* x1_; + DataFormatKF* x2_; + DataFormatKF* x3_; + DataFormatKF* H00_; + DataFormatKF* H12_; + DataFormatKF* m0_; + DataFormatKF* m1_; + DataFormatKF* v0_; + DataFormatKF* v1_; + DataFormatKF* r0_; + DataFormatKF* r1_; + DataFormatKF* S00_; + DataFormatKF* S01_; + DataFormatKF* S12_; + DataFormatKF* S13_; + DataFormatKF* K00_; + DataFormatKF* K10_; + DataFormatKF* K21_; + DataFormatKF* K31_; + DataFormatKF* R00_; + DataFormatKF* R11_; + DataFormatKF* R00Rough_; + DataFormatKF* R11Rough_; + DataFormatKF* invR00Approx_; + DataFormatKF* invR11Approx_; + DataFormatKF* invR00Cor_; + DataFormatKF* invR11Cor_; + DataFormatKF* invR00_; + DataFormatKF* invR11_; + DataFormatKF* C00_; + DataFormatKF* C01_; + DataFormatKF* C11_; + DataFormatKF* C22_; + DataFormatKF* C23_; + DataFormatKF* C33_; + }; + +} // namespace trackerTFP + +#endif \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/interface/KalmanFilterFormats.h b/L1Trigger/TrackerTFP/interface/KalmanFilterFormats.h new file mode 100644 index 0000000000000..918e61a69fc2c --- /dev/null +++ b/L1Trigger/TrackerTFP/interface/KalmanFilterFormats.h @@ -0,0 +1,200 @@ +#ifndef L1Trigger_TrackerTFP_KalmanFilterFormats_h +#define L1Trigger_TrackerTFP_KalmanFilterFormats_h + +/*---------------------------------------------------------------------- +Classes to calculate and provide dataformats used by Kalman Filter emulator +enabling tuning of bit widths +----------------------------------------------------------------------*/ + +#include "FWCore/Framework/interface/data_default_record_trait.h" +#include "L1Trigger/TrackerTFP/interface/KalmanFilterFormatsRcd.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "L1Trigger/TrackerTFP/interface/DataFormats.h" + +#include +#include +#include +#include +#include +#include +#include + +namespace trackerTFP { + + enum class VariableKF { + begin, + x0 = begin, + x1, + x2, + x3, + H00, + H12, + m0, + m1, + v0, + v1, + r0, + r1, + S00, + S01, + S12, + S13, + K00, + K10, + K21, + K31, + R00, + R11, + R00Rough, + R11Rough, + invR00Approx, + invR11Approx, + invR00Cor, + invR11Cor, + invR00, + invR11, + C00, + C01, + C11, + C22, + C23, + C33, + end, + x + }; + inline constexpr int operator+(VariableKF v) { return static_cast(v); } + inline constexpr VariableKF operator++(VariableKF v) { return VariableKF(+v + 1); } + + class DataFormatKF { + public: + DataFormatKF(const VariableKF& v, bool twos); + virtual ~DataFormatKF() {} + double digi(double val) const { return (std::floor(val / base_ + 1.e-12) + .5) * base_; } + bool twos() const { return twos_; } + int width() const { return width_; } + double base() const { return base_; } + double range() const { return range_; } + const std::pair& rangeActual() const { return rangeActual_; } + // returns false if data format would oferflow for this double value + bool inRange(double d) const; + void updateRangeActual(double d); + int integer(double d) const { return floor(d / base_); } + + protected: + VariableKF v_; + bool twos_; + int width_; + double base_; + double range_; + std::pair rangeActual_; + }; + + template + class FormatKF : public DataFormatKF { + public: + FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig); + ~FormatKF() override {} + + private: + void calcRange() { range_ = base_ * pow(2, width_); } + }; + + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig); + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig); + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig); + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig); + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig); + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig); + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig); + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig); + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig); + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig); + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig); + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig); + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig); + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig); + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig); + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig); + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig); + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig); + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig); + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig); + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig); + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig); + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig); + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig); + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig); + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig); + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig); + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig); + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig); + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig); + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig); + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig); + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig); + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig); + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig); + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig); + + class KalmanFilterFormats { + public: + KalmanFilterFormats(); + KalmanFilterFormats(const edm::ParameterSet& iConfig, const DataFormats* dataFormats); + ~KalmanFilterFormats() {} + const tt::Setup* setup() const { return setup_; } + const DataFormats* dataFormats() const { return dataFormats_; } + int width(VariableKF v) const { return formats_[+v].width(); } + double base(VariableKF v) const { return formats_[+v].base(); } + DataFormatKF& format(VariableKF v) { return formats_[+v]; } + void endJob(); + + private: + template + void fillFormats(); + const edm::ParameterSet iConfig_; + const DataFormats* dataFormats_; + const tt::Setup* setup_; + std::vector formats_; + }; + +} // namespace trackerTFP + +EVENTSETUP_DATA_DEFAULT_RECORD(trackerTFP::KalmanFilterFormats, trackerTFP::KalmanFilterFormatsRcd); + +#endif diff --git a/L1Trigger/TrackerTFP/interface/KalmanFilterFormatsRcd.h b/L1Trigger/TrackerTFP/interface/KalmanFilterFormatsRcd.h new file mode 100644 index 0000000000000..c1c2a3298b97b --- /dev/null +++ b/L1Trigger/TrackerTFP/interface/KalmanFilterFormatsRcd.h @@ -0,0 +1,17 @@ +#ifndef L1Trigger_TrackerTFP_KalmanFilterFormatsRcd_h +#define L1Trigger_TrackerTFP_KalmanFilterFormatsRcd_h + +#include "FWCore/Framework/interface/DependentRecordImplementation.h" +#include "L1Trigger/TrackerTFP/interface/DataFormatsRcd.h" +#include "FWCore/Utilities/interface/mplVector.h" + +namespace trackerTFP { + + typedef edm::mpl::Vector RcdsKalmanFilterFormats; + + class KalmanFilterFormatsRcd + : public edm::eventsetup::DependentRecordImplementation {}; + +} // namespace trackerTFP + +#endif \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/interface/LayerEncoding.h b/L1Trigger/TrackerTFP/interface/LayerEncoding.h new file mode 100644 index 0000000000000..52052d243b3be --- /dev/null +++ b/L1Trigger/TrackerTFP/interface/LayerEncoding.h @@ -0,0 +1,55 @@ +#ifndef L1Trigger_TrackerTFP_LayerEncoding_h +#define L1Trigger_TrackerTFP_LayerEncoding_h + +#include "FWCore/Framework/interface/data_default_record_trait.h" +#include "L1Trigger/TrackerTFP/interface/LayerEncodingRcd.h" +#include "L1Trigger/TrackerTFP/interface/DataFormats.h" + +#include + +namespace trackerTFP { + + /*! \class trackerTFP::LayerEncoding + * \brief Class to encode layer ids for Kalman Filter + * Layers consitent with rough r-z track parameters are counted from 0 onwards. + * \author Thomas Schuh + * \date 2020, July + */ + class LayerEncoding { + public: + LayerEncoding() {} + LayerEncoding(const DataFormats* dataFormats); + ~LayerEncoding() {} + // Set of layers in each (zT,tanL) digi Bin of each eta sector numbered 0->N + const std::vector& layerEncoding(int binEta, int binZT, int binCot) const { + return layerEncoding_.at(binEta).at(binZT).at(binCot); + } + // maybe layers for given ets sector, bin in zT and bin in cotThea + const std::vector& maybeLayer(int binEta, int binZT, int binCot) const { + return maybeLayer_.at(binEta).at(binZT).at(binCot); + } + // encoded layer id for given eta sector, bin in zT, bin in cotThea and decoed layer id, returns -1 if layer incositent with track + const int layerIdKF(int binEta, int binZT, int binCot, int layerId) const; + // pattern of maybe layers for given eta sector, bin in zT and bin in cotThea + TTBV maybePattern(int binEta, int binZT, int binCot) const; + + private: + // helper class providing run-time constants + const tt::Setup* setup_; + // helper class providing dataformats + const DataFormats* dataFormats_; + // data foramt of variable zT + const DataFormat* zT_; + // data foramt of variable cotTheta + const DataFormat* cot_; + // outer to inner indices: eta sector, bin in zT, bin in cotTheta, layerId + std::vector>>> layerEncoding_; + // outer to inner indices: eta sector, bin in zT, bin in cotTheta, layerId of maybe layers + std::vector>>> maybeLayer_; + }; + +} // namespace trackerTFP + +EVENTSETUP_DATA_DEFAULT_RECORD(trackerTFP::LayerEncoding, trackerTFP::LayerEncodingRcd); + +#endif \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/interface/LayerEncodingRcd.h b/L1Trigger/TrackerTFP/interface/LayerEncodingRcd.h new file mode 100644 index 0000000000000..3ac343084f6d5 --- /dev/null +++ b/L1Trigger/TrackerTFP/interface/LayerEncodingRcd.h @@ -0,0 +1,18 @@ +#ifndef L1Trigger_TrackerTFP_LayerEncodingRcd_h +#define L1Trigger_TrackerTFP_LayerEncodingRcd_h + +#include "FWCore/Framework/interface/DependentRecordImplementation.h" +#include "L1Trigger/TrackerTFP/interface/DataFormatsRcd.h" +#include "FWCore/Utilities/interface/mplVector.h" + +namespace trackerTFP { + + typedef edm::mpl::Vector RcdsLayerEncoding; + + // record of trackerTFP::LayerEncoding + class LayerEncodingRcd : public edm::eventsetup::DependentRecordImplementation { + }; + +} // namespace trackerTFP + +#endif \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/interface/MiniHoughTransform.h b/L1Trigger/TrackerTFP/interface/MiniHoughTransform.h new file mode 100644 index 0000000000000..8cdaa35d922f2 --- /dev/null +++ b/L1Trigger/TrackerTFP/interface/MiniHoughTransform.h @@ -0,0 +1,69 @@ +#ifndef L1Trigger_TrackerTFP_MiniHoughTransform_h +#define L1Trigger_TrackerTFP_MiniHoughTransform_h + +#include "L1Trigger/TrackTrigger/interface/Setup.h" +#include "L1Trigger/TrackerTFP/interface/DataFormats.h" +#include "DataFormats/L1TrackTrigger/interface/TTTypes.h" + +#include +#include +#include + +namespace trackerTFP { + + // Class to refine HT track candidates in r-phi, by subdividing each HT cell into a finer granularity array + class MiniHoughTransform { + public: + MiniHoughTransform(const edm::ParameterSet& iConfig, + const tt::Setup* setup, + const DataFormats* dataFormats, + int region); + ~MiniHoughTransform() {} + + // read in and organize input product (fill vector input_) + void consume(const tt::StreamsStub& streams); + // fill output products + void produce(tt::StreamsStub& accepted, tt::StreamsStub& lost); + + private: + // remove and return first element of deque, returns nullptr if empty + template + T* pop_front(std::deque& ts) const; + // perform finer pattern recognition per track + void fill(int channel, const std::vector& input, std::vector>& output); + // Static load balancing of inputs: mux 4 streams to 1 stream + void slb(std::vector>& inputs, std::vector& accepted, tt::StreamStub& lost) const; + // Dynamic load balancing of inputs: swapping parts of streams to balance the amount of tracks per stream + void dlb(std::vector>& streams) const; + + // true if truncation is enbaled + bool enableTruncation_; + // provides run-time constants + const tt::Setup* setup_; + // provides dataformats + const DataFormats* dataFormats_; + // dataformat of inv2R + DataFormat inv2R_; + // dataformat of phiT + DataFormat phiT_; + // processing region (0 - 8) + int region_; + // number of inv2R bins used in HT + int numBinsInv2R_; + // number of cells used in MHT + int numCells_; + // number of dynamic load balancing nodes + int numNodes_; + // number of channel per dynamic load balancing node + int numChannel_; + // container of input stubs + std::vector stubsHT_; + // container of output stubs + std::vector stubsMHT_; + // h/w liked organized pointer to input stubs + std::vector> input_; + }; + +} // namespace trackerTFP + +#endif \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/interface/State.h b/L1Trigger/TrackerTFP/interface/State.h new file mode 100644 index 0000000000000..91804aa4648e8 --- /dev/null +++ b/L1Trigger/TrackerTFP/interface/State.h @@ -0,0 +1,131 @@ +#ifndef L1Trigger_TrackerTFP_State_h +#define L1Trigger_TrackerTFP_State_h + +#include "L1Trigger/TrackTrigger/interface/Setup.h" +#include "L1Trigger/TrackerTFP/interface/DataFormats.h" + +#include +#include + +namespace trackerTFP { + + // Class to represent a Kalman Filter State + class State { + public: + // default constructor + State(State* state); + // proto state constructor + State(const DataFormats* dataFormats, TrackKFin* track, int trackId); + // combinatoric state constructor + State(State* state, StubKFin* stub); + // updated state constructor + State(State* state, const std::vector& doubles); + ~State() {} + + // Determine quality of completed state + void finish(); + // number of skipped layers + int numSkippedLayers() const { return numSkippedLayers_; } + // number of consitent layers + int numConsistentLayers() const { return numConsistentLayers_; } + // input track + TrackKFin* track() const { return track_; } + // parent state (nullpointer if no parent available) + State* parent() const { return parent_; } + // stub to add to state + StubKFin* stub() const { return stub_; } + // hitPattern of so far added stubs + const TTBV& hitPattern() const { return hitPattern_; } + // track id of input track + int trackId() const { return trackId_; } + // pattern of maybe layers for input track + TTBV maybePattern() const { return track_->maybePattern(); } + // stub id per layer of so far added stubs + const std::vector& layerMap() const { return layerMap_; } + // layer id of the current stub to add + int layer() const { return stub_->layer(); } + // helix inv2R wrt input helix + double x0() const { return x0_; } + // helix phi at radius ChosenRofPhi wrt input helix + double x1() const { return x1_; } + // helix cot(Theta) wrt input helix + double x2() const { return x2_; } + // helix z at radius chosenRofZ wrt input helix + double x3() const { return x3_; } + // cov. matrix element + double C00() const { return C00_; } + // cov. matrix element + double C01() const { return C01_; } + // cov. matrix element + double C11() const { return C11_; } + // cov. matrix element + double C22() const { return C22_; } + // cov. matrix element + double C23() const { return C23_; } + // cov. matrix element + double C33() const { return C33_; } + // Derivative of predicted stub coords wrt helix params: stub radius minus chosenRofPhi + double H00() const { return stub_->r(); } + // Derivative of predicted stub coords wrt helix params: stub radius minus chosenRofZ + double H12() const { return stub_->r() + dataFormats_->chosenRofPhi() - setup_->chosenRofZ(); } + // stub phi residual wrt input helix + double m0() const { return stub_->phi(); } + // stub z residual wrt input helix + double m1() const { return stub_->z(); } + // stub projected phi uncertainty + double dPhi() const { return stub_->dPhi(); } + // stub projected z uncertainty + double dZ() const { return stub_->dZ(); } + // squared stub projected phi uncertainty instead of wheight (wrong but simpler) + double v0() const { return pow(stub_->dPhi(), 2); } + // squared stub projected z uncertainty instead of wheight (wrong but simpler) + double v1() const { return pow(stub_->dZ(), 2); } + // output frame + tt::FrameTrack frame() const { return TrackKF(*track_, x1_, x0_, x3_, x2_).frame(); } + // collection of stubs added so far to state + std::vector stubs() const; + + private: + // provides data fomats + const DataFormats* dataFormats_; + // provides run-time constants + const tt::Setup* setup_; + // input track + TrackKFin* track_; + // track id + int trackId_; + // previous state, nullptr for first states + State* parent_; + // stub to add + StubKFin* stub_; + // shows which stub on each layer has been added so far + std::vector layerMap_; + // shows which layer has been added so far + TTBV hitPattern_; + // helix inv2R wrt input helix + double x0_; + // helix phi at radius ChosenRofPhi wrt input helix + double x1_; + // helix cot(Theta) wrt input helix + double x2_; + // helix z at radius chosenRofZ wrt input helix + double x3_; + + // cov. matrix + + double C00_; + double C01_; + double C11_; + double C22_; + double C23_; + double C33_; + + // number of skipped layers + int numSkippedLayers_; + // number of consistent layers + int numConsistentLayers_; + }; + +} // namespace trackerTFP + +#endif \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/interface/ZHoughTransform.h b/L1Trigger/TrackerTFP/interface/ZHoughTransform.h new file mode 100644 index 0000000000000..1fbb2c622c7b3 --- /dev/null +++ b/L1Trigger/TrackerTFP/interface/ZHoughTransform.h @@ -0,0 +1,56 @@ +#ifndef L1Trigger_TrackerTFP_ZHoughTransform_h +#define L1Trigger_TrackerTFP_ZHoughTransform_h + +#include "L1Trigger/TrackTrigger/interface/Setup.h" +#include "L1Trigger/TrackerTFP/interface/DataFormats.h" +#include "DataFormats/L1TrackTrigger/interface/TTTypes.h" + +#include +#include + +namespace trackerTFP { + + // Class to refine MHT track candidates in r-z + class ZHoughTransform { + public: + ZHoughTransform(const edm::ParameterSet& iConfig, + const tt::Setup* setup, + const DataFormats* dataFormats, + int region); + ~ZHoughTransform() {} + + // read in and organize input product (fill vector input_) + void consume(const tt::StreamsStub& streams); + // fill output products + void produce(tt::StreamsStub& accepted, tt::StreamsStub& lost); + + private: + // remove and return first element of deque, returns nullptr if empty + template + T* pop_front(std::deque& ts) const; + // perform finer pattern recognition per track + void fill(int channel, const std::deque& input, std::vector>& output); + // Static load balancing of inputs: mux 4 streams to 1 stream + void slb(std::vector>& inputs, std::deque& accepted, tt::StreamStub& lost) const; + // + void merge(std::deque& stubs, tt::StreamStub& stream) const; + + // true if truncation is enbaled + bool enableTruncation_; + // provides run-time constants + const tt::Setup* setup_; + // provides dataformats + const DataFormats* dataFormats_; + // processing region (0 - 8) + int region_; + // container of in- and output stubs + std::vector stubsZHT_; + // h/w liked organized pointer to input stubs + std::vector> input_; + // + int stage_; + }; + +} // namespace trackerTFP + +#endif \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/plugins/BuildFile.xml b/L1Trigger/TrackerTFP/plugins/BuildFile.xml new file mode 100644 index 0000000000000..4a51952a71403 --- /dev/null +++ b/L1Trigger/TrackerTFP/plugins/BuildFile.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/plugins/ProducerDemonstrator.cc b/L1Trigger/TrackerTFP/plugins/ProducerDemonstrator.cc new file mode 100644 index 0000000000000..d1cb6d6e4e42b --- /dev/null +++ b/L1Trigger/TrackerTFP/plugins/ProducerDemonstrator.cc @@ -0,0 +1,43 @@ +#include "FWCore/Framework/interface/ESProducer.h" +#include "FWCore/Framework/interface/ModuleFactory.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/Utilities/interface/ESGetToken.h" +#include "L1Trigger/TrackerTFP/interface/Demonstrator.h" + +#include + +using namespace std; +using namespace edm; +using namespace tt; + +namespace trackerTFP { + + /*! \class trackerTFP::ProducerDemonstrator + * \brief Class to demontrate correctness of track trigger emulators + * \author Thomas Schuh + * \date 2020, Nov + */ + class ProducerDemonstrator : public ESProducer { + public: + ProducerDemonstrator(const ParameterSet& iConfig); + ~ProducerDemonstrator() override {} + unique_ptr produce(const DemonstratorRcd& rcd); + + private: + const ParameterSet* iConfig_; + ESGetToken esGetToken_; + }; + + ProducerDemonstrator::ProducerDemonstrator(const ParameterSet& iConfig) : iConfig_(&iConfig) { + auto cc = setWhatProduced(this); + esGetToken_ = cc.consumes(); + } + + unique_ptr ProducerDemonstrator::produce(const DemonstratorRcd& rcd) { + const Setup* setup = &rcd.get(esGetToken_); + return make_unique(*iConfig_, setup); + } + +} // namespace trackerTFP + +DEFINE_FWK_EVENTSETUP_MODULE(trackerTFP::ProducerDemonstrator); \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/plugins/ProducerES.cc b/L1Trigger/TrackerTFP/plugins/ProducerES.cc new file mode 100644 index 0000000000000..4bba602de2873 --- /dev/null +++ b/L1Trigger/TrackerTFP/plugins/ProducerES.cc @@ -0,0 +1,45 @@ +#include "FWCore/Framework/interface/ESProducer.h" +#include "FWCore/Framework/interface/ESHandle.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/Utilities/interface/ESGetToken.h" +#include "FWCore/Utilities/interface/ESInputTag.h" +#include "DataFormats/Provenance/interface/ParameterSetID.h" +#include "L1Trigger/TrackerTFP/interface/DataFormats.h" + +#include + +using namespace std; +using namespace edm; +using namespace tt; + +namespace trackerTFP { + + /*! \class trackerTFP::ProducerES + * \brief Class to produce setup of Track Trigger emulator data formats + * \author Thomas Schuh + * \date 2020, June + */ + class ProducerES : public ESProducer { + public: + ProducerES(const ParameterSet& iConfig); + ~ProducerES() override {} + unique_ptr produce(const DataFormatsRcd& rcd); + + private: + const ParameterSet iConfig_; + ESGetToken esGetToken_; + }; + + ProducerES::ProducerES(const ParameterSet& iConfig) : iConfig_(iConfig) { + auto cc = setWhatProduced(this); + esGetToken_ = cc.consumes(); + } + + unique_ptr ProducerES::produce(const DataFormatsRcd& rcd) { + const Setup* setup = &rcd.get(esGetToken_); + return make_unique(iConfig_, setup); + } + +} // namespace trackerTFP + +DEFINE_FWK_EVENTSETUP_MODULE(trackerTFP::ProducerES); \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/plugins/ProducerFormatsKF.cc b/L1Trigger/TrackerTFP/plugins/ProducerFormatsKF.cc new file mode 100644 index 0000000000000..c69380c5e47d9 --- /dev/null +++ b/L1Trigger/TrackerTFP/plugins/ProducerFormatsKF.cc @@ -0,0 +1,45 @@ +#include "FWCore/Framework/interface/ESProducer.h" +#include "FWCore/Framework/interface/ESHandle.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/Utilities/interface/ESGetToken.h" +#include "FWCore/Utilities/interface/ESInputTag.h" +#include "DataFormats/Provenance/interface/ParameterSetID.h" +#include "L1Trigger/TrackerTFP/interface/DataFormats.h" +#include "L1Trigger/TrackerTFP/interface/KalmanFilterFormats.h" + +#include + +using namespace std; +using namespace edm; + +namespace trackerTFP { + + /*! \class trackerTFP::ProducerFormatsKF + * \brief Class to produce setup of Kalman Filter emulator data formats + * \author Thomas Schuh + * \date 2020, July + */ + class ProducerFormatsKF : public ESProducer { + public: + ProducerFormatsKF(const ParameterSet& iConfig); + ~ProducerFormatsKF() override {} + unique_ptr produce(const KalmanFilterFormatsRcd& rcd); + + private: + const ParameterSet iConfig_; + ESGetToken esGetToken_; + }; + + ProducerFormatsKF::ProducerFormatsKF(const ParameterSet& iConfig) : iConfig_(iConfig) { + auto cc = setWhatProduced(this); + esGetToken_ = cc.consumes(); + } + + unique_ptr ProducerFormatsKF::produce(const KalmanFilterFormatsRcd& rcd) { + const DataFormats* dataFormats = &rcd.get(esGetToken_); + return make_unique(iConfig_, dataFormats); + } + +} // namespace trackerTFP + +DEFINE_FWK_EVENTSETUP_MODULE(trackerTFP::ProducerFormatsKF); \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/plugins/ProducerGP.cc b/L1Trigger/TrackerTFP/plugins/ProducerGP.cc new file mode 100644 index 0000000000000..3dedce5c702fc --- /dev/null +++ b/L1Trigger/TrackerTFP/plugins/ProducerGP.cc @@ -0,0 +1,112 @@ +#include "FWCore/Framework/interface/stream/EDProducer.h" +#include "FWCore/Framework/interface/Run.h" +#include "FWCore/Framework/interface/EventSetup.h" +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/MakerMacros.h" +#include "FWCore/Utilities/interface/EDGetToken.h" +#include "FWCore/Utilities/interface/EDPutToken.h" +#include "FWCore/Utilities/interface/ESGetToken.h" +#include "FWCore/Utilities/interface/InputTag.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "DataFormats/Common/interface/Handle.h" + +#include "DataFormats/L1TrackTrigger/interface/TTDTC.h" +#include "DataFormats/L1TrackTrigger/interface/TTTypes.h" +#include "L1Trigger/TrackTrigger/interface/Setup.h" +#include "L1Trigger/TrackerTFP/interface/DataFormats.h" +#include "L1Trigger/TrackerTFP/interface/GeometricProcessor.h" + +#include +#include + +using namespace std; +using namespace edm; +using namespace tt; + +namespace trackerTFP { + + /*! \class trackerTFP::ProducerGP + * \brief L1TrackTrigger Geometric Processor emulator + * \author Thomas Schuh + * \date 2020, March + */ + class ProducerGP : public stream::EDProducer<> { + public: + explicit ProducerGP(const ParameterSet&); + ~ProducerGP() override {} + + private: + void beginRun(const Run&, const EventSetup&) override; + void produce(Event&, const EventSetup&) override; + virtual void endJob() {} + + // ED input token of DTC stubs + EDGetTokenT edGetToken_; + // ED output token for accepted stubs + EDPutTokenT edPutTokenAccepted_; + // ED output token for lost stubs + EDPutTokenT edPutTokenLost_; + // Setup token + ESGetToken esGetTokenSetup_; + // DataFormats token + ESGetToken esGetTokenDataFormats_; + // configuration + ParameterSet iConfig_; + // helper classe to store configurations + const Setup* setup_; + // helper class to extract structured data from tt::Frames + const DataFormats* dataFormats_; + }; + + ProducerGP::ProducerGP(const ParameterSet& iConfig) : iConfig_(iConfig) { + const string& label = iConfig.getParameter("LabelDTC"); + const string& branchAccepted = iConfig.getParameter("BranchAcceptedStubs"); + const string& branchLost = iConfig.getParameter("BranchLostStubs"); + // book in- and output ED products + edGetToken_ = consumes(InputTag(label, branchAccepted)); + edPutTokenAccepted_ = produces(branchAccepted); + edPutTokenLost_ = produces(branchLost); + // book ES products + esGetTokenSetup_ = esConsumes(); + esGetTokenDataFormats_ = esConsumes(); + // initial ES products + setup_ = nullptr; + dataFormats_ = nullptr; + } + + void ProducerGP::beginRun(const Run& iRun, const EventSetup& iSetup) { + setup_ = &iSetup.getData(esGetTokenSetup_); + if (!setup_->configurationSupported()) + return; + // check process history if desired + if (iConfig_.getParameter("CheckHistory")) + setup_->checkHistory(iRun.processHistory()); + dataFormats_ = &iSetup.getData(esGetTokenDataFormats_); + } + + void ProducerGP::produce(Event& iEvent, const EventSetup& iSetup) { + // empty GP products + StreamsStub accepted(dataFormats_->numStreams(Process::gp)); + StreamsStub lost(dataFormats_->numStreams(Process::gp)); + // read in DTC Product and produce TFP product + if (setup_->configurationSupported()) { + Handle handle; + iEvent.getByToken(edGetToken_, handle); + const TTDTC& ttDTC = *handle.product(); + for (int region = 0; region < setup_->numRegions(); region++) { + // object to route Stubs of one region to one stream per sector + GeometricProcessor gp(iConfig_, setup_, dataFormats_, region); + // read in and organize input product + gp.consume(ttDTC); + // fill output products + gp.produce(accepted, lost); + } + } + // store products + iEvent.emplace(edPutTokenAccepted_, move(accepted)); + iEvent.emplace(edPutTokenLost_, move(lost)); + } + +} // namespace trackerTFP + +DEFINE_FWK_MODULE(trackerTFP::ProducerGP); \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/plugins/ProducerHT.cc b/L1Trigger/TrackerTFP/plugins/ProducerHT.cc new file mode 100644 index 0000000000000..0262859657afa --- /dev/null +++ b/L1Trigger/TrackerTFP/plugins/ProducerHT.cc @@ -0,0 +1,113 @@ +#include "FWCore/Framework/interface/stream/EDProducer.h" +#include "FWCore/Framework/interface/Run.h" +#include "FWCore/Framework/interface/EventSetup.h" +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/MakerMacros.h" +#include "FWCore/Utilities/interface/EDGetToken.h" +#include "FWCore/Utilities/interface/EDPutToken.h" +#include "FWCore/Utilities/interface/ESGetToken.h" +#include "FWCore/Utilities/interface/InputTag.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "DataFormats/Common/interface/Handle.h" + +#include "DataFormats/L1TrackTrigger/interface/TTTypes.h" +#include "L1Trigger/TrackTrigger/interface/Setup.h" +#include "L1Trigger/TrackerTFP/interface/DataFormats.h" +#include "L1Trigger/TrackerTFP/interface/HoughTransform.h" + +#include +#include + +using namespace std; +using namespace edm; +using namespace tt; + +namespace trackerTFP { + + /*! \class trackerTFP::ProducerHT + * \brief L1TrackTrigger Hough Transform emulator + * \author Thomas Schuh + * \date 2020, March + */ + class ProducerHT : public stream::EDProducer<> { + public: + explicit ProducerHT(const ParameterSet&); + ~ProducerHT() override {} + + private: + void beginRun(const Run&, const EventSetup&) override; + void produce(Event&, const EventSetup&) override; + virtual void endJob() {} + + // ED input token of gp stubs + EDGetTokenT edGetToken_; + // ED output token for accepted stubs + EDPutTokenT edPutTokenAccepted_; + // ED output token for lost stubs + EDPutTokenT edPutTokenLost_; + // Setup token + ESGetToken esGetTokenSetup_; + // DataFormats token + ESGetToken esGetTokenDataFormats_; + // configuration + ParameterSet iConfig_; + // helper class to store configurations + const Setup* setup_; + // helper class to extract structured data from tt::Frames + const DataFormats* dataFormats_; + }; + + ProducerHT::ProducerHT(const ParameterSet& iConfig) : iConfig_(iConfig) { + const string& label = iConfig.getParameter("LabelGP"); + const string& branchAccepted = iConfig.getParameter("BranchAcceptedStubs"); + const string& branchLost = iConfig.getParameter("BranchLostStubs"); + // book in- and output ED products + edGetToken_ = consumes(InputTag(label, branchAccepted)); + edPutTokenAccepted_ = produces(branchAccepted); + edPutTokenLost_ = produces(branchLost); + // book ES products + esGetTokenSetup_ = esConsumes(); + esGetTokenDataFormats_ = esConsumes(); + // initial ES products + setup_ = nullptr; + dataFormats_ = nullptr; + } + + void ProducerHT::beginRun(const Run& iRun, const EventSetup& iSetup) { + // helper class to store configurations + setup_ = &iSetup.getData(esGetTokenSetup_); + if (!setup_->configurationSupported()) + return; + // check process history if desired + if (iConfig_.getParameter("CheckHistory")) + setup_->checkHistory(iRun.processHistory()); + // helper class to extract structured data from tt::Frames + dataFormats_ = &iSetup.getData(esGetTokenDataFormats_); + } + + void ProducerHT::produce(Event& iEvent, const EventSetup& iSetup) { + // empty HT products + StreamsStub accepted(dataFormats_->numStreams(Process::ht)); + StreamsStub lost(dataFormats_->numStreams(Process::ht)); + // read in DTC Product and produce TFP product + if (setup_->configurationSupported()) { + Handle handle; + iEvent.getByToken(edGetToken_, handle); + const StreamsStub& streams = *handle.product(); + for (int region = 0; region < setup_->numRegions(); region++) { + // object to find initial rough candidates in r-phi in a region + HoughTransform ht(iConfig_, setup_, dataFormats_, region); + // read in and organize input product + ht.consume(streams); + // fill output products + ht.produce(accepted, lost); + } + } + // store products + iEvent.emplace(edPutTokenAccepted_, move(accepted)); + iEvent.emplace(edPutTokenLost_, move(lost)); + } + +} // namespace trackerTFP + +DEFINE_FWK_MODULE(trackerTFP::ProducerHT); \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/plugins/ProducerKF.cc b/L1Trigger/TrackerTFP/plugins/ProducerKF.cc new file mode 100644 index 0000000000000..585dbfae310af --- /dev/null +++ b/L1Trigger/TrackerTFP/plugins/ProducerKF.cc @@ -0,0 +1,152 @@ +#include "FWCore/Framework/interface/stream/EDProducer.h" +#include "FWCore/Framework/interface/Run.h" +#include "FWCore/Framework/interface/EventSetup.h" +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/MakerMacros.h" +#include "FWCore/Utilities/interface/EDGetToken.h" +#include "FWCore/Utilities/interface/EDPutToken.h" +#include "FWCore/Utilities/interface/ESGetToken.h" +#include "FWCore/Utilities/interface/InputTag.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "DataFormats/Common/interface/Handle.h" + +#include "DataFormats/L1TrackTrigger/interface/TTTypes.h" +#include "L1Trigger/TrackTrigger/interface/Setup.h" +#include "L1Trigger/TrackerTFP/interface/DataFormats.h" +#include "L1Trigger/TrackerTFP/interface/KalmanFilterFormats.h" +#include "L1Trigger/TrackerTFP/interface/LayerEncoding.h" +#include "L1Trigger/TrackerTFP/interface/KalmanFilter.h" + +#include + +using namespace std; +using namespace edm; +using namespace tt; + +namespace trackerTFP { + + /*! \class trackerTFP::ProducerKF + * \brief L1TrackTrigger Kamlan Filter emulator + * \author Thomas Schuh + * \date 2020, July + */ + class ProducerKF : public stream::EDProducer<> { + public: + explicit ProducerKF(const ParameterSet&); + ~ProducerKF() override {} + + private: + void beginRun(const Run&, const EventSetup&) override; + void produce(Event&, const EventSetup&) override; + void endStream() override { + if (printDebug_) + kalmanFilterFormats_->endJob(); + } + + // ED input token of sf stubs and tracks + EDGetTokenT edGetTokenStubs_; + EDGetTokenT edGetTokenTracks_; + // ED output token for accepted stubs and tracks + EDPutTokenT edPutTokenAcceptedStubs_; + EDPutTokenT edPutTokenAcceptedTracks_; + // ED output token for lost stubs and tracks + EDPutTokenT edPutTokenLostStubs_; + EDPutTokenT edPutTokenLostTracks_; + // ED output token for number of accepted and lost States + EDPutTokenT edPutTokenNumAcceptedStates_; + EDPutTokenT edPutTokenNumLostStates_; + // Setup token + ESGetToken esGetTokenSetup_; + // DataFormats token + ESGetToken esGetTokenDataFormats_; + // KalmanFilterFormats token + ESGetToken esGetTokenKalmanFilterFormats_; + // configuration + ParameterSet iConfig_; + // helper class to store configurations + const Setup* setup_; + // helper class to extract structured data from tt::Frames + const DataFormats* dataFormats_; + // helper class to + KalmanFilterFormats* kalmanFilterFormats_; + // print end job internal unused MSB + bool printDebug_; + }; + + ProducerKF::ProducerKF(const ParameterSet& iConfig) : iConfig_(iConfig) { + printDebug_ = iConfig.getParameter("PrintKFDebug"); + const string& label = iConfig.getParameter("LabelKFin"); + const string& branchAcceptedStubs = iConfig.getParameter("BranchAcceptedStubs"); + const string& branchAcceptedTracks = iConfig.getParameter("BranchAcceptedTracks"); + const string& branchLostStubs = iConfig.getParameter("BranchLostStubs"); + const string& branchLostTracks = iConfig.getParameter("BranchLostTracks"); + // book in- and output ED products + edGetTokenStubs_ = consumes(InputTag(label, branchAcceptedStubs)); + edGetTokenTracks_ = consumes(InputTag(label, branchAcceptedTracks)); + edPutTokenAcceptedStubs_ = produces(branchAcceptedStubs); + edPutTokenAcceptedTracks_ = produces(branchAcceptedTracks); + edPutTokenLostStubs_ = produces(branchLostStubs); + edPutTokenLostTracks_ = produces(branchLostTracks); + edPutTokenNumAcceptedStates_ = produces(branchAcceptedTracks); + edPutTokenNumLostStates_ = produces(branchLostTracks); + // book ES products + esGetTokenSetup_ = esConsumes(); + esGetTokenDataFormats_ = esConsumes(); + esGetTokenKalmanFilterFormats_ = esConsumes(); + // initial ES products + setup_ = nullptr; + dataFormats_ = nullptr; + kalmanFilterFormats_ = nullptr; + } + + void ProducerKF::beginRun(const Run& iRun, const EventSetup& iSetup) { + // helper class to store configurations + setup_ = &iSetup.getData(esGetTokenSetup_); + if (!setup_->configurationSupported()) + return; + // check process history if desired + if (iConfig_.getParameter("CheckHistory")) + setup_->checkHistory(iRun.processHistory()); + // helper class to extract structured data from tt::Frames + dataFormats_ = &iSetup.getData(esGetTokenDataFormats_); + // helper class to + kalmanFilterFormats_ = const_cast(&iSetup.getData(esGetTokenKalmanFilterFormats_)); + } + + void ProducerKF::produce(Event& iEvent, const EventSetup& iSetup) { + // empty KF products + StreamsStub acceptedStubs(dataFormats_->numStreamsStubs(Process::kf)); + StreamsTrack acceptedTracks(dataFormats_->numStreamsTracks(Process::kf)); + StreamsStub lostStubs(dataFormats_->numStreamsStubs(Process::kf)); + StreamsTrack lostTracks(dataFormats_->numStreamsTracks(Process::kf)); + int numAcceptedStates(0); + int numLostStates(0); + // read in SF Product and produce KF product + if (setup_->configurationSupported()) { + Handle handleStubs; + iEvent.getByToken(edGetTokenStubs_, handleStubs); + const StreamsStub& stubs = *handleStubs; + Handle handleTracks; + iEvent.getByToken(edGetTokenTracks_, handleTracks); + const StreamsTrack& tracks = *handleTracks; + for (int region = 0; region < setup_->numRegions(); region++) { + // object to fit tracks in a processing region + KalmanFilter kf(iConfig_, setup_, dataFormats_, kalmanFilterFormats_, region); + // read in and organize input tracks and stubs + kf.consume(tracks, stubs); + // fill output products + kf.produce(acceptedStubs, acceptedTracks, lostStubs, lostTracks, numAcceptedStates, numLostStates); + } + } + // store products + iEvent.emplace(edPutTokenAcceptedStubs_, move(acceptedStubs)); + iEvent.emplace(edPutTokenAcceptedTracks_, move(acceptedTracks)); + iEvent.emplace(edPutTokenLostStubs_, move(lostStubs)); + iEvent.emplace(edPutTokenLostTracks_, move(lostTracks)); + iEvent.emplace(edPutTokenNumAcceptedStates_, numAcceptedStates); + iEvent.emplace(edPutTokenNumLostStates_, numLostStates); + } + +} // namespace trackerTFP + +DEFINE_FWK_MODULE(trackerTFP::ProducerKF); \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/plugins/ProducerKFin.cc b/L1Trigger/TrackerTFP/plugins/ProducerKFin.cc new file mode 100644 index 0000000000000..e1dd4c892d81d --- /dev/null +++ b/L1Trigger/TrackerTFP/plugins/ProducerKFin.cc @@ -0,0 +1,228 @@ +#include "FWCore/Framework/interface/stream/EDProducer.h" +#include "FWCore/Framework/interface/Run.h" +#include "FWCore/Framework/interface/EventSetup.h" +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/MakerMacros.h" +#include "FWCore/Utilities/interface/EDGetToken.h" +#include "FWCore/Utilities/interface/EDPutToken.h" +#include "FWCore/Utilities/interface/ESGetToken.h" +#include "FWCore/Utilities/interface/InputTag.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "DataFormats/Common/interface/Handle.h" + +#include "DataFormats/L1TrackTrigger/interface/TTTypes.h" +#include "L1Trigger/TrackTrigger/interface/Setup.h" +#include "L1Trigger/TrackerTFP/interface/DataFormats.h" +#include "L1Trigger/TrackerTFP/interface/LayerEncoding.h" + +#include +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace edm; +using namespace tt; + +namespace trackerTFP { + + /*! \class trackerTFP::ProducerKFin + * \brief transforms TTTracks into KF input + * \author Thomas Schuh + * \date 2020, July + */ + class ProducerKFin : public stream::EDProducer<> { + public: + explicit ProducerKFin(const ParameterSet&); + ~ProducerKFin() override {} + + private: + void beginRun(const Run&, const EventSetup&) override; + void produce(Event&, const EventSetup&) override; + virtual void endJob() {} + + // ED input token of TTTracks + EDGetTokenT>> edGetTokenTTTracks_; + // ED input token of Stubs + EDGetTokenT edGetTokenStubs_; + // ED output token for stubs + EDPutTokenT edPutTokenAcceptedStubs_; + EDPutTokenT edPutTokenLostStubs_; + // ED output token for tracks + EDPutTokenT edPutTokenAcceptedTracks_; + EDPutTokenT edPutTokenLostTracks_; + // Setup token + ESGetToken esGetTokenSetup_; + // DataFormats token + ESGetToken esGetTokenDataFormats_; + // LayerEncoding token + ESGetToken esGetTokenLayerEncoding_; + // configuration + ParameterSet iConfig_; + // helper class to store configurations + const Setup* setup_; + // helper class to extract structured data from tt::Frames + const DataFormats* dataFormats_; + // helper class to encode layer + const LayerEncoding* layerEncoding_; + // + bool enableTruncation_; + }; + + ProducerKFin::ProducerKFin(const ParameterSet& iConfig) : iConfig_(iConfig) { + const string& labelTTTracks = iConfig.getParameter("LabelZHTout"); + const string& labelStubs = iConfig.getParameter("LabelZHT"); + const string& branchAcceptedStubs = iConfig.getParameter("BranchAcceptedStubs"); + const string& branchAcceptedTracks = iConfig.getParameter("BranchAcceptedTracks"); + const string& branchLostStubs = iConfig.getParameter("BranchLostStubs"); + const string& branchLostTracks = iConfig.getParameter("BranchLostTracks"); + // book in- and output ED products + edGetTokenTTTracks_ = + consumes>>(InputTag(labelTTTracks, branchAcceptedTracks)); + edGetTokenStubs_ = consumes(InputTag(labelStubs, branchAcceptedStubs)); + edPutTokenAcceptedStubs_ = produces(branchAcceptedStubs); + edPutTokenAcceptedTracks_ = produces(branchAcceptedTracks); + edPutTokenLostStubs_ = produces(branchLostStubs); + edPutTokenLostTracks_ = produces(branchLostTracks); + // book ES products + esGetTokenSetup_ = esConsumes(); + esGetTokenDataFormats_ = esConsumes(); + esGetTokenLayerEncoding_ = esConsumes(); + // initial ES products + setup_ = nullptr; + dataFormats_ = nullptr; + layerEncoding_ = nullptr; + // + enableTruncation_ = iConfig.getParameter("EnableTruncation"); + } + + void ProducerKFin::beginRun(const Run& iRun, const EventSetup& iSetup) { + // helper class to store configurations + setup_ = &iSetup.getData(esGetTokenSetup_); + if (!setup_->configurationSupported()) + return; + // check process history if desired + if (iConfig_.getParameter("CheckHistory")) + setup_->checkHistory(iRun.processHistory()); + // helper class to extract structured data from tt::Frames + dataFormats_ = &iSetup.getData(esGetTokenDataFormats_); + // helper class to encode layer + layerEncoding_ = &iSetup.getData(esGetTokenLayerEncoding_); + } + + void ProducerKFin::produce(Event& iEvent, const EventSetup& iSetup) { + const DataFormat& dfcot = dataFormats_->format(Variable::cot, Process::kfin); + const DataFormat& dfzT = dataFormats_->format(Variable::zT, Process::kfin); + const DataFormat& dfinv2R = dataFormats_->format(Variable::inv2R, Process::kfin); + const DataFormat& dfdPhi = dataFormats_->format(Variable::dPhi, Process::kfin); + const DataFormat& dfdZ = dataFormats_->format(Variable::dZ, Process::kfin); + // empty KFin products + StreamsStub streamAcceptedStubs(dataFormats_->numStreamsStubs(Process::kf)); + StreamsTrack streamAcceptedTracks(dataFormats_->numStreamsTracks(Process::kf)); + StreamsStub streamLostStubs(dataFormats_->numStreamsStubs(Process::kf)); + StreamsTrack streamLostTracks(dataFormats_->numStreamsTracks(Process::kf)); + // read in SFout Product and produce KFin product + if (setup_->configurationSupported()) { + Handle handleStubs; + iEvent.getByToken(edGetTokenStubs_, handleStubs); + const StreamsStub& streams = *handleStubs.product(); + Handle>> handleTTTracks; + iEvent.getByToken>>(edGetTokenTTTracks_, handleTTTracks); + const vector>& ttTracks = *handleTTTracks.product(); + for (int region = 0; region < setup_->numRegions(); region++) { + // Unpack input SF data into vector + int nStubsZHR(0); + for (int channel = 0; channel < dataFormats_->numChannel(Process::zht); channel++) { + const int index = region * dataFormats_->numChannel(Process::zht) + channel; + const StreamStub& stream = streams[index]; + nStubsZHR += accumulate(stream.begin(), stream.end(), 0, [](int& sum, const FrameStub& frame) { + return sum += frame.first.isNonnull() ? 1 : 0; + }); + } + vector stubsZHT; + stubsZHT.reserve(nStubsZHR); + for (int channel = 0; channel < dataFormats_->numChannel(Process::zht); channel++) { + const int index = region * dataFormats_->numChannel(Process::zht) + channel; + for (const FrameStub& frame : streams[index]) + if (frame.first.isNonnull()) + stubsZHT.emplace_back(frame, dataFormats_); + } + vector> dequesStubs(dataFormats_->numChannel(Process::kf) * setup_->numLayers()); + vector> dequesTracks(dataFormats_->numChannel(Process::kf)); + int i(0); + for (const TTTrack& ttTrack : ttTracks) { + if ((int)ttTrack.phiSector() / setup_->numSectorsPhi() != region) { + i++; + continue; + } + const int sectorPhi = ttTrack.phiSector() % setup_->numSectorsPhi(); + deque& tracks = dequesTracks[sectorPhi]; + const int binEta = ttTrack.etaSector(); + const int binZT = dfzT.toUnsigned(dfzT.integer(ttTrack.z0())); + const int binCot = dfcot.toUnsigned(dfcot.integer(ttTrack.tanL())); + StubZHT* stubZHT = nullptr; + vector layerCounts(setup_->numLayers(), 0); + for (const TTStubRef& ttStubRef : ttTrack.getStubRefs()) { + const int layerId = setup_->layerId(ttStubRef); + const int layerIdKF = layerEncoding_->layerIdKF(binEta, binZT, binCot, layerId); + if (layerCounts[layerIdKF] == setup_->zhtMaxStubsPerLayer()) + continue; + layerCounts[layerIdKF]++; + deque& stubs = dequesStubs[sectorPhi * setup_->numLayers() + layerIdKF]; + auto identical = [ttStubRef, ttTrack](const StubZHT& stub) { + return (int)ttTrack.trackSeedType() == stub.trackId() && ttStubRef == stub.ttStubRef(); + }; + stubZHT = &*find_if(stubsZHT.begin(), stubsZHT.end(), identical); + const double inv2R = dfinv2R.floating(stubZHT->inv2R()); + const double cot = dfcot.floating(stubZHT->cot()) + setup_->sectorCot(binEta); + const double dPhi = dfdPhi.digi(setup_->dPhi(ttStubRef, inv2R)); + const double dZ = dfdZ.digi(setup_->dZ(ttStubRef, cot)); + const StubKFin stubKFin(*stubZHT, dPhi, dZ, layerIdKF); + stubs.emplace_back(stubKFin.frame()); + } + const int size = *max_element(layerCounts.begin(), layerCounts.end()); + int layerIdKF(0); + for (int layerCount : layerCounts) { + deque& stubs = dequesStubs[sectorPhi * setup_->numLayers() + layerIdKF++]; + const int nGaps = size - layerCount; + stubs.insert(stubs.end(), nGaps, FrameStub()); + } + const TTBV& maybePattern = layerEncoding_->maybePattern(binEta, binZT, binCot); + const TrackKFin track(*stubZHT, TTTrackRef(handleTTTracks, i++), maybePattern); + tracks.emplace_back(track.frame()); + const int nGaps = size - 1; + tracks.insert(tracks.end(), nGaps, FrameTrack()); + } + // transform deques to vectors & emulate truncation + for (int channel = 0; channel < dataFormats_->numChannel(Process::kf); channel++) { + const int index = region * dataFormats_->numChannel(Process::kf) + channel; + deque& tracks = dequesTracks[channel]; + auto limitTracks = next(tracks.begin(), min(setup_->numFrames(), (int)tracks.size())); + if (!enableTruncation_) + limitTracks = tracks.end(); + streamAcceptedTracks[index] = StreamTrack(tracks.begin(), limitTracks); + streamLostTracks[index] = StreamTrack(limitTracks, tracks.end()); + for (int l = 0; l < setup_->numLayers(); l++) { + deque& stubs = dequesStubs[channel * setup_->numLayers() + l]; + auto limitStubs = next(stubs.begin(), min(setup_->numFrames(), (int)stubs.size())); + if (!enableTruncation_) + limitStubs = stubs.end(); + streamAcceptedStubs[index * setup_->numLayers() + l] = StreamStub(stubs.begin(), limitStubs); + streamLostStubs[index * setup_->numLayers() + l] = StreamStub(limitStubs, stubs.end()); + } + } + } + } + // store products + iEvent.emplace(edPutTokenAcceptedStubs_, move(streamAcceptedStubs)); + iEvent.emplace(edPutTokenAcceptedTracks_, move(streamAcceptedTracks)); + iEvent.emplace(edPutTokenLostStubs_, move(streamLostStubs)); + iEvent.emplace(edPutTokenLostTracks_, move(streamLostTracks)); + } + +} // namespace trackerTFP + +DEFINE_FWK_MODULE(trackerTFP::ProducerKFin); \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/plugins/ProducerLayerEncoding.cc b/L1Trigger/TrackerTFP/plugins/ProducerLayerEncoding.cc new file mode 100644 index 0000000000000..1b02e6944e652 --- /dev/null +++ b/L1Trigger/TrackerTFP/plugins/ProducerLayerEncoding.cc @@ -0,0 +1,45 @@ +#include "FWCore/Framework/interface/ESProducer.h" +#include "FWCore/Framework/interface/ESHandle.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/Utilities/interface/ESGetToken.h" +#include "FWCore/Utilities/interface/ESInputTag.h" +#include "DataFormats/Provenance/interface/ParameterSetID.h" +#include "L1Trigger/TrackerTFP/interface/LayerEncoding.h" + +#include + +using namespace std; +using namespace edm; + +namespace trackerTFP { + + /*! \class trackerTFP::ProducerLayerEncoding + * \brief Class to produce KF layer encoding + * \author Thomas Schuh + * \date 2020, July + */ + class ProducerLayerEncoding : public ESProducer { + public: + ProducerLayerEncoding(const ParameterSet& iConfig); + ~ProducerLayerEncoding() override {} + unique_ptr produce(const LayerEncodingRcd& rcd); + + private: + const ParameterSet iConfig_; + ESGetToken esGetToken_; + }; + + ProducerLayerEncoding::ProducerLayerEncoding(const ParameterSet& iConfig) : iConfig_(iConfig) { + auto cc = setWhatProduced(this); + esGetToken_ = cc.consumes(); + } + + unique_ptr ProducerLayerEncoding::produce(const LayerEncodingRcd& rcd) { + const DataFormats* dataFormats = &rcd.get(esGetToken_); + //return make_unique(iConfig_, dataFormats); + return make_unique(dataFormats); + } + +} // namespace trackerTFP + +DEFINE_FWK_EVENTSETUP_MODULE(trackerTFP::ProducerLayerEncoding); \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/plugins/ProducerMHT.cc b/L1Trigger/TrackerTFP/plugins/ProducerMHT.cc new file mode 100644 index 0000000000000..96ff7aa29620c --- /dev/null +++ b/L1Trigger/TrackerTFP/plugins/ProducerMHT.cc @@ -0,0 +1,113 @@ +#include "FWCore/Framework/interface/stream/EDProducer.h" +#include "FWCore/Framework/interface/Run.h" +#include "FWCore/Framework/interface/EventSetup.h" +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/MakerMacros.h" +#include "FWCore/Utilities/interface/EDGetToken.h" +#include "FWCore/Utilities/interface/EDPutToken.h" +#include "FWCore/Utilities/interface/ESGetToken.h" +#include "FWCore/Utilities/interface/InputTag.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "DataFormats/Common/interface/Handle.h" + +#include "DataFormats/L1TrackTrigger/interface/TTTypes.h" +#include "L1Trigger/TrackTrigger/interface/Setup.h" +#include "L1Trigger/TrackerTFP/interface/DataFormats.h" +#include "L1Trigger/TrackerTFP/interface/MiniHoughTransform.h" + +#include +#include + +using namespace std; +using namespace edm; +using namespace tt; + +namespace trackerTFP { + + /*! \class trackerTFP::ProducerMHT + * \brief L1TrackTrigger Mini Hough Transform emulator + * \author Thomas Schuh + * \date 2020, May + */ + class ProducerMHT : public stream::EDProducer<> { + public: + explicit ProducerMHT(const ParameterSet&); + ~ProducerMHT() override {} + + private: + void beginRun(const Run&, const EventSetup&) override; + void produce(Event&, const EventSetup&) override; + virtual void endJob() {} + + // ED input token of gp stubs + EDGetTokenT edGetToken_; + // ED output token for accepted stubs + EDPutTokenT edPutTokenAccepted_; + // ED output token for lost stubs + EDPutTokenT edPutTokenLost_; + // Setup token + ESGetToken esGetTokenSetup_; + // DataFormats token + ESGetToken esGetTokenDataFormats_; + // configuration + ParameterSet iConfig_; + // helper class to store configurations + const Setup* setup_; + // helper class to extract structured data from tt::Frames + const DataFormats* dataFormats_; + }; + + ProducerMHT::ProducerMHT(const ParameterSet& iConfig) : iConfig_(iConfig) { + const string& label = iConfig.getParameter("LabelHT"); + const string& branchAccepted = iConfig.getParameter("BranchAcceptedStubs"); + const string& branchLost = iConfig.getParameter("BranchLostStubs"); + // book in- and output ED products + edGetToken_ = consumes(InputTag(label, branchAccepted)); + edPutTokenAccepted_ = produces(branchAccepted); + edPutTokenLost_ = produces(branchLost); + // book ES products + esGetTokenSetup_ = esConsumes(); + esGetTokenDataFormats_ = esConsumes(); + // initial ES products + setup_ = nullptr; + dataFormats_ = nullptr; + } + + void ProducerMHT::beginRun(const Run& iRun, const EventSetup& iSetup) { + // helper class to store configurations + setup_ = &iSetup.getData(esGetTokenSetup_); + if (!setup_->configurationSupported()) + return; + // check process history if desired + if (iConfig_.getParameter("CheckHistory")) + setup_->checkHistory(iRun.processHistory()); + // helper class to extract structured data from tt::Frames + dataFormats_ = &iSetup.getData(esGetTokenDataFormats_); + } + + void ProducerMHT::produce(Event& iEvent, const EventSetup& iSetup) { + // empty MHT products + StreamsStub accepted(dataFormats_->numStreams(Process::mht)); + StreamsStub lost(dataFormats_->numStreams(Process::mht)); + // read in HT Product and produce MHT product + if (setup_->configurationSupported()) { + Handle handle; + iEvent.getByToken(edGetToken_, handle); + const StreamsStub& streams = *handle.product(); + for (int region = 0; region < setup_->numRegions(); region++) { + // object to find in a region finer rough candidates in r-phi + MiniHoughTransform mht(iConfig_, setup_, dataFormats_, region); + // read in and organize input product + mht.consume(streams); + // fill output products + mht.produce(accepted, lost); + } + } + // store products + iEvent.emplace(edPutTokenAccepted_, move(accepted)); + iEvent.emplace(edPutTokenLost_, move(lost)); + } + +} // namespace trackerTFP + +DEFINE_FWK_MODULE(trackerTFP::ProducerMHT); \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/plugins/ProducerTT.cc b/L1Trigger/TrackerTFP/plugins/ProducerTT.cc new file mode 100644 index 0000000000000..0294a79df1cd6 --- /dev/null +++ b/L1Trigger/TrackerTFP/plugins/ProducerTT.cc @@ -0,0 +1,127 @@ +#include "FWCore/Framework/interface/stream/EDProducer.h" +#include "FWCore/Framework/interface/Run.h" +#include "FWCore/Framework/interface/EventSetup.h" +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/MakerMacros.h" +#include "FWCore/Utilities/interface/EDGetToken.h" +#include "FWCore/Utilities/interface/EDPutToken.h" +#include "FWCore/Utilities/interface/ESGetToken.h" +#include "FWCore/Utilities/interface/InputTag.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "DataFormats/Common/interface/Handle.h" + +#include "DataFormats/L1TrackTrigger/interface/TTTypes.h" +#include "L1Trigger/TrackTrigger/interface/Setup.h" +#include "L1Trigger/TrackerTFP/interface/DataFormats.h" + +#include +#include + +using namespace std; +using namespace edm; +using namespace tt; + +namespace trackerTFP { + + /*! \class trackerTFP::ProducerTT + * \brief Converts KF output into TTTracks + * \author Thomas Schuh + * \date 2020, Oct + */ + class ProducerTT : public stream::EDProducer<> { + public: + explicit ProducerTT(const ParameterSet&); + ~ProducerTT() override {} + + private: + void beginRun(const Run&, const EventSetup&) override; + void produce(Event&, const EventSetup&) override; + void endJob() {} + + // ED input token of kf stubs + EDGetTokenT edGetTokenStubs_; + // ED input token of kf tracks + EDGetTokenT edGetTokenTracks_; + // ED output token for TTTracks + EDPutTokenT edPutToken_; + // Setup token + ESGetToken esGetTokenSetup_; + // DataFormats token + ESGetToken esGetTokenDataFormats_; + // configuration + ParameterSet iConfig_; + // helper class to store configurations + const Setup* setup_; + // helper class to extract structured data from tt::Frames + const DataFormats* dataFormats_; + }; + + ProducerTT::ProducerTT(const ParameterSet& iConfig) : iConfig_(iConfig) { + const string& label = iConfig.getParameter("LabelKF"); + const string& branchStubs = iConfig.getParameter("BranchAcceptedStubs"); + const string& branchTracks = iConfig.getParameter("BranchAcceptedTracks"); + // book in- and output ED products + edGetTokenStubs_ = consumes(InputTag(label, branchStubs)); + edGetTokenTracks_ = consumes(InputTag(label, branchTracks)); + edPutToken_ = produces(branchTracks); + // book ES products + esGetTokenSetup_ = esConsumes(); + esGetTokenDataFormats_ = esConsumes(); + // initial ES products + setup_ = nullptr; + dataFormats_ = nullptr; + } + + void ProducerTT::beginRun(const Run& iRun, const EventSetup& iSetup) { + // helper class to store configurations + setup_ = &iSetup.getData(esGetTokenSetup_); + if (!setup_->configurationSupported()) + return; + // check process history if desired + if (iConfig_.getParameter("CheckHistory")) + setup_->checkHistory(iRun.processHistory()); + // helper class to extract structured data from tt::Frames + dataFormats_ = &iSetup.getData(esGetTokenDataFormats_); + } + + void ProducerTT::produce(Event& iEvent, const EventSetup& iSetup) { + // empty KFTTTrack product + TTTracks ttTracks; + // read in KF Product and produce KFTTTrack product + if (setup_->configurationSupported()) { + Handle handleTracks; + iEvent.getByToken(edGetTokenTracks_, handleTracks); + const StreamsTrack& streamsTracks = *handleTracks.product(); + Handle handleStubs; + iEvent.getByToken(edGetTokenTracks_, handleStubs); + const StreamsStub& streamsStubs = *handleStubs.product(); + int nTracks(0); + for (const StreamTrack& stream : streamsTracks) + nTracks += accumulate(stream.begin(), stream.end(), 0, [](int& sum, const FrameTrack& frame) { + return sum += frame.first.isNonnull() ? 1 : 0; + }); + ttTracks.reserve(nTracks); + for (int channel = 0; channel < dataFormats_->numStreamsTracks(Process::kf); channel++) { + int iTrk(0); + const int offset = channel * setup_->numLayers(); + for (const FrameTrack& frameTrack : streamsTracks[channel]) { + vector stubs; + stubs.reserve(setup_->numLayers()); + for (int layer = 0; layer < setup_->numLayers(); layer++) { + const FrameStub& frameStub = streamsStubs[offset + layer][iTrk]; + if (frameStub.first.isNonnull()) + stubs.emplace_back(frameStub, dataFormats_, layer); + } + TrackKF track(frameTrack, dataFormats_); + ttTracks.emplace_back(track.ttTrack(stubs)); + iTrk++; + } + } + } + // store products + iEvent.emplace(edPutToken_, move(ttTracks)); + } + +} // namespace trackerTFP + +DEFINE_FWK_MODULE(trackerTFP::ProducerTT); \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/plugins/ProducerZHT.cc b/L1Trigger/TrackerTFP/plugins/ProducerZHT.cc new file mode 100644 index 0000000000000..38943b1372087 --- /dev/null +++ b/L1Trigger/TrackerTFP/plugins/ProducerZHT.cc @@ -0,0 +1,113 @@ +#include "FWCore/Framework/interface/stream/EDProducer.h" +#include "FWCore/Framework/interface/Run.h" +#include "FWCore/Framework/interface/EventSetup.h" +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/MakerMacros.h" +#include "FWCore/Utilities/interface/EDGetToken.h" +#include "FWCore/Utilities/interface/EDPutToken.h" +#include "FWCore/Utilities/interface/ESGetToken.h" +#include "FWCore/Utilities/interface/InputTag.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "DataFormats/Common/interface/Handle.h" + +#include "DataFormats/L1TrackTrigger/interface/TTTypes.h" +#include "L1Trigger/TrackTrigger/interface/Setup.h" +#include "L1Trigger/TrackerTFP/interface/DataFormats.h" +#include "L1Trigger/TrackerTFP/interface/ZHoughTransform.h" + +#include +#include + +using namespace std; +using namespace edm; +using namespace tt; + +namespace trackerTFP { + + /*! \class trackerTFP::ProducerZHT + * \brief L1TrackTrigger r-z Hough Transform emulator + * \author Thomas Schuh + * \date 2021, May + */ + class ProducerZHT : public stream::EDProducer<> { + public: + explicit ProducerZHT(const ParameterSet&); + ~ProducerZHT() override {} + + private: + void beginRun(const Run&, const EventSetup&) override; + void produce(Event&, const EventSetup&) override; + virtual void endJob() {} + + // ED input token of gp stubs + EDGetTokenT edGetToken_; + // ED output token for accepted stubs + EDPutTokenT edPutTokenAccepted_; + // ED output token for lost stubs + EDPutTokenT edPutTokenLost_; + // Setup token + ESGetToken esGetTokenSetup_; + // DataFormats token + ESGetToken esGetTokenDataFormats_; + // configuration + ParameterSet iConfig_; + // helper class to store configurations + const Setup* setup_; + // helper class to extract structured data from tt::Frames + const DataFormats* dataFormats_; + }; + + ProducerZHT::ProducerZHT(const ParameterSet& iConfig) : iConfig_(iConfig) { + const string& label = iConfig.getParameter("LabelMHT"); + const string& branchAccepted = iConfig.getParameter("BranchAcceptedStubs"); + const string& branchLost = iConfig.getParameter("BranchLostStubs"); + // book in- and output ED products + edGetToken_ = consumes(InputTag(label, branchAccepted)); + edPutTokenAccepted_ = produces(branchAccepted); + edPutTokenLost_ = produces(branchLost); + // book ES products + esGetTokenSetup_ = esConsumes(); + esGetTokenDataFormats_ = esConsumes(); + // initial ES products + setup_ = nullptr; + dataFormats_ = nullptr; + } + + void ProducerZHT::beginRun(const Run& iRun, const EventSetup& iSetup) { + // helper class to store configurations + setup_ = &iSetup.getData(esGetTokenSetup_); + if (!setup_->configurationSupported()) + return; + // check process history if desired + if (iConfig_.getParameter("CheckHistory")) + setup_->checkHistory(iRun.processHistory()); + // helper class to extract structured data from tt::Frames + dataFormats_ = &iSetup.getData(esGetTokenDataFormats_); + } + + void ProducerZHT::produce(Event& iEvent, const EventSetup& iSetup) { + // empty MHT products + StreamsStub accepted(dataFormats_->numStreams(Process::mht)); + StreamsStub lost(dataFormats_->numStreams(Process::mht)); + // read in HT Product and produce MHT product + if (setup_->configurationSupported()) { + Handle handle; + iEvent.getByToken(edGetToken_, handle); + const StreamsStub& streams = *handle.product(); + for (int region = 0; region < setup_->numRegions(); region++) { + // object to find in a region finer rough candidates in r-phi + ZHoughTransform zht(iConfig_, setup_, dataFormats_, region); + // read in and organize input product + zht.consume(streams); + // fill output products + zht.produce(accepted, lost); + } + } + // store products + iEvent.emplace(edPutTokenAccepted_, move(accepted)); + iEvent.emplace(edPutTokenLost_, move(lost)); + } + +} // namespace trackerTFP + +DEFINE_FWK_MODULE(trackerTFP::ProducerZHT); \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/plugins/ProducerZHTout.cc b/L1Trigger/TrackerTFP/plugins/ProducerZHTout.cc new file mode 100644 index 0000000000000..774fe46024a4d --- /dev/null +++ b/L1Trigger/TrackerTFP/plugins/ProducerZHTout.cc @@ -0,0 +1,138 @@ +#include "FWCore/Framework/interface/stream/EDProducer.h" +#include "FWCore/Framework/interface/Run.h" +#include "FWCore/Framework/interface/EventSetup.h" +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/MakerMacros.h" +#include "FWCore/Utilities/interface/EDGetToken.h" +#include "FWCore/Utilities/interface/EDPutToken.h" +#include "FWCore/Utilities/interface/ESGetToken.h" +#include "FWCore/Utilities/interface/InputTag.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "DataFormats/Common/interface/Handle.h" + +#include "DataFormats/L1TrackTrigger/interface/TTTypes.h" +#include "L1Trigger/TrackTrigger/interface/Setup.h" +#include "L1Trigger/TrackerTFP/interface/DataFormats.h" + +#include +#include +#include + +using namespace std; +using namespace edm; +using namespace tt; + +namespace trackerTFP { + + /*! \class trackerTFP::ProducerZHTout + * \brief transforms SF output into TTTracks + * \author Thomas Schuh + * \date 2020, July + */ + class ProducerZHTout : public stream::EDProducer<> { + public: + explicit ProducerZHTout(const ParameterSet&); + ~ProducerZHTout() override {} + + private: + void beginRun(const Run&, const EventSetup&) override; + void produce(Event&, const EventSetup&) override; + virtual void endJob() {} + + // ED input token of sf stubs + EDGetTokenT edGetToken_; + // ED output token of TTTracks + EDPutTokenT>> edPutToken_; + // Setup token + ESGetToken esGetTokenSetup_; + // DataFormats token + ESGetToken esGetTokenDataFormats_; + // configuration + ParameterSet iConfig_; + // helper class to store configurations + const Setup* setup_; + // helper class to extract structured data from tt::Frames + const DataFormats* dataFormats_; + }; + + ProducerZHTout::ProducerZHTout(const ParameterSet& iConfig) : iConfig_(iConfig) { + const string& label = iConfig.getParameter("LabelZHT"); + const string& branchAcceptedStubs = iConfig.getParameter("BranchAcceptedStubs"); + const string& branchAcceptedTracks = iConfig.getParameter("BranchAcceptedTracks"); + // book in- and output ED products + edGetToken_ = consumes(InputTag(label, branchAcceptedStubs)); + edPutToken_ = produces>>(branchAcceptedTracks); + // book ES products + esGetTokenSetup_ = esConsumes(); + esGetTokenDataFormats_ = esConsumes(); + // initial ES products + setup_ = nullptr; + dataFormats_ = nullptr; + } + + void ProducerZHTout::beginRun(const Run& iRun, const EventSetup& iSetup) { + // helper class to store configurations + setup_ = &iSetup.getData(esGetTokenSetup_); + if (!setup_->configurationSupported()) + return; + // check process history if desired + if (iConfig_.getParameter("CheckHistory")) + setup_->checkHistory(iRun.processHistory()); + // helper class to extract structured data from tt::Frames + dataFormats_ = &iSetup.getData(esGetTokenDataFormats_); + } + + void ProducerZHTout::produce(Event& iEvent, const EventSetup& iSetup) { + const DataFormat& dfCot = dataFormats_->format(Variable::cot, Process::zht); + const DataFormat& dfZT = dataFormats_->format(Variable::zT, Process::zht); + const DataFormat& dfPhiT = dataFormats_->format(Variable::phiT, Process::zht); + const DataFormat& dfinv2R = dataFormats_->format(Variable::inv2R, Process::zht); + // empty SFout product + deque> ttTracks; + // read in SF Product and produce SFout product + if (setup_->configurationSupported()) { + Handle handle; + iEvent.getByToken(edGetToken_, handle); + const StreamsStub& streams = *handle.product(); + for (int region = 0; region < setup_->numRegions(); region++) { + for (int channel = 0; channel < dataFormats_->numChannel(Process::zht); channel++) { + const int index = region * dataFormats_->numChannel(Process::zht) + channel; + // convert stream to stubs + const StreamStub& stream = streams[index]; + vector stubs; + stubs.reserve(stream.size()); + for (const FrameStub& frame : stream) + if (frame.first.isNonnull()) + stubs.emplace_back(frame, dataFormats_); + // form tracks + int i(0); + for (auto it = stubs.begin(); it != stubs.end();) { + const auto start = it; + const int id = it->trackId(); + auto different = [id](const StubZHT& stub) { return id != stub.trackId(); }; + it = find_if(it, stubs.end(), different); + vector ttStubRefs; + ttStubRefs.reserve(distance(start, it)); + transform(start, it, back_inserter(ttStubRefs), [](const StubZHT& stub) { return stub.ttStubRef(); }); + const double zT = dfZT.floating(start->zT()); + const double cot = dfCot.floating(start->cot()); + const double phiT = dfPhiT.floating(start->phiT()); + const double inv2R = dfinv2R.floating(start->inv2R()); + ttTracks.emplace_back(inv2R, phiT, cot, zT, 0., 0., 0., 0., 0., 0, 0, 0.); + ttTracks.back().setStubRefs(ttStubRefs); + ttTracks.back().setPhiSector(start->sectorPhi() + region * setup_->numSectorsPhi()); + ttTracks.back().setEtaSector(start->sectorEta()); + ttTracks.back().setTrackSeedType(start->trackId()); + if (i++ == setup_->zhtMaxTracks()) + break; + } + } + } + } + // store product + iEvent.emplace(edPutToken_, ttTracks.begin(), ttTracks.end()); + } + +} // namespace trackerTFP + +DEFINE_FWK_MODULE(trackerTFP::ProducerZHTout); \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/python/Analyzer_cff.py b/L1Trigger/TrackerTFP/python/Analyzer_cff.py new file mode 100644 index 0000000000000..fb694fbf61362 --- /dev/null +++ b/L1Trigger/TrackerTFP/python/Analyzer_cff.py @@ -0,0 +1,12 @@ +import FWCore.ParameterSet.Config as cms + +from L1Trigger.TrackerTFP.Analyzer_cfi import TrackerTFPAnalyzer_params +from L1Trigger.TrackerTFP.Producer_cfi import TrackerTFPProducer_params + +TrackerTFPAnalyzerGP = cms.EDAnalyzer( 'trackerTFP::AnalyzerGP', TrackerTFPAnalyzer_params, TrackerTFPProducer_params ) +TrackerTFPAnalyzerHT = cms.EDAnalyzer( 'trackerTFP::AnalyzerHT', TrackerTFPAnalyzer_params, TrackerTFPProducer_params ) +TrackerTFPAnalyzerMHT = cms.EDAnalyzer( 'trackerTFP::AnalyzerMHT', TrackerTFPAnalyzer_params, TrackerTFPProducer_params ) +TrackerTFPAnalyzerZHT = cms.EDAnalyzer( 'trackerTFP::AnalyzerZHT', TrackerTFPAnalyzer_params, TrackerTFPProducer_params ) +TrackerTFPAnalyzerKFin = cms.EDAnalyzer( 'trackerTFP::AnalyzerKFin', TrackerTFPAnalyzer_params, TrackerTFPProducer_params ) +TrackerTFPAnalyzerKF = cms.EDAnalyzer( 'trackerTFP::AnalyzerKF', TrackerTFPAnalyzer_params, TrackerTFPProducer_params ) +TrackerTFPAnalyzerTT = cms.EDAnalyzer( 'trackerTFP::AnalyzerTT', TrackerTFPAnalyzer_params, TrackerTFPProducer_params ) \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/python/Analyzer_cfi.py b/L1Trigger/TrackerTFP/python/Analyzer_cfi.py new file mode 100644 index 0000000000000..08a0518d2e852 --- /dev/null +++ b/L1Trigger/TrackerTFP/python/Analyzer_cfi.py @@ -0,0 +1,10 @@ +import FWCore.ParameterSet.Config as cms + +TrackerTFPAnalyzer_params = cms.PSet ( + + UseMCTruth = cms.bool( True ), # enables analyze of TPs + InputTagReconstructable = cms.InputTag("StubAssociator", "Reconstructable"), # + InputTagSelection = cms.InputTag("StubAssociator", "UseForAlgEff"), # + + +) \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/python/Customize_cff.py b/L1Trigger/TrackerTFP/python/Customize_cff.py new file mode 100644 index 0000000000000..1d7128d22f806 --- /dev/null +++ b/L1Trigger/TrackerTFP/python/Customize_cff.py @@ -0,0 +1,7 @@ +import FWCore.ParameterSet.Config as cms + +def setupUseTMTT(process): + process.TrackTriggerDataFormats.UseHybrid = False + process.TrackTriggerSetup.TrackingParticle.MinPt = 3.0 + process.TrackTriggerSetup.Firmware.MaxdPhi = 0.01 + return process \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/python/Demonstrator_cff.py b/L1Trigger/TrackerTFP/python/Demonstrator_cff.py new file mode 100644 index 0000000000000..7555f78fd84bb --- /dev/null +++ b/L1Trigger/TrackerTFP/python/Demonstrator_cff.py @@ -0,0 +1,8 @@ +import FWCore.ParameterSet.Config as cms + +from L1Trigger.TrackerTFP.Demonstrator_cfi import TrackTriggerDemonstrator_params +from L1Trigger.TrackerTFP.Producer_cfi import TrackerTFPProducer_params + +TrackTriggerDemonstrator = cms.ESProducer("trackerTFP::ProducerDemonstrator", TrackTriggerDemonstrator_params) + +TrackerTFPDemonstrator = cms.EDAnalyzer("trackerTFP::AnalyzerDemonstrator", TrackTriggerDemonstrator_params, TrackerTFPProducer_params) \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/python/Demonstrator_cfi.py b/L1Trigger/TrackerTFP/python/Demonstrator_cfi.py new file mode 100644 index 0000000000000..3c696fbb3bc33 --- /dev/null +++ b/L1Trigger/TrackerTFP/python/Demonstrator_cfi.py @@ -0,0 +1,11 @@ +# configuration of Demonstrator. +import FWCore.ParameterSet.Config as cms + +TrackTriggerDemonstrator_params = cms.PSet ( + + LabelIn = cms.string( "TrackerTFPProducerKFin" ), # + LabelOut = cms.string( "TrackerTFPProducerKF" ), # + DirIPBB = cms.string( "/heplnw039/tschuh/work/proj/kf/" ), # path to ipbb proj area + RunTime = cms.double( 6.0 ) # runtime in us + +) \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/python/KalmanFilterFormats_cff.py b/L1Trigger/TrackerTFP/python/KalmanFilterFormats_cff.py new file mode 100644 index 0000000000000..23d4f03c776a0 --- /dev/null +++ b/L1Trigger/TrackerTFP/python/KalmanFilterFormats_cff.py @@ -0,0 +1,5 @@ +import FWCore.ParameterSet.Config as cms + +from L1Trigger.TrackerTFP.KalmanFilterFormats_cfi import TrackTriggerKalmanFilterFormats_params + +TrackTriggerKalmanFilterFormats = cms.ESProducer("trackerTFP::ProducerFormatsKF", TrackTriggerKalmanFilterFormats_params) \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/python/KalmanFilterFormats_cfi.py b/L1Trigger/TrackerTFP/python/KalmanFilterFormats_cfi.py new file mode 100644 index 0000000000000..742637ef59e04 --- /dev/null +++ b/L1Trigger/TrackerTFP/python/KalmanFilterFormats_cfi.py @@ -0,0 +1,75 @@ +# configuration of internal KF variable bases which can be shifted by powers of 2 w.r.t. KF output track parameter +# TrackerTFPProducer_params.PrintKFDebug printouts unused MSB for each variable, so that one could consider decreasing the basseshift by that amount +# numerical instabillity (negative C00, C11, C22, C33) requires smaller baseshifts of related variables (rx, Sxx, Kxx, Rxx, invRxx) +# if a variable overflows an Exception will be thrown and the corresponding baseshift needs to be increased. +import FWCore.ParameterSet.Config as cms + +TrackTriggerKalmanFilterFormats_params = cms.PSet ( + + tmtt = cms.PSet ( + BaseShiftx0 = cms.int32( -2 ), + BaseShiftx1 = cms.int32( -9 ), + BaseShiftx2 = cms.int32( -5 ), + BaseShiftx3 = cms.int32( -6 ), + BaseShiftv0 = cms.int32( -6 ), + BaseShiftv1 = cms.int32( 7 ), + BaseShiftr0 = cms.int32( -7 ), + BaseShiftr1 = cms.int32( -4 ), + BaseShiftS00 = cms.int32( -2 ), + BaseShiftS01 = cms.int32( -7 ), + BaseShiftS12 = cms.int32( 3 ), + BaseShiftS13 = cms.int32( 1 ), + BaseShiftK00 = cms.int32( -16 ), + BaseShiftK10 = cms.int32( -23 ), + BaseShiftK21 = cms.int32( -22 ), + BaseShiftK31 = cms.int32( -23 ), + BaseShiftR00 = cms.int32( -5 ), + BaseShiftR11 = cms.int32( 6 ), + BaseShiftInvR00Approx = cms.int32( -26 ), + BaseShiftInvR11Approx = cms.int32( -37 ), + BaseShiftInvR00Cor = cms.int32( -15 ), + BaseShiftInvR11Cor = cms.int32( -15 ), + BaseShiftInvR00 = cms.int32( -24 ), + BaseShiftInvR11 = cms.int32( -34 ), + BaseShiftC00 = cms.int32( 5 ), + BaseShiftC01 = cms.int32( -3 ), + BaseShiftC11 = cms.int32( -7 ), + BaseShiftC22 = cms.int32( 3 ), + BaseShiftC23 = cms.int32( 0 ), + BaseShiftC33 = cms.int32( 1 ) + ), + + hybrid = cms.PSet ( + BaseShiftx0 = cms.int32( -4 ), + BaseShiftx1 = cms.int32( -10 ), + BaseShiftx2 = cms.int32( -2 ), + BaseShiftx3 = cms.int32( -3 ), + BaseShiftv0 = cms.int32( -4 ), + BaseShiftv1 = cms.int32( 8 ), + BaseShiftr0 = cms.int32( -9 ), + BaseShiftr1 = cms.int32( -1 ), + BaseShiftS00 = cms.int32( 0 ), + BaseShiftS01 = cms.int32( -7 ), + BaseShiftS12 = cms.int32( 3 ), + BaseShiftS13 = cms.int32( 1 ), + BaseShiftK00 = cms.int32( -16 ), + BaseShiftK10 = cms.int32( -22 ), + BaseShiftK21 = cms.int32( -22 ), + BaseShiftK31 = cms.int32( -23 ), + BaseShiftR00 = cms.int32( -4 ), + BaseShiftR11 = cms.int32( 7 ), + BaseShiftInvR00Approx = cms.int32( -27 ), + BaseShiftInvR11Approx = cms.int32( -38 ), + BaseShiftInvR00Cor = cms.int32( -15 ), + BaseShiftInvR11Cor = cms.int32( -15 ), + BaseShiftInvR00 = cms.int32( -23 ), + BaseShiftInvR11 = cms.int32( -33 ), + BaseShiftC00 = cms.int32( 5 ), + BaseShiftC01 = cms.int32( -3 ), + BaseShiftC11 = cms.int32( -7 ), + BaseShiftC22 = cms.int32( 3 ), + BaseShiftC23 = cms.int32( 0 ), + BaseShiftC33 = cms.int32( 1 ) + ), + +) \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/python/ProducerES_cff.py b/L1Trigger/TrackerTFP/python/ProducerES_cff.py new file mode 100644 index 0000000000000..b7654b1054e43 --- /dev/null +++ b/L1Trigger/TrackerTFP/python/ProducerES_cff.py @@ -0,0 +1,5 @@ +import FWCore.ParameterSet.Config as cms + +from L1Trigger.TrackerTFP.ProducerES_cfi import TrackTriggerDataFormats_params + +TrackTriggerDataFormats = cms.ESProducer("trackerTFP::ProducerES", TrackTriggerDataFormats_params) \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/python/ProducerES_cfi.py b/L1Trigger/TrackerTFP/python/ProducerES_cfi.py new file mode 100644 index 0000000000000..aeffbf910e9f8 --- /dev/null +++ b/L1Trigger/TrackerTFP/python/ProducerES_cfi.py @@ -0,0 +1,28 @@ +import FWCore.ParameterSet.Config as cms + +TrackTriggerDataFormats_params = cms.PSet ( + + UseHybrid = cms.bool( True ), + + ZHoughTransform = cms.PSet ( + + NumBinsZT = cms.int32( 2 ), + NumBinsCot = cms.int32( 2 ), + NumStages = cms.int32( 5 ) + + ), + + KalmanFilter = cms.PSet ( + + RangeFactor = cms.double( 2.0 ) # search window of each track parameter in initial uncertainties + + ), + + DuplicateRemoval = cms.PSet ( + WidthPhi0 = cms.int32( 12 ), # number of bist used for phi0 + WidthQoverPt = cms.int32( 15 ), # number of bist used for qOverPt + WidthCot = cms.int32( 16 ), # number of bist used for cot(theta) + WidthZ0 = cms.int32( 12 ) # number of bist used for z0 + ), + +) \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/python/ProducerLayerEncoding_cff.py b/L1Trigger/TrackerTFP/python/ProducerLayerEncoding_cff.py new file mode 100644 index 0000000000000..14dd59d610b31 --- /dev/null +++ b/L1Trigger/TrackerTFP/python/ProducerLayerEncoding_cff.py @@ -0,0 +1,5 @@ +import FWCore.ParameterSet.Config as cms + +from L1Trigger.TrackerTFP.ProducerLayerEncoding_cfi import TrackTriggerLayerEncoding_params + +TrackTriggerLayerEncoding = cms.ESProducer("trackerTFP::ProducerLayerEncoding", TrackTriggerLayerEncoding_params) \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/python/ProducerLayerEncoding_cfi.py b/L1Trigger/TrackerTFP/python/ProducerLayerEncoding_cfi.py new file mode 100644 index 0000000000000..aff3ae8b1b195 --- /dev/null +++ b/L1Trigger/TrackerTFP/python/ProducerLayerEncoding_cfi.py @@ -0,0 +1,7 @@ +import FWCore.ParameterSet.Config as cms + +TrackTriggerLayerEncoding_params = cms.PSet ( + + + +) \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/python/Producer_cff.py b/L1Trigger/TrackerTFP/python/Producer_cff.py new file mode 100644 index 0000000000000..77d45f6059195 --- /dev/null +++ b/L1Trigger/TrackerTFP/python/Producer_cff.py @@ -0,0 +1,18 @@ +# Produce L1 tracks with TMTT C++ emulation +import FWCore.ParameterSet.Config as cms + +from L1Trigger.TrackTrigger.ProducerSetup_cff import TrackTriggerSetup +from L1Trigger.TrackerTFP.Producer_cfi import TrackerTFPProducer_params +from L1Trigger.TrackerTFP.ProducerES_cff import TrackTriggerDataFormats +from L1Trigger.TrackerTFP.ProducerLayerEncoding_cff import TrackTriggerLayerEncoding +from L1Trigger.TrackerTFP.KalmanFilterFormats_cff import TrackTriggerKalmanFilterFormats + +TrackerTFPProducerGP = cms.EDProducer( 'trackerTFP::ProducerGP', TrackerTFPProducer_params ) +TrackerTFPProducerHT = cms.EDProducer( 'trackerTFP::ProducerHT', TrackerTFPProducer_params ) +TrackerTFPProducerMHT = cms.EDProducer( 'trackerTFP::ProducerMHT', TrackerTFPProducer_params ) +TrackerTFPProducerZHT = cms.EDProducer( 'trackerTFP::ProducerZHT', TrackerTFPProducer_params ) +TrackerTFPProducerZHTout = cms.EDProducer( 'trackerTFP::ProducerZHTout', TrackerTFPProducer_params ) +TrackerTFPProducerKFin = cms.EDProducer( 'trackerTFP::ProducerKFin', TrackerTFPProducer_params ) +TrackerTFPProducerKF = cms.EDProducer( 'trackerTFP::ProducerKF', TrackerTFPProducer_params ) +TrackerTFPProducerTT = cms.EDProducer( 'trackerTFP::ProducerTT', TrackerTFPProducer_params ) +TrackerTFPProducerAS = cms.EDProducer( 'trackerTFP::ProducerAS', TrackerTFPProducer_params ) \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/python/Producer_cfi.py b/L1Trigger/TrackerTFP/python/Producer_cfi.py new file mode 100644 index 0000000000000..54118ba7fe58a --- /dev/null +++ b/L1Trigger/TrackerTFP/python/Producer_cfi.py @@ -0,0 +1,24 @@ +import FWCore.ParameterSet.Config as cms + +TrackerTFPProducer_params = cms.PSet ( + + LabelDTC = cms.string( "TrackerDTCProducer" ), # + LabelGP = cms.string( "TrackerTFPProducerGP" ), # + LabelHT = cms.string( "TrackerTFPProducerHT" ), # + LabelMHT = cms.string( "TrackerTFPProducerMHT" ), # + LabelZHT = cms.string( "TrackerTFPProducerZHT" ), # + LabelZHTout = cms.string( "TrackerTFPProducerZHTout" ), # + LabelKFin = cms.string( "TrackerTFPProducerKFin" ), # + LabelKF = cms.string( "TrackerTFPProducerKF" ), # + LabelDR = cms.string( "TrackerTFPProducerDR" ), # + LabelTT = cms.string( "TrackerTFPProducerTT" ), # + LabelAS = cms.string( "TrackerTFPProducerAS" ), # + BranchAcceptedStubs = cms.string( "StubAccepted" ), # branch for prodcut with passed stubs + BranchAcceptedTracks = cms.string( "TrackAccepted" ), # branch for prodcut with passed tracks + BranchLostStubs = cms.string( "StubLost" ), # branch for prodcut with lost stubs + BranchLostTracks = cms.string( "TracksLost" ), # branch for prodcut with lost tracks + CheckHistory = cms.bool ( False ), # checks if input sample production is configured as current process + EnableTruncation = cms.bool ( True ), # enable emulation of truncation, lost stubs are filled in BranchLost + PrintKFDebug = cms.bool ( False ) # print end job internal unused MSB + +) \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/src/DataFormats.cc b/L1Trigger/TrackerTFP/src/DataFormats.cc new file mode 100644 index 0000000000000..c1cf78285c04d --- /dev/null +++ b/L1Trigger/TrackerTFP/src/DataFormats.cc @@ -0,0 +1,896 @@ +#include "L1Trigger/TrackerTFP/interface/DataFormats.h" +#include "L1Trigger/TrackTrigger/interface/StubPtConsistency.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace edm; +using namespace tt; + +namespace trackerTFP { + + // default constructor, trying to needs space as proper constructed object + DataFormats::DataFormats() + : numDataFormats_(0), + formats_(+Variable::end, std::vector(+Process::end, nullptr)), + numUnusedBitsStubs_(+Process::end, TTBV::S_), + numUnusedBitsTracks_(+Process::end, TTBV::S_), + numChannel_(+Process::end, 0) { + setup_ = nullptr; + countFormats(); + dataFormats_.reserve(numDataFormats_); + numStreams_.reserve(+Process::end); + numStreamsStubs_.reserve(+Process::end); + numStreamsTracks_.reserve(+Process::end); + } + + // method to count number of unique data formats + template + void DataFormats::countFormats() { + if constexpr (config_[+v][+p] == p) + numDataFormats_++; + if constexpr (++p != Process::end) + countFormats(); + else if constexpr (++v != Variable::end) + countFormats<++v>(); + } + + // proper constructor + DataFormats::DataFormats(const ParameterSet& iConfig, const Setup* setup) : DataFormats() { + iConfig_ = iConfig; + setup_ = setup; + fillDataFormats(); + for (const Process p : Processes) + for (const Variable v : stubs_[+p]) + numUnusedBitsStubs_[+p] -= formats_[+v][+p] ? formats_[+v][+p]->width() : 0; + for (const Process p : Processes) + for (const Variable v : tracks_[+p]) + numUnusedBitsTracks_[+p] -= formats_[+v][+p] ? formats_[+v][+p]->width() : 0; + numChannel_[+Process::dtc] = setup_->numDTCsPerRegion(); + numChannel_[+Process::pp] = setup_->numDTCsPerTFP(); + numChannel_[+Process::gp] = setup_->numSectors(); + numChannel_[+Process::ht] = setup_->htNumBinsInv2R(); + numChannel_[+Process::mht] = setup_->htNumBinsInv2R(); + numChannel_[+Process::zht] = setup_->htNumBinsInv2R(); + numChannel_[+Process::kfin] = setup_->kfNumWorker() * setup_->numLayers(); + numChannel_[+Process::kf] = setup_->kfNumWorker(); + transform(numChannel_.begin(), numChannel_.end(), back_inserter(numStreams_), [this](int channel) { + return channel * setup_->numRegions(); + }); + numStreamsStubs_ = numStreams_; + numStreamsStubs_[+Process::kf] = numStreams_[+Process::kfin]; + numStreamsTracks_ = vector(+Process::end, 0); + numStreamsTracks_[+Process::kfin] = numStreams_[+Process::kf]; + numStreamsTracks_[+Process::kf] = numStreams_[+Process::kf]; + } + + // constructs data formats of all unique used variables and flavours + template + void DataFormats::fillDataFormats() { + if constexpr (config_[+v][+p] == p) { + dataFormats_.emplace_back(Format(iConfig_, setup_)); + fillFormats(); + } + if constexpr (++p != Process::end) + fillDataFormats(); + else if constexpr (++v != Variable::end) + fillDataFormats<++v>(); + } + + // helper (loop) data formats of all unique used variables and flavours + template + void DataFormats::fillFormats() { + if (config_[+v][+it] == p) { + formats_[+v][+it] = &dataFormats_.back(); + } + if constexpr (++it != Process::end) + fillFormats(); + } + + // converts bits to ntuple of variables + template + void DataFormats::convertStub(Process p, const Frame& bv, tuple& data) const { + TTBV ttBV(bv); + extractStub(p, ttBV, data); + } + + // helper (loop) to convert bits to ntuple of variables + template + void DataFormats::extractStub(Process p, TTBV& ttBV, std::tuple& data) const { + Variable v = *next(stubs_[+p].begin(), sizeof...(Ts) - 1 - it); + formats_[+v][+p]->extract(ttBV, get(data)); + if constexpr (it + 1 != sizeof...(Ts)) + extractStub(p, ttBV, data); + } + + // converts ntuple of variables to bits + template + void DataFormats::convertStub(Process p, const std::tuple& data, Frame& bv) const { + TTBV ttBV(1, numUnusedBitsStubs_[+p]); + attachStub(p, data, ttBV); + bv = ttBV.bs(); + } + + // helper (loop) to convert ntuple of variables to bits + template + void DataFormats::attachStub(Process p, const tuple& data, TTBV& ttBV) const { + Variable v = *next(stubs_[+p].begin(), it); + formats_[+v][+p]->attach(get(data), ttBV); + if constexpr (it + 1 != sizeof...(Ts)) + attachStub(p, data, ttBV); + } + + // converts bits to ntuple of variables + template + void DataFormats::convertTrack(Process p, const Frame& bv, tuple& data) const { + TTBV ttBV(bv); + extractTrack(p, ttBV, data); + } + + // helper (loop) to convert bits to ntuple of variables + template + void DataFormats::extractTrack(Process p, TTBV& ttBV, std::tuple& data) const { + Variable v = *next(tracks_[+p].begin(), sizeof...(Ts) - 1 - it); + formats_[+v][+p]->extract(ttBV, get(data)); + if constexpr (it + 1 != sizeof...(Ts)) + extractTrack(p, ttBV, data); + } + + // converts ntuple of variables to bits + template + void DataFormats::convertTrack(Process p, const std::tuple& data, Frame& bv) const { + TTBV ttBV(1, numUnusedBitsTracks_[+p]); + attachTrack(p, data, ttBV); + bv = ttBV.bs(); + } + + // helper (loop) to convert ntuple of variables to bits + template + void DataFormats::attachTrack(Process p, const tuple& data, TTBV& ttBV) const { + Variable v = *next(tracks_[+p].begin(), it); + formats_[+v][+p]->attach(get(data), ttBV); + if constexpr (it + 1 != sizeof...(Ts)) + attachTrack(p, data, ttBV); + } + + // construct Stub from Frame + template + Stub::Stub(const FrameStub& frame, const DataFormats* dataFormats, Process p) + : dataFormats_(dataFormats), p_(p), frame_(frame), trackId_(0) { + dataFormats_->convertStub(p, frame.second, data_); + } + + // construct Stub from other Stub + template + template + Stub::Stub(const Stub& stub, Ts... data) + : dataFormats_(stub.dataFormats()), + p_(++stub.p()), + frame_(stub.frame().first, Frame()), + data_(data...), + trackId_(0) {} + + // construct Stub from TTStubRef + template + Stub::Stub(const TTStubRef& ttStubRef, const DataFormats* dataFormats, Process p, Ts... data) + : dataFormats_(dataFormats), p_(p), frame_(ttStubRef, Frame()), data_(data...), trackId_(0) {} + + // construct StubPP from Frame + StubPP::StubPP(const FrameStub& frame, const DataFormats* formats) : Stub(frame, formats, Process::pp) { + for (int sectorEta = sectorEtaMin(); sectorEta <= sectorEtaMax(); sectorEta++) + for (int sectorPhi = 0; sectorPhi < width(Variable::sectorsPhi); sectorPhi++) + sectors_[sectorEta * width(Variable::sectorsPhi) + sectorPhi] = sectorsPhi()[sectorPhi]; + } + + // construct StubGP from Frame + StubGP::StubGP(const FrameStub& frame, const DataFormats* formats, int sectorPhi, int sectorEta) + : Stub(frame, formats, Process::gp), sectorPhi_(sectorPhi), sectorEta_(sectorEta) { + const Setup* setup = dataFormats_->setup(); + inv2RBins_ = TTBV(0, setup->htNumBinsInv2R()); + for (int inv2R = inv2RMin(); inv2R <= inv2RMax(); inv2R++) + inv2RBins_.set(inv2R + inv2RBins_.size() / 2); + } + + // construct StubGP from StubPP + StubGP::StubGP(const StubPP& stub, int sectorPhi, int sectorEta) + : Stub(stub, stub.r(), stub.phi(), stub.z(), stub.layer(), stub.inv2RMin(), stub.inv2RMax()), + sectorPhi_(sectorPhi), + sectorEta_(sectorEta) { + const Setup* setup = dataFormats_->setup(); + get<1>(data_) -= (sectorPhi_ - .5) * setup->baseSector(); + get<2>(data_) -= (r() + dataFormats_->chosenRofPhi()) * setup->sectorCot(sectorEta_); + dataFormats_->convertStub(p_, data_, frame_.second); + } + + // construct StubHT from Frame + StubHT::StubHT(const FrameStub& frame, const DataFormats* formats, int inv2R) + : Stub(frame, formats, Process::ht), inv2R_(inv2R) { + fillTrackId(); + } + + // construct StubHT from StubGP and HT cell assignment + StubHT::StubHT(const StubGP& stub, int phiT, int inv2R) + : Stub(stub, stub.r(), stub.phi(), stub.z(), stub.layer(), stub.sectorPhi(), stub.sectorEta(), phiT), + inv2R_(inv2R) { + get<1>(data_) -= + format(Variable::inv2R).floating(this->inv2R()) * r() + format(Variable::phiT).floating(this->phiT()); + fillTrackId(); + dataFormats_->convertStub(p_, data_, frame_.second); + } + + void StubHT::fillTrackId() { + TTBV ttBV(bv()); + trackId_ = ttBV.extract(width(Variable::sectorPhi) + width(Variable::sectorEta) + width(Variable::phiT)); + } + + // construct StubMHT from Frame + StubMHT::StubMHT(const FrameStub& frame, const DataFormats* formats) : Stub(frame, formats, Process::mht) { + fillTrackId(); + } + + // construct StubMHT from StubHT and MHT cell assignment + StubMHT::StubMHT(const StubHT& stub, int phiT, int inv2R) + : Stub(stub, + stub.r(), + stub.phi(), + stub.z(), + stub.layer(), + stub.sectorPhi(), + stub.sectorEta(), + stub.phiT(), + stub.inv2R()) { + const Setup* setup = dataFormats_->setup(); + // update track (phIT, inv2R), and phi residuals w.r.t. track, to reflect MHT cell assignment. + get<6>(data_) = this->phiT() * setup->mhtNumBinsPhiT() + phiT; + get<7>(data_) = this->inv2R() * setup->mhtNumBinsInv2R() + inv2R; + get<1>(data_) -= base(Variable::inv2R) * (inv2R - .5) * r() + base(Variable::phiT) * (phiT - .5); + dataFormats_->convertStub(p_, data_, frame_.second); + fillTrackId(); + } + + // fills track id + void StubMHT::fillTrackId() { + TTBV ttBV(bv()); + trackId_ = ttBV.extract(width(Variable::sectorPhi) + width(Variable::sectorEta) + width(Variable::phiT) + + width(Variable::inv2R)); + } + + // construct StubZHT from Frame + StubZHT::StubZHT(const FrameStub& frame, const DataFormats* formats) : Stub(frame, formats, Process::zht) { + cot_ = 0.; + zT_ = 0.; + fillTrackId(); + } + + // construct StubZHT from StubMHT + StubZHT::StubZHT(const StubMHT& stub) + : Stub(stub, + stub.r(), + stub.phi(), + stub.z(), + stub.layer(), + stub.sectorPhi(), + stub.sectorEta(), + stub.phiT(), + stub.inv2R(), + 0, + 0) { + cot_ = 0.; + zT_ = 0.; + r_ = format(Variable::r).digi(this->r() + dataFormats_->chosenRofPhi() - dataFormats_->setup()->chosenRofZ()); + chi_ = stub.z(); + trackId_ = stub.trackId(); + } + + // + StubZHT::StubZHT(const StubZHT& stub, double zT, double cot, int id) + : Stub(stub.frame().first, + stub.dataFormats(), + Process::zht, + stub.r(), + stub.phi(), + stub.z(), + stub.layer(), + stub.sectorPhi(), + stub.sectorEta(), + stub.phiT(), + stub.inv2R(), + stub.zT(), + stub.cot()) { + // update track (zT, cot), and phi residuals w.r.t. track, to reflect ZHT cell assignment. + r_ = stub.r_; + cot_ = stub.cotf() + cot; + zT_ = stub.ztf() + zT; + chi_ = stub.z() - zT_ + r_ * cot_; + get<8>(data_) = format(Variable::zT).integer(zT_); + get<9>(data_) = format(Variable::cot).integer(cot_); + dataFormats_->convertStub(p_, data_, frame_.second); + trackId_ = stub.trackId() * 4 + id; + } + + // + StubZHT::StubZHT(const StubZHT& stub, int cot, int zT) + : Stub(stub.frame().first, + stub.dataFormats(), + Process::zht, + stub.r(), + stub.phi(), + 0., + stub.layer(), + stub.sectorPhi(), + stub.sectorEta(), + stub.phiT(), + stub.inv2R(), + zT, + cot) { + get<2>(data_) = + format(Variable::z) + .digi(stub.z() - (format(Variable::zT).floating(zT) - stub.r_ * format(Variable::cot).floating(cot))); + dataFormats_->convertStub(p_, data_, frame_.second); + fillTrackId(); + } + + // fills track id + void StubZHT::fillTrackId() { + TTBV ttBV(bv()); + trackId_ = ttBV.extract(width(Variable::sectorPhi) + width(Variable::sectorEta) + width(Variable::phiT) + + width(Variable::inv2R) + width(Variable::zT) + width(Variable::cot)); + } + + // construct StubKFin from Frame + StubKFin::StubKFin(const FrameStub& frame, const DataFormats* formats, int layer) + : Stub(frame, formats, Process::kfin), layer_(layer) {} + + // construct StubKFin from StubZHT + StubKFin::StubKFin(const StubZHT& stub, double dPhi, double dZ, int layer) + : Stub(stub, stub.r(), stub.phi(), stub.z(), dPhi, dZ), layer_(layer) { + dataFormats_->convertStub(p_, data_, frame_.second); + } + + // construct StubKFin from TTStubRef + StubKFin::StubKFin(const TTStubRef& ttStubRef, + const DataFormats* dataFormats, + double r, + double phi, + double z, + double dPhi, + double dZ, + int layer) + : Stub(ttStubRef, dataFormats, Process::kfin, r, phi, z, dPhi, dZ), layer_(layer) { + dataFormats_->convertStub(p_, data_, frame_.second); + } + + // construct StubKF from Frame + StubKF::StubKF(const FrameStub& frame, const DataFormats* formats, int layer) + : Stub(frame, formats, Process::kf), layer_(layer) {} + + // construct StubKF from StubKFin + StubKF::StubKF(const StubKFin& stub, double inv2R, double phiT, double cot, double zT) + : Stub(stub, stub.r(), 0., 0., stub.dPhi(), stub.dZ()), layer_(stub.layer()) { + const Setup* setup = dataFormats_->setup(); + get<1>(data_) = format(Variable::phi).digi(stub.phi() - (phiT + this->r() * inv2R)); + const double d = + (dataFormats_->hybrid() ? setup->hybridChosenRofPhi() : setup->chosenRofPhi()) - setup->chosenRofZ(); + const double rz = format(Variable::r).digi(this->r() + d); + get<2>(data_) = format(Variable::z).digi(stub.z() - (zT + rz * cot)); + dataFormats_->convertStub(p_, data_, frame_.second); + } + + // construct Track from Frame + template + Track::Track(const FrameTrack& frame, const DataFormats* dataFormats, Process p) + : dataFormats_(dataFormats), p_(p), frame_(frame) { + dataFormats_->convertTrack(p_, frame.second, data_); + } + + // construct Track from other Track + template + template + Track::Track(const Track& track, Ts... data) + : dataFormats_(track.dataFormats()), p_(++track.p()), frame_(track.frame().first, Frame()), data_(data...) {} + + // construct Track from Stub + template + template + Track::Track(const Stub& stub, const TTTrackRef& ttTrackRef, Ts... data) + : dataFormats_(stub.dataFormats()), p_(++stub.p()), frame_(ttTrackRef, Frame()), data_(data...) {} + + // construct Track from TTTrackRef + template + Track::Track(const TTTrackRef& ttTrackRef, const DataFormats* dataFormats, Process p, Ts... data) + : dataFormats_(dataFormats), p_(p), frame_(ttTrackRef, Frame()), data_(data...) {} + + // construct TrackKFin from Frame + TrackKFin::TrackKFin(const FrameTrack& frame, const DataFormats* dataFormats, const vector& stubs) + : Track(frame, dataFormats, Process::kfin), stubs_(setup()->numLayers()), hitPattern_(0, setup()->numLayers()) { + vector nStubs(stubs_.size(), 0); + for (StubKFin* stub : stubs) + nStubs[stub->layer()]++; + for (int layer = 0; layer < dataFormats->setup()->numLayers(); layer++) + stubs_[layer].reserve(nStubs[layer]); + for (StubKFin* stub : stubs) { + const int layer = stub->layer(); + stubs_[layer].push_back(stub); + hitPattern_.set(layer); + } + } + + // construct TrackKFin from StubZHT + TrackKFin::TrackKFin(const StubZHT& stub, const TTTrackRef& ttTrackRef, const TTBV& maybePattern) + : Track(stub, ttTrackRef, maybePattern, stub.sectorPhi(), stub.sectorEta(), 0., 0., 0., 0.), + stubs_(setup()->numLayers()), + hitPattern_(0, setup()->numLayers()) { + get<3>(data_) = format(Variable::phiT, Process::mht).floating(stub.phiT()); + get<4>(data_) = format(Variable::inv2R, Process::mht).floating(stub.inv2R()); + get<5>(data_) = format(Variable::zT, Process::zht).floating(stub.zT()); + get<6>(data_) = format(Variable::cot, Process::zht).floating(stub.cot()); + dataFormats_->convertTrack(p_, data_, frame_.second); + } + + // construct TrackKFin from TTTrackRef + TrackKFin::TrackKFin(const TTTrackRef& ttTrackRef, + const DataFormats* dataFormats, + const TTBV& maybePattern, + double phiT, + double inv2R, + double zT, + double cot, + int sectorPhi, + int sectorEta) + : Track(ttTrackRef, dataFormats, Process::kfin, maybePattern, sectorPhi, sectorEta, phiT, inv2R, zT, cot), + stubs_(setup()->numLayers()), + hitPattern_(0, setup()->numLayers()) { + dataFormats_->convertTrack(p_, data_, frame_.second); + } + + vector TrackKFin::ttStubRefs(const TTBV& hitPattern, const vector& layerMap) const { + vector stubs; + stubs.reserve(hitPattern.count()); + for (int layer = 0; layer < setup()->numLayers(); layer++) + if (hitPattern[layer]) + stubs.push_back(stubs_[layer][layerMap[layer]]->ttStubRef()); + return stubs; + } + + // construct TrackKF from Frame + TrackKF::TrackKF(const FrameTrack& frame, const DataFormats* dataFormats) : Track(frame, dataFormats, Process::kf) {} + + // construct TrackKF from TrackKfin + TrackKF::TrackKF(const TrackKFin& track, double phiT, double inv2R, double zT, double cot) + : Track( + track, false, track.sectorPhi(), track.sectorEta(), track.phiT(), track.inv2R(), track.cot(), track.zT()) { + get<0>(data_) = abs(inv2R) < dataFormats_->format(Variable::inv2R, Process::zht).base() / 2. && + abs(phiT) < dataFormats_->format(Variable::phiT, Process::zht).base() / 2.; + get<3>(data_) += phiT; + get<4>(data_) += inv2R; + get<5>(data_) += cot; + get<6>(data_) += zT; + dataFormats_->convertTrack(p_, data_, frame_.second); + } + + // conversion to TTTrack with given stubs + TTTrack TrackKF::ttTrack(const vector& stubs) const { + const double invR = -this->inv2R() * 2.; + const double phi0 = + deltaPhi(this->phiT() - this->inv2R() * dataFormats_->chosenRofPhi() + + setup()->baseSector() * (this->sectorPhi() - .5) + setup()->baseRegion() * frame_.first->phiSector()); + const double cot = this->cot() + setup()->sectorCot(this->sectorEta()); + const double z0 = this->zT() - this->cot() * setup()->chosenRofZ(); + TTBV hitVector(0, setup()->numLayers()); + double chi2phi(0.); + double chi2z(0.); + vector ttStubRefs; + const int nLayer = stubs.size(); + ttStubRefs.reserve(nLayer); + for (const StubKF& stub : stubs) { + hitVector.set(stub.layer()); + const TTStubRef& ttStubRef = stub.ttStubRef(); + chi2phi += pow(stub.phi(), 2) / setup()->v0(ttStubRef, this->inv2R()); + chi2z += pow(stub.z(), 2) / setup()->v1(ttStubRef, cot); + ttStubRefs.push_back(ttStubRef); + } + static constexpr int nPar = 4; + static constexpr double d0 = 0.; + static constexpr double trkMVA1 = 0.; + static constexpr double trkMVA2 = 0.; + static constexpr double trkMVA3 = 0.; + const int hitPattern = hitVector.val(); + const double bField = setup()->bField(); + TTTrack ttTrack( + invR, phi0, cot, z0, d0, chi2phi, chi2z, trkMVA1, trkMVA2, trkMVA3, hitPattern, nPar, bField); + ttTrack.setStubRefs(ttStubRefs); + ttTrack.setPhiSector(frame_.first->phiSector()); + ttTrack.setEtaSector(this->sectorEta()); + ttTrack.setTrackSeedType(frame_.first->trackSeedType()); + ttTrack.setStubPtConsistency(StubPtConsistency::getConsistency( + ttTrack, setup()->trackerGeometry(), setup()->trackerTopology(), bField, nPar)); + return ttTrack; + } + + // construct TrackDR from Frame + TrackDR::TrackDR(const FrameTrack& frame, const DataFormats* dataFormats) : Track(frame, dataFormats, Process::dr) {} + + // construct TrackDR from TrackKF + TrackDR::TrackDR(const TrackKF& track) : Track(track, 0., 0., 0., 0.) { + get<0>(data_) = track.phiT() + track.inv2R() * dataFormats_->chosenRofPhi() + + dataFormats_->format(Variable::phi, Process::gp).range() * (track.sectorPhi() - .5); + get<1>(data_) = track.inv2R(); + get<2>(data_) = track.zT() - track.cot() * setup()->chosenRofZ(); + get<3>(data_) = track.cot() + setup()->sectorCot(track.sectorEta()); + dataFormats_->convertTrack(p_, data_, frame_.second); + } + + // conversion to TTTrack + TTTrack TrackDR::ttTrack() const { + const double inv2R = this->inv2R(); + const double phi0 = this->phi0(); + const double cot = this->cot(); + const double z0 = this->z0(); + static constexpr double d0 = 0.; + static constexpr double chi2phi = 0.; + static constexpr double chi2z = 0; + static constexpr double trkMVA1 = 0.; + static constexpr double trkMVA2 = 0.; + static constexpr double trkMVA3 = 0.; + static constexpr int hitPattern = 0.; + static constexpr int nPar = 4; + static constexpr double bField = 0.; + const int sectorPhi = frame_.first->phiSector(); + const int sectorEta = frame_.first->etaSector(); + TTTrack ttTrack( + inv2R, phi0, cot, z0, d0, chi2phi, chi2z, trkMVA1, trkMVA2, trkMVA3, hitPattern, nPar, bField); + ttTrack.setPhiSector(sectorPhi); + ttTrack.setEtaSector(sectorEta); + return ttTrack; + } + + template <> + Format::Format(const ParameterSet& iConfig, const Setup* setup) : DataFormat(true) { + range_ = 2. * M_PI / (double)(setup->numRegions() * setup->numSectorsPhi()); + base_ = range_ / (double)setup->htNumBinsPhiT(); + width_ = ceil(log2(setup->htNumBinsPhiT())); + } + + template <> + Format::Format(const ParameterSet& iConfig, const Setup* setup) : DataFormat(true) { + const Format ht(iConfig, setup); + range_ = ht.range(); + base_ = ht.base() / setup->mhtNumBinsPhiT(); + width_ = ceil(log2(setup->htNumBinsPhiT() * setup->mhtNumBinsPhiT())); + } + + template <> + Format::Format(const ParameterSet& iConfig, const Setup* setup) : DataFormat(true) { + const double mintPt = iConfig.getParameter("UseHybrid") ? setup->hybridMinPtCand() : setup->minPt(); + range_ = 2. * setup->invPtToDphi() / mintPt; + base_ = range_ / (double)setup->htNumBinsInv2R(); + width_ = ceil(log2(setup->htNumBinsInv2R())); + } + + template <> + Format::Format(const ParameterSet& iConfig, const Setup* setup) : DataFormat(true) { + const Format ht(iConfig, setup); + range_ = ht.range(); + base_ = ht.base() / setup->mhtNumBinsInv2R(); + width_ = ceil(log2(setup->htNumBinsInv2R() * setup->mhtNumBinsInv2R())); + } + + template <> + Format::Format(const ParameterSet& iConfig, const Setup* setup) : DataFormat(true) { + const double chosenRofPhi = + iConfig.getParameter("UseHybrid") ? setup->hybridChosenRofPhi() : setup->chosenRofPhi(); + width_ = setup->tmttWidthR(); + range_ = 2. * max(abs(setup->outerRadius() - chosenRofPhi), abs(setup->innerRadius() - chosenRofPhi)); + const Format phiT(iConfig, setup); + const Format inv2R(iConfig, setup); + base_ = phiT.base() / inv2R.base(); + const int shift = ceil(log2(range_ / base_ / pow(2., width_))); + base_ *= pow(2., shift); + } + + template <> + Format::Format(const ParameterSet& iConfig, const Setup* setup) : DataFormat(true) { + const Format phiT(iConfig, setup); + const Format inv2R(iConfig, setup); + const Format r(iConfig, setup); + range_ = phiT.range() + inv2R.range() * r.base() * pow(2., r.width()) / 4.; + const Format dtc(iConfig, setup); + base_ = dtc.base(); + width_ = ceil(log2(range_ / base_)); + } + + template <> + Format::Format(const ParameterSet& iConfig, const Setup* setup) : DataFormat(true) { + width_ = setup->tmttWidthPhi(); + const Format phiT(iConfig, setup); + const Format inv2R(iConfig, setup); + const Format r(iConfig, setup); + range_ = 2. * M_PI / (double)setup->numRegions() + inv2R.range() * r.base() * pow(2., r.width()) / 4.; + const int shift = ceil(log2(range_ / phiT.base() / pow(2., width_))); + base_ = phiT.base() * pow(2., shift); + } + + template <> + Format::Format(const ParameterSet& iConfig, const Setup* setup) : DataFormat(true) { + const Format phiT(iConfig, setup); + range_ = 2. * phiT.base(); + const Format gp(iConfig, setup); + base_ = gp.base(); + width_ = ceil(log2(range_ / base_)); + } + + template <> + Format::Format(const ParameterSet& iConfig, const Setup* setup) : DataFormat(true) { + const Format phiT(iConfig, setup); + range_ = 2. * phiT.base(); + const Format ht(iConfig, setup); + base_ = ht.base(); + width_ = ceil(log2(range_ / base_)); + } + + template <> + Format::Format(const ParameterSet& iConfig, const Setup* setup) : DataFormat(true) { + const Format phi(iConfig, setup); + const double rangeFactor = iConfig.getParameter("KalmanFilter").getParameter("RangeFactor"); + range_ = rangeFactor * phi.range(); + base_ = phi.base(); + width_ = ceil(log2(range_ / base_)); + } + + template <> + Format::Format(const ParameterSet& iConfig, const Setup* setup) : DataFormat(true) { + width_ = setup->tmttWidthZ(); + range_ = 2. * setup->halfLength(); + const Format r(iConfig, setup); + const int shift = ceil(log2(range_ / r.base())) - width_; + base_ = r.base() * pow(2., shift); + } + + template <> + Format::Format(const ParameterSet& iConfig, const Setup* setup) : DataFormat(true) { + range_ = setup->neededRangeChiZ(); + const Format dtc(iConfig, setup); + base_ = dtc.base(); + width_ = ceil(log2(range_ / base_)); + } + + template <> + Format::Format(const ParameterSet& iConfig, const Setup* setup) : DataFormat(true) { + const int numBinsZT = iConfig.getParameter("ZHoughTransform").getParameter("NumBinsZT"); + const int numStages = iConfig.getParameter("ZHoughTransform").getParameter("NumStages"); + width_ = ceil(log2(pow(numBinsZT, numStages))); + const Format z(iConfig, setup); + range_ = -1.; + for (int eta = 0; eta < setup->numSectorsEta(); eta++) + range_ = max(range_, (sinh(setup->boundarieEta(eta + 1)) - sinh(setup->boundarieEta(eta)))); + range_ *= setup->chosenRofZ(); + const int shift = ceil(log2(range_ / z.base() / pow(2., width_))); + base_ = z.base() * pow(2., shift); + } + + template <> + Format::Format(const ParameterSet& iConfig, const Setup* setup) : DataFormat(true) { + const int numBinsCot = iConfig.getParameter("ZHoughTransform").getParameter("NumBinsCot"); + const int numStages = iConfig.getParameter("ZHoughTransform").getParameter("NumStages"); + width_ = ceil(log2(pow(numBinsCot, numStages))); + const Format zT(iConfig, setup); + range_ = (zT.range() + 2. * setup->beamWindowZ()) / setup->chosenRofZ(); + const int shift = ceil(log2(range_)) - width_; + base_ = pow(2., shift); + } + + template <> + Format::Format(const ParameterSet& iConfig, const Setup* setup) : DataFormat(true) { + const Format zT(iConfig, setup); + const Format cot(iConfig, setup); + const double rangeR = + 2. * max(abs(setup->outerRadius() - setup->chosenRofZ()), abs(setup->innerRadius() - setup->chosenRofZ())); + range_ = zT.base() + cot.base() * rangeR + setup->maxdZ(); + const Format dtc(iConfig, setup); + base_ = dtc.base(); + width_ = ceil(log2(range_ / base_)); + /*const Format z(iConfig, setup); + width_ = z.width(); + range_ = z.range(); + base_ = z.base();*/ + } + + template <> + Format::Format(const ParameterSet& iConfig, const Setup* setup) : DataFormat(true) { + const Format zht(iConfig, setup); + range_ = zht.range() * pow(2, setup->kfinShiftRangeZ()); + base_ = zht.base(); + width_ = ceil(log2(range_ / base_)); + } + + template <> + Format::Format(const ParameterSet& iConfig, const Setup* setup) : DataFormat(true) { + const Format phiT(iConfig, setup); + const Format inv2R(iConfig, setup); + const double chosenRofPhi = + iConfig.getParameter("UseHybrid") ? setup->hybridChosenRofPhi() : setup->chosenRofPhi(); + const double rangeR = 2. * max(abs(setup->outerRadius() - chosenRofPhi), abs(setup->innerRadius() - chosenRofPhi)); + range_ = phiT.base() + inv2R.base() * rangeR + setup->maxdPhi(); + const Format dtc(iConfig, setup); + base_ = dtc.base(); + width_ = ceil(log2(range_ / base_)); + } + + template <> + Format::Format(const ParameterSet& iConfig, const Setup* setup) : DataFormat(true) { + const Format zht(iConfig, setup); + range_ = zht.range() * pow(2, setup->kfinShiftRangePhi()); + base_ = zht.base(); + width_ = ceil(log2(range_ / base_)); + } + + template <> + Format::Format(const ParameterSet& iConfig, const Setup* setup) : DataFormat(true) { + /*const Format z(iConfig, setup); + const double rangeFactor = iConfig.getParameter("KalmanFilter").getParameter("RangeFactor"); + range_ = rangeFactor * z.range(); + base_ = z.base(); + width_ = ceil(log2(range_ / base_));*/ + const Format zT(iConfig, setup); + const Format cot(iConfig, setup); + const double rangeR = + 2. * max(abs(setup->outerRadius() - setup->chosenRofZ()), abs(setup->innerRadius() - setup->chosenRofZ())); + range_ = zT.base() + cot.base() * rangeR + setup->maxdZ(); + const Format dtc(iConfig, setup); + base_ = dtc.base(); + const double rangeFactor = iConfig.getParameter("KalmanFilter").getParameter("RangeFactor"); + range_ *= rangeFactor; + width_ = ceil(log2(range_ / base_)); + } + + template <> + Format::Format(const ParameterSet& iConfig, const Setup* setup) : DataFormat(false) { + range_ = setup->numLayers(); + width_ = ceil(log2(range_)); + } + + template <> + Format::Format(const ParameterSet& iConfig, const Setup* setup) + : DataFormat(false) { + range_ = setup->numSectorsEta(); + width_ = ceil(log2(range_)); + } + + template <> + Format::Format(const ParameterSet& iConfig, const Setup* setup) + : DataFormat(false) { + range_ = setup->numSectorsPhi(); + width_ = ceil(log2(range_)); + } + + template <> + Format::Format(const ParameterSet& iConfig, const Setup* setup) + : DataFormat(false) { + range_ = setup->numSectorsPhi(); + width_ = setup->numSectorsPhi(); + } + + template <> + Format::Format(const edm::ParameterSet& iConfig, const Setup* setup) + : DataFormat(false) { + width_ = 1; + range_ = 1.; + } + + template <> + Format::Format(const edm::ParameterSet& iConfig, const Setup* setup) + : DataFormat(false) { + width_ = setup->numLayers(); + } + + template <> + Format::Format(const edm::ParameterSet& iConfig, const Setup* setup) : DataFormat(true) { + const Format inv2R(iConfig, setup); + const Format phiT(iConfig, setup); + const double chosenRofPhi = + iConfig.getParameter("UseHybrid") ? setup->hybridChosenRofPhi() : setup->chosenRofPhi(); + width_ = setup->tfpWidthPhi0(); + range_ = 2. * M_PI / (double)setup->numRegions() + inv2R.range() * chosenRofPhi; + base_ = phiT.base(); + const int shift = ceil(log2(range_ / base_ / pow(2., width_))); + base_ *= pow(2., shift); + } + + template <> + Format::Format(const edm::ParameterSet& iConfig, const Setup* setup) + : DataFormat(true) { + const Format inv2R(iConfig, setup); + width_ = setup->tfpWidthInv2R(); + range_ = inv2R.range(); + base_ = inv2R.base(); + const int shift = ceil(log2(range_ / base_ / pow(2., width_))); + base_ *= pow(2., shift); + } + + template <> + Format::Format(const edm::ParameterSet& iConfig, const Setup* setup) : DataFormat(true) { + const Format zT(iConfig, setup); + width_ = setup->tfpWidthZ0(); + range_ = 2. * setup->beamWindowZ(); + base_ = zT.base(); + const int shift = ceil(log2(range_ / base_ / pow(2., width_))); + base_ *= pow(2., shift); + } + + template <> + Format::Format(const edm::ParameterSet& iConfig, const Setup* setup) : DataFormat(true) { + const Format cot(iConfig, setup); + width_ = setup->tfpWidthCot(); + range_ = 2. * setup->maxCot(); + base_ = cot.base(); + const int shift = ceil(log2(range_ / base_ / pow(2., width_))); + base_ *= pow(2., shift); + } + + template <> + Format::Format(const edm::ParameterSet& iConfig, const Setup* setup) : DataFormat(true) { + const Format phi0(iConfig, setup); + const Format phiT(iConfig, setup); + const double rangeFactor = iConfig.getParameter("KalmanFilter").getParameter("RangeFactor"); + range_ = rangeFactor * phiT.range(); + base_ = phi0.base(); + width_ = ceil(log2(range_ / base_)); + } + + template <> + Format::Format(const edm::ParameterSet& iConfig, const Setup* setup) + : DataFormat(true) { + const Format dr(iConfig, setup); + const Format mht(iConfig, setup); + const double rangeFactor = iConfig.getParameter("KalmanFilter").getParameter("RangeFactor"); + range_ = mht.range() + rangeFactor * mht.base(); + base_ = dr.base(); + width_ = ceil(log2(range_ / base_)); + } + + template <> + Format::Format(const edm::ParameterSet& iConfig, const Setup* setup) : DataFormat(true) { + const Format z0(iConfig, setup); + const Format zT(iConfig, setup); + const double rangeFactor = iConfig.getParameter("KalmanFilter").getParameter("RangeFactor"); + range_ = zT.range() + rangeFactor * zT.base(); + base_ = z0.base(); + width_ = ceil(log2(range_ / base_)); + } + + template <> + Format::Format(const edm::ParameterSet& iConfig, const Setup* setup) : DataFormat(true) { + const Format dr(iConfig, setup); + const Format zht(iConfig, setup); + const double rangeFactor = iConfig.getParameter("KalmanFilter").getParameter("RangeFactor"); + range_ = zht.range() + rangeFactor * zht.base(); + base_ = dr.base(); + width_ = ceil(log2(range_ / base_)); + } + + template <> + Format::Format(const edm::ParameterSet& iConfig, const Setup* setup) + : DataFormat(false) { + const Format phi(iConfig, setup); + range_ = setup->maxdPhi(); + base_ = phi.base(); + width_ = ceil(log2(range_ / base_)); + } + + template <> + Format::Format(const edm::ParameterSet& iConfig, const Setup* setup) + : DataFormat(false) { + const Format z(iConfig, setup); + range_ = setup->maxdZ(); + base_ = z.base(); + width_ = ceil(log2(range_ / base_)); + } + +} // namespace trackerTFP diff --git a/L1Trigger/TrackerTFP/src/DataFormatsRcd.cc b/L1Trigger/TrackerTFP/src/DataFormatsRcd.cc new file mode 100644 index 0000000000000..d91903414dabc --- /dev/null +++ b/L1Trigger/TrackerTFP/src/DataFormatsRcd.cc @@ -0,0 +1,4 @@ +#include "L1Trigger/TrackerTFP/interface/DataFormatsRcd.h" +#include "FWCore/Framework/interface/eventsetuprecord_registration_macro.h" + +EVENTSETUP_RECORD_REG(trackerTFP::DataFormatsRcd); \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/src/Demonstrator.cc b/L1Trigger/TrackerTFP/src/Demonstrator.cc new file mode 100644 index 0000000000000..e4ba89e515003 --- /dev/null +++ b/L1Trigger/TrackerTFP/src/Demonstrator.cc @@ -0,0 +1,150 @@ +#include "L1Trigger/TrackerTFP/interface/Demonstrator.h" + +#include +#include +#include +#include + +using namespace std; +using namespace edm; +using namespace tt; + +namespace trackerTFP { + + Demonstrator::Demonstrator(const ParameterSet& iConfig, const Setup* setup) + : dirIPBB_(iConfig.getParameter("DirIPBB")), + runTime_(iConfig.getParameter("RunTime")), + dirIn_(dirIPBB_ + "in.txt"), + dirOut_(dirIPBB_ + "out.txt"), + dirPre_(dirIPBB_ + "pre.txt"), + dirDiff_(dirIPBB_ + "diff.txt"), + numFrames_(setup->numFramesIO()), + numFramesInfra_(setup->numFramesInfra()), + numRegions_(setup->numRegions()) {} + + // plays input through modelsim and compares result with output + bool Demonstrator::analyze(const vector>& input, const vector>& output) const { + stringstream ss; + // converts input into stringstream + convert(input, ss); + // play input through modelsim + sim(ss); + // converts output into stringstream + convert(output, ss); + // compares output with modelsim output + return compare(ss); + } + + // converts streams of bv into stringstream + void Demonstrator::convert(const vector>& bits, stringstream& ss) const { + // reset ss + ss.str(""); + ss.clear(); + // number of tranceiver in a quad + static constexpr int quad = 4; + const int numChannel = bits.size() / numRegions_; + const int voidChannel = numChannel % quad == 0 ? 0 : quad - numChannel % quad; + // start with header + ss << header(numChannel + voidChannel); + int nFrame(0); + // create one packet per region + for (int region = 0; region < numRegions_; region++) { + const int offset = region * numChannel; + // start with emp 6 frame gap + ss << infraGap(nFrame, numChannel + voidChannel); + for (int frame = 0; frame < numFrames_; frame++) { + // write one frame for all channel + ss << this->frame(nFrame); + for (int channel = 0; channel < numChannel; channel++) { + const vector& bvs = bits[offset + channel]; + ss << (frame < (int)bvs.size() ? hex(bvs[frame]) : hex(Frame())); + } + for (int channel = 0; channel < voidChannel; channel++) + ss << " 0v" << string(TTBV::S_ / 4, '0'); + ss << endl; + } + } + } + + // plays stringstream through modelsim + void Demonstrator::sim(const stringstream& ss) const { + // write ss to disk + fstream fs; + fs.open(dirIn_.c_str(), fstream::out); + fs << ss.rdbuf(); + fs.close(); + // run modelsim + stringstream cmd; + cmd << "cd " << dirIPBB_ << " && ./run_sim -quiet -c work.top -do 'run " << runTime_ + << "us' -do 'quit' &> /dev/null"; + system(cmd.str().c_str()); + } + + // compares stringstream with modelsim output + bool Demonstrator::compare(stringstream& ss) const { + // write ss to disk + fstream fs; + fs.open(dirPre_.c_str(), fstream::out); + fs << ss.rdbuf(); + fs.close(); + // use linux diff on disk + const string c = "diff " + dirPre_ + " " + dirOut_ + " &> " + dirDiff_; + system(c.c_str()); + ss.str(""); + ss.clear(); + // read diff output + fs.open(dirDiff_.c_str(), fstream::in); + ss << fs.rdbuf(); + fs.close(); + // count lines, 4 are expected + int n(0); + string token; + while (getline(ss, token)) + n++; + return n == 4; + } + + // creates emp file header + string Demonstrator::header(int numLinks) const { + stringstream ss; + // file header + ss << "Board CMSSW" << endl << " Quad/Chan :"; + // quad header + for (int link = 0; link < numLinks; link++) + ss << " q" << setfill('0') << setw(2) << link / 4 << "c" << link % 4 << " "; + ss << endl; + // link header + ss << " Link :"; + for (int link = 0; link < numLinks; link++) + ss << " " << setfill('0') << setw(3) << link << " "; + ss << endl; + return ss.str(); + } + + // creates 6 frame gap between packets + string Demonstrator::infraGap(int& nFrame, int numLinks) const { + stringstream ss; + for (int gap = 0; gap < numFramesInfra_; gap++) { + ss << frame(nFrame); + for (int link = 0; link < numLinks; link++) + ss << " 0v" << string(TTBV::S_ / 4, '0'); + ss << endl; + } + return ss.str(); + } + + // creates frame number + string Demonstrator::frame(int& nFrame) const { + stringstream ss; + ss << "Frame " << setfill('0') << setw(4) << nFrame++ << " :"; + return ss.str(); + } + + // converts bv into hex + string Demonstrator::hex(const Frame& bv) const { + stringstream ss; + ss << " 1v" << setfill('0') << setw(TTBV::S_ / 4) << std::hex << bv.to_ullong(); + return ss.str(); + } + +} // namespace trackerTFP \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/src/DemonstratorRcd.cc b/L1Trigger/TrackerTFP/src/DemonstratorRcd.cc new file mode 100644 index 0000000000000..b509b1884d32a --- /dev/null +++ b/L1Trigger/TrackerTFP/src/DemonstratorRcd.cc @@ -0,0 +1,4 @@ +#include "L1Trigger/TrackerTFP/interface/DemonstratorRcd.h" +#include "FWCore/Framework/interface/eventsetuprecord_registration_macro.h" + +EVENTSETUP_RECORD_REG(trackerTFP::DemonstratorRcd); \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/src/DistServer.cc b/L1Trigger/TrackerTFP/src/DistServer.cc new file mode 100644 index 0000000000000..9bb81d337e278 --- /dev/null +++ b/L1Trigger/TrackerTFP/src/DistServer.cc @@ -0,0 +1,61 @@ +#include "L1Trigger/TrackerTFP/interface/DistServer.h" +#include "L1Trigger/TrackerTFP/interface/DataFormats.h" + +#include +#include + +using namespace std; +using namespace trackerTFP; + +DistServer::DistServer(unsigned int nInputs, unsigned int nOutputs, unsigned int nInterleaving) + : nInputs_(nInputs), nOutputs_(nOutputs), nInterleaving_(nInterleaving), inputs_(nInputs_) { + for (unsigned int iInput = 0; iInput < this->nInputs(); ++iInput) { + addr_.emplace_back(this->nInterleaving(), 0); + for (unsigned int iInterleave = 0; iInterleave < this->nInterleaving(); ++iInterleave) { + addr_[iInput][iInterleave] = iInterleave; + } + } +} + +TrackKFOutSAPtrCollection DistServer::clock(TrackKFOutSAPtrCollection& data) { + for (unsigned int iInput = 0; iInput < nInputs(); ++iInput) { + if (data[iInput]->dataValid()) { + inputs()[iInput].push_back(data[iInput]); + } + } + + vector > lMap(nInputs(), vector(nOutputs())); + + TrackKFOutSAPtrCollection lInputs(nInputs(), std::make_shared()); + + std::vector >& addr = this->addr(); + + for (unsigned int iInput = 0; iInput < nInputs(); ++iInput) { + unsigned int lAddr = addr[iInput][0]; + if (lAddr < inputs()[iInput].size()) { + lInputs[iInput] = inputs()[iInput][lAddr]; + lMap[iInput][lInputs[iInput]->sortKey()] = true; + } + } + + for (unsigned int iInput = 0; iInput < nInputs(); ++iInput) { + vector& toRotate = addr[iInput]; + rotate(toRotate.begin(), toRotate.begin() + 1, toRotate.end()); + } + + TrackKFOutSAPtrCollection lOutputs(nOutputs(), std::make_shared()); + + unsigned int nOutputs = 0; + for (unsigned int iOutput = 0; iOutput < lOutputs.size(); ++iOutput) { + for (unsigned int iInput = 0; iInput < nInputs(); ++iInput) { + if (lMap[iInput][iOutput]) { + lOutputs[iOutput] = lInputs[iInput]; + addr[iInput].back() += this->nInterleaving(); + nOutputs++; + break; + } + } + } + + return lOutputs; +} \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/src/ES_DataFormats.cc b/L1Trigger/TrackerTFP/src/ES_DataFormats.cc new file mode 100644 index 0000000000000..cc4623ee9b136 --- /dev/null +++ b/L1Trigger/TrackerTFP/src/ES_DataFormats.cc @@ -0,0 +1,4 @@ +#include "FWCore/Utilities/interface/typelookup.h" +#include "L1Trigger/TrackerTFP/interface/DataFormats.h" + +TYPELOOKUP_DATA_REG(trackerTFP::DataFormats); \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/src/ES_Demonstrator.cc b/L1Trigger/TrackerTFP/src/ES_Demonstrator.cc new file mode 100644 index 0000000000000..7968e432b7bc4 --- /dev/null +++ b/L1Trigger/TrackerTFP/src/ES_Demonstrator.cc @@ -0,0 +1,4 @@ +#include "FWCore/Utilities/interface/typelookup.h" +#include "L1Trigger/TrackerTFP/interface/Demonstrator.h" + +TYPELOOKUP_DATA_REG(trackerTFP::Demonstrator); \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/src/ES_KalmanFilterFormats.cc b/L1Trigger/TrackerTFP/src/ES_KalmanFilterFormats.cc new file mode 100644 index 0000000000000..63576bc81448e --- /dev/null +++ b/L1Trigger/TrackerTFP/src/ES_KalmanFilterFormats.cc @@ -0,0 +1,4 @@ +#include "FWCore/Utilities/interface/typelookup.h" +#include "L1Trigger/TrackerTFP/interface/KalmanFilterFormats.h" + +TYPELOOKUP_DATA_REG(trackerTFP::KalmanFilterFormats); \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/src/ES_LayerEncoding.cc b/L1Trigger/TrackerTFP/src/ES_LayerEncoding.cc new file mode 100644 index 0000000000000..6a1428ea2030a --- /dev/null +++ b/L1Trigger/TrackerTFP/src/ES_LayerEncoding.cc @@ -0,0 +1,4 @@ +#include "FWCore/Utilities/interface/typelookup.h" +#include "L1Trigger/TrackerTFP/interface/LayerEncoding.h" + +TYPELOOKUP_DATA_REG(trackerTFP::LayerEncoding); \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/src/GeometricProcessor.cc b/L1Trigger/TrackerTFP/src/GeometricProcessor.cc new file mode 100644 index 0000000000000..f745ac9d3fa0e --- /dev/null +++ b/L1Trigger/TrackerTFP/src/GeometricProcessor.cc @@ -0,0 +1,131 @@ +#include "L1Trigger/TrackerTFP/interface/GeometricProcessor.h" + +#include +#include +#include +#include +#include + +using namespace std; +using namespace edm; +using namespace tt; + +namespace trackerTFP { + + GeometricProcessor::GeometricProcessor(const ParameterSet& iConfig, + const Setup* setup, + const DataFormats* dataFormats, + int region) + : enableTruncation_(iConfig.getParameter("EnableTruncation")), + setup_(setup), + dataFormats_(dataFormats), + region_(region), + input_(dataFormats_->numChannel(Process::gp), vector>(dataFormats_->numChannel(Process::pp))) {} + + // read in and organize input product (fill vector input_) + void GeometricProcessor::consume(const TTDTC& ttDTC) { + auto validFrame = [](int& sum, const FrameStub& frame) { return sum += frame.first.isNonnull() ? 1 : 0; }; + int nStubsPP(0); + for (int channel = 0; channel < dataFormats_->numChannel(Process::pp); channel++) { + const StreamStub& stream = ttDTC.stream(region_, channel); + nStubsPP += accumulate(stream.begin(), stream.end(), 0, validFrame); + } + stubsPP_.reserve(nStubsPP); + for (int channel = 0; channel < dataFormats_->numChannel(Process::pp); channel++) { + for (const FrameStub& frame : ttDTC.stream(region_, channel)) { + StubPP* stub = nullptr; + if (frame.first.isNonnull()) { + stubsPP_.emplace_back(frame, dataFormats_); + stub = &stubsPP_.back(); + } + for (int sector = 0; sector < dataFormats_->numChannel(Process::gp); sector++) + // adding gaps (nullptr) if no stub available or not in sector to emulate f/w + input_[sector][channel].push_back(stub && stub->inSector(sector) ? stub : nullptr); + } + } + // remove all gaps between end and last stub + for (vector>& input : input_) + for (deque& stubs : input) + for (auto it = stubs.end(); it != stubs.begin();) + it = (*--it) ? stubs.begin() : stubs.erase(it); + auto validStub = [](int& sum, StubPP* stub) { return sum += stub ? 1 : 0; }; + int nStubsGP(0); + for (const vector>& sector : input_) + for (const deque& channel : sector) + nStubsGP += accumulate(channel.begin(), channel.end(), 0, validStub); + stubsGP_.reserve(nStubsGP); + } + + // fill output products + void GeometricProcessor::produce(StreamsStub& accepted, StreamsStub& lost) { + for (int sector = 0; sector < dataFormats_->numChannel(Process::gp); sector++) { + vector>& inputs = input_[sector]; + vector> stacks(dataFormats_->numChannel(Process::pp)); + const int sectorPhi = sector % setup_->numSectorsPhi(); + const int sectorEta = sector / setup_->numSectorsPhi(); + auto size = [](int& sum, const deque& stubs) { return sum += stubs.size(); }; + const int nStubs = accumulate(inputs.begin(), inputs.end(), 0, size); + vector acceptedSector; + vector lostSector; + acceptedSector.reserve(nStubs); + lostSector.reserve(nStubs); + // clock accurate firmware emulation, each while trip describes one clock tick, one stub in and one stub out per tick + while (!all_of(inputs.begin(), inputs.end(), [](const deque& stubs) { return stubs.empty(); }) or + !all_of(stacks.begin(), stacks.end(), [](const deque& stubs) { return stubs.empty(); })) { + // fill input fifos + for (int channel = 0; channel < dataFormats_->numChannel(Process::pp); channel++) { + deque& stack = stacks[channel]; + StubPP* stub = pop_front(inputs[channel]); + if (stub) { + stubsGP_.emplace_back(*stub, sectorPhi, sectorEta); + if (enableTruncation_ && (int)stack.size() == setup_->gpDepthMemory() - 1) + lostSector.push_back(pop_front(stack)); + stack.push_back(&stubsGP_.back()); + } + } + // merge input fifos to one stream, prioritizing higher input channel over lower channel + bool nothingToRoute(true); + for (int channel = dataFormats_->numChannel(Process::pp) - 1; channel >= 0; channel--) { + StubGP* stub = pop_front(stacks[channel]); + if (stub) { + nothingToRoute = false; + acceptedSector.push_back(stub); + break; + } + } + if (nothingToRoute) + acceptedSector.push_back(nullptr); + } + // truncate if desired + if (enableTruncation_ && (int)acceptedSector.size() > setup_->numFrames()) { + const auto limit = next(acceptedSector.begin(), setup_->numFrames()); + copy_if(limit, acceptedSector.end(), back_inserter(lostSector), [](const StubGP* stub) { return stub; }); + acceptedSector.erase(limit, acceptedSector.end()); + } + // remove all gaps between end and last stub + for (auto it = acceptedSector.end(); it != acceptedSector.begin();) + it = (*--it) ? acceptedSector.begin() : acceptedSector.erase(it); + // fill products + auto put = [](const vector& stubs, StreamStub& stream) { + auto toFrame = [](StubGP* stub) { return stub ? stub->frame() : FrameStub(); }; + stream.reserve(stubs.size()); + transform(stubs.begin(), stubs.end(), back_inserter(stream), toFrame); + }; + const int index = region_ * dataFormats_->numChannel(Process::gp) + sector; + put(acceptedSector, accepted[index]); + put(lostSector, lost[index]); + } + } + + // remove and return first element of deque, returns nullptr if empty + template + T* GeometricProcessor::pop_front(deque& ts) const { + T* t = nullptr; + if (!ts.empty()) { + t = ts.front(); + ts.pop_front(); + } + return t; + } + +} // namespace trackerTFP \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/src/HoughTransform.cc b/L1Trigger/TrackerTFP/src/HoughTransform.cc new file mode 100644 index 0000000000000..dfaecf8ff7c65 --- /dev/null +++ b/L1Trigger/TrackerTFP/src/HoughTransform.cc @@ -0,0 +1,214 @@ +#include "L1Trigger/TrackerTFP/interface/HoughTransform.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace edm; +using namespace tt; + +namespace trackerTFP { + + HoughTransform::HoughTransform(const ParameterSet& iConfig, + const Setup* setup, + const DataFormats* dataFormats, + int region) + : enableTruncation_(iConfig.getParameter("EnableTruncation")), + setup_(setup), + dataFormats_(dataFormats), + inv2R_(dataFormats_->format(Variable::inv2R, Process::ht)), + phiT_(dataFormats_->format(Variable::phiT, Process::ht)), + region_(region), + input_(dataFormats_->numChannel(Process::ht), vector>(dataFormats_->numChannel(Process::gp))) {} + + // read in and organize input product (fill vector input_) + void HoughTransform::consume(const StreamsStub& streams) { + const int offset = region_ * dataFormats_->numChannel(Process::gp); + auto validFrame = [](int& sum, const FrameStub& frame) { return sum += frame.first.isNonnull() ? 1 : 0; }; + int nStubsGP(0); + for (int sector = 0; sector < dataFormats_->numChannel(Process::gp); sector++) { + const StreamStub& stream = streams[offset + sector]; + nStubsGP += accumulate(stream.begin(), stream.end(), 0, validFrame); + } + stubsGP_.reserve(nStubsGP); + for (int sector = 0; sector < dataFormats_->numChannel(Process::gp); sector++) { + const int sectorPhi = sector % setup_->numSectorsPhi(); + const int sectorEta = sector / setup_->numSectorsPhi(); + for (const FrameStub& frame : streams[offset + sector]) { + // Store input stubs in vector, so rest of HT algo can work with pointers to them (saves CPU) + StubGP* stub = nullptr; + if (frame.first.isNonnull()) { + stubsGP_.emplace_back(frame, dataFormats_, sectorPhi, sectorEta); + stub = &stubsGP_.back(); + } + for (int binInv2R = 0; binInv2R < dataFormats_->numChannel(Process::ht); binInv2R++) + input_[binInv2R][sector].push_back(stub && stub->inInv2RBin(binInv2R) ? stub : nullptr); + } + } + // remove all gaps between end and last stub + for (vector>& input : input_) + for (deque& stubs : input) + for (auto it = stubs.end(); it != stubs.begin();) + it = (*--it) ? stubs.begin() : stubs.erase(it); + auto validStub = [](int& sum, StubGP* stub) { return sum += stub ? 1 : 0; }; + int nStubsHT(0); + for (const vector>& binInv2R : input_) + for (const deque& sector : binInv2R) + nStubsHT += accumulate(sector.begin(), sector.end(), 0, validStub); + stubsHT_.reserve(nStubsHT); + } + + // fill output products + void HoughTransform::produce(StreamsStub& accepted, StreamsStub& lost) { + for (int binInv2R = 0; binInv2R < dataFormats_->numChannel(Process::ht); binInv2R++) { + const int inv2R = inv2R_.toSigned(binInv2R); + deque acceptedAll; + deque lostAll; + for (deque& inputSector : input_[binInv2R]) { + const int size = inputSector.size(); + vector acceptedSector; + vector lostSector; + acceptedSector.reserve(size); + lostSector.reserve(size); + // associate stubs with inv2R and phiT bins + fillIn(inv2R, inputSector, acceptedSector, lostSector); + // Process::ht collects all stubs before readout starts -> remove all gaps + acceptedSector.erase(remove(acceptedSector.begin(), acceptedSector.end(), nullptr), acceptedSector.end()); + // identify tracks + readOut(acceptedSector, lostSector, acceptedAll, lostAll); + } + // truncate accepted stream + const auto limit = enableTruncation_ + ? next(acceptedAll.begin(), min(setup_->numFrames(), (int)acceptedAll.size())) + : acceptedAll.end(); + copy_if(limit, acceptedAll.end(), back_inserter(lostAll), [](StubHT* stub) { return stub; }); + acceptedAll.erase(limit, acceptedAll.end()); + // store found tracks + auto put = [](const deque& stubs, StreamStub& stream) { + stream.reserve(stubs.size()); + for (StubHT* stub : stubs) + stream.emplace_back(stub ? stub->frame() : FrameStub()); + }; + const int offset = region_ * dataFormats_->numChannel(Process::ht); + put(acceptedAll, accepted[offset + binInv2R]); + // store lost tracks + put(lostAll, lost[offset + binInv2R]); + } + } + + // associate stubs with phiT bins in this inv2R column + void HoughTransform::fillIn(int inv2R, + deque& inputSector, + vector& acceptedSector, + vector& lostSector) { + // fifo, used to store stubs which belongs to a second possible track + deque stack; + // clock accurate firmware emulation, each while trip describes one clock tick, one stub in and one stub out per tick + while (!inputSector.empty() || !stack.empty()) { + StubHT* stubHT = nullptr; + StubGP* stubGP = pop_front(inputSector); + if (stubGP) { + const double phiT = stubGP->phi() - inv2R_.floating(inv2R) * stubGP->r(); + const int major = phiT_.integer(phiT); + if (phiT_.inRange(major)) { + // major candidate has pt > threshold (3 GeV) + // stubHT records which HT bin this stub is added to + stubsHT_.emplace_back(*stubGP, major, inv2R); + stubHT = &stubsHT_.back(); + } + const double chi = phiT - phiT_.floating(major); + if (abs(stubGP->r() * inv2R_.base()) + 2. * abs(chi) >= phiT_.base()) { + // stub belongs to two candidates + const int minor = chi >= 0. ? major + 1 : major - 1; + if (phiT_.inRange(minor)) { + // second (minor) candidate has pt > threshold (3 GeV) + stubsHT_.emplace_back(*stubGP, minor, inv2R); + if (enableTruncation_ && (int)stack.size() == setup_->htDepthMemory() - 1) + // buffer overflow + lostSector.push_back(pop_front(stack)); + // store minor stub in fifo + stack.push_back(&stubsHT_.back()); + } + } + } + // take a minor stub if no major stub available + acceptedSector.push_back(stubHT ? stubHT : pop_front(stack)); + } + // truncate to many input stubs + const auto limit = enableTruncation_ + ? next(acceptedSector.begin(), min(setup_->numFrames(), (int)acceptedSector.size())) + : acceptedSector.end(); + copy_if(limit, acceptedSector.end(), back_inserter(lostSector), [](StubHT* stub) { return stub; }); + acceptedSector.erase(limit, acceptedSector.end()); + } + + // identify tracks + void HoughTransform::readOut(const vector& acceptedSector, + const vector& lostSector, + deque& acceptedAll, + deque& lostAll) const { + // used to recognise in which order tracks are found + TTBV trkFoundPhiTs(0, setup_->htNumBinsPhiT()); + // hitPattern for all possible tracks, used to find tracks + vector patternHits(setup_->htNumBinsPhiT(), TTBV(0, setup_->numLayers())); + // found unsigned phiTs, ordered in time + vector binsPhiT; + // stub container for all possible tracks + vector> tracks(setup_->htNumBinsPhiT()); + for (int binPhiT = 0; binPhiT < setup_->htNumBinsPhiT(); binPhiT++) { + const int phiT = phiT_.toSigned(binPhiT); + auto samePhiT = [phiT](int& sum, StubHT* stub) { return sum += stub->phiT() == phiT; }; + const int numAccepted = accumulate(acceptedSector.begin(), acceptedSector.end(), 0, samePhiT); + const int numLost = accumulate(lostSector.begin(), lostSector.end(), 0, samePhiT); + tracks[binPhiT].reserve(numAccepted + numLost); + } + for (StubHT* stub : acceptedSector) { + const int binPhiT = phiT_.toUnsigned(stub->phiT()); + TTBV& pattern = patternHits[binPhiT]; + pattern.set(stub->layer()); + tracks[binPhiT].push_back(stub); + if (pattern.count() >= setup_->htMinLayers() && !trkFoundPhiTs[binPhiT]) { + // first time track found + trkFoundPhiTs.set(binPhiT); + binsPhiT.push_back(binPhiT); + } + } + // read out found tracks ordered as found + for (int binPhiT : binsPhiT) { + const vector& track = tracks[binPhiT]; + acceptedAll.insert(acceptedAll.end(), track.begin(), track.end()); + } + // look for lost tracks + for (StubHT* stub : lostSector) { + const int binPhiT = phiT_.toUnsigned(stub->phiT()); + if (!trkFoundPhiTs[binPhiT]) + tracks[binPhiT].push_back(stub); + } + for (int binPhiT : trkFoundPhiTs.ids(false)) { + const vector& track = tracks[binPhiT]; + set layers; + auto toLayer = [](StubHT* stub) { return stub->layer(); }; + transform(track.begin(), track.end(), inserter(layers, layers.begin()), toLayer); + if ((int)layers.size() >= setup_->htMinLayers()) + lostAll.insert(lostAll.end(), track.begin(), track.end()); + } + } + + // remove and return first element of deque, returns nullptr if empty + template + T* HoughTransform::pop_front(deque& ts) const { + T* t = nullptr; + if (!ts.empty()) { + t = ts.front(); + ts.pop_front(); + } + return t; + } + +} // namespace trackerTFP \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/src/KalmanFilter.cc b/L1Trigger/TrackerTFP/src/KalmanFilter.cc new file mode 100644 index 0000000000000..30b550b28e87b --- /dev/null +++ b/L1Trigger/TrackerTFP/src/KalmanFilter.cc @@ -0,0 +1,457 @@ +#include "L1Trigger/TrackerTFP/interface/KalmanFilter.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace edm; +using namespace tt; + +namespace trackerTFP { + + KalmanFilter::KalmanFilter(const ParameterSet& iConfig, + const Setup* setup, + const DataFormats* dataFormats, + KalmanFilterFormats* kalmanFilterFormats, + int region) + : enableTruncation_(iConfig.getParameter("EnableTruncation")), + setup_(setup), + dataFormats_(dataFormats), + kalmanFilterFormats_(kalmanFilterFormats), + region_(region), + input_(dataFormats_->numChannel(Process::kf)), + layer_(0), + x0_(&kalmanFilterFormats_->format(VariableKF::x0)), + x1_(&kalmanFilterFormats_->format(VariableKF::x1)), + x2_(&kalmanFilterFormats_->format(VariableKF::x2)), + x3_(&kalmanFilterFormats_->format(VariableKF::x3)), + H00_(&kalmanFilterFormats_->format(VariableKF::H00)), + H12_(&kalmanFilterFormats_->format(VariableKF::H12)), + m0_(&kalmanFilterFormats_->format(VariableKF::m0)), + m1_(&kalmanFilterFormats_->format(VariableKF::m1)), + v0_(&kalmanFilterFormats_->format(VariableKF::v0)), + v1_(&kalmanFilterFormats_->format(VariableKF::v1)), + r0_(&kalmanFilterFormats_->format(VariableKF::r0)), + r1_(&kalmanFilterFormats_->format(VariableKF::r1)), + S00_(&kalmanFilterFormats_->format(VariableKF::S00)), + S01_(&kalmanFilterFormats_->format(VariableKF::S01)), + S12_(&kalmanFilterFormats_->format(VariableKF::S12)), + S13_(&kalmanFilterFormats_->format(VariableKF::S13)), + K00_(&kalmanFilterFormats_->format(VariableKF::K00)), + K10_(&kalmanFilterFormats_->format(VariableKF::K10)), + K21_(&kalmanFilterFormats_->format(VariableKF::K21)), + K31_(&kalmanFilterFormats_->format(VariableKF::K31)), + R00_(&kalmanFilterFormats_->format(VariableKF::R00)), + R11_(&kalmanFilterFormats_->format(VariableKF::R11)), + R00Rough_(&kalmanFilterFormats_->format(VariableKF::R00Rough)), + R11Rough_(&kalmanFilterFormats_->format(VariableKF::R11Rough)), + invR00Approx_(&kalmanFilterFormats_->format(VariableKF::invR00Approx)), + invR11Approx_(&kalmanFilterFormats_->format(VariableKF::invR11Approx)), + invR00Cor_(&kalmanFilterFormats_->format(VariableKF::invR00Cor)), + invR11Cor_(&kalmanFilterFormats_->format(VariableKF::invR11Cor)), + invR00_(&kalmanFilterFormats_->format(VariableKF::invR00)), + invR11_(&kalmanFilterFormats_->format(VariableKF::invR11)), + C00_(&kalmanFilterFormats_->format(VariableKF::C00)), + C01_(&kalmanFilterFormats_->format(VariableKF::C01)), + C11_(&kalmanFilterFormats_->format(VariableKF::C11)), + C22_(&kalmanFilterFormats_->format(VariableKF::C22)), + C23_(&kalmanFilterFormats_->format(VariableKF::C23)), + C33_(&kalmanFilterFormats_->format(VariableKF::C33)) { + C00_->updateRangeActual(pow(dataFormats_->base(Variable::inv2R, Process::kfin), 2)); + C11_->updateRangeActual(pow(dataFormats_->base(Variable::phiT, Process::kfin), 2)); + C22_->updateRangeActual(pow(dataFormats_->base(Variable::cot, Process::kfin), 2)); + C33_->updateRangeActual(pow(dataFormats_->base(Variable::zT, Process::kfin), 2)); + } + + // read in and organize input product (fill vector input_) + void KalmanFilter::consume(const StreamsTrack& streamsTrack, const StreamsStub& streamsStub) { + auto valid = [](const auto& frame) { return frame.first.isNonnull(); }; + auto acc = [](int& sum, const auto& frame) { return sum += (frame.first.isNonnull() ? 1 : 0); }; + int nTracks(0); + int nStubs(0); + const int offset = region_ * dataFormats_->numChannel(Process::kf); + for (int channel = 0; channel < dataFormats_->numChannel(Process::kf); channel++) { + const int channelTrack = offset + channel; + const StreamTrack& streamTracks = streamsTrack[channelTrack]; + nTracks += accumulate(streamTracks.begin(), streamTracks.end(), 0, acc); + for (int layer = 0; layer < setup_->numLayers(); layer++) { + const int channelStub = channelTrack * setup_->numLayers() + layer; + const StreamStub& streamStubs = streamsStub[channelStub]; + nStubs += accumulate(streamStubs.begin(), streamStubs.end(), 0, acc); + } + } + tracks_.reserve(nTracks); + stubs_.reserve(nStubs); + // N.B. One input stream for track & one for its stubs in each layer. If a track has N stubs in one layer, and fewer in all other layers, then next valid track will be N frames later + for (int channel = 0; channel < dataFormats_->numChannel(Process::kf); channel++) { + const int channelTrack = offset + channel; + const StreamTrack& streamTracks = streamsTrack[channelTrack]; + vector& tracks = input_[channel]; + tracks.reserve(streamTracks.size()); + for (int frame = 0; frame < (int)streamTracks.size(); frame++) { + const FrameTrack& frameTrack = streamTracks[frame]; + // Select frames with valid track + if (frameTrack.first.isNull()) { + if (dataFormats_->hybrid()) + tracks.push_back(nullptr); + continue; + } + auto endOfTrk = find_if(next(streamTracks.begin(), frame + 1), streamTracks.end(), valid); + if (dataFormats_->hybrid()) + endOfTrk = next(streamTracks.begin(), frame + 1); + // No. of frames before next track indicates gives max. no. of stubs this track had in any layer + const int maxStubsPerLayer = distance(next(streamTracks.begin(), frame), endOfTrk); + tracks.insert(tracks.end(), maxStubsPerLayer - 1, nullptr); + deque stubs; + for (int layer = 0; layer < setup_->numLayers(); layer++) { + const int channelStub = channelTrack * setup_->numLayers() + layer; + const StreamStub& streamStubs = streamsStub[channelStub]; + // Get stubs on this track + for (int i = frame; i < frame + maxStubsPerLayer; i++) { + const FrameStub& frameStub = streamStubs[i]; + if (frameStub.first.isNull()) + break; + // Store input stubs, so remainder of KF algo can work with pointers to them (saves CPU) + stubs_.emplace_back(frameStub, dataFormats_, layer); + stubs.push_back(&stubs_.back()); + } + } + // Store input tracks, so remainder of KF algo can work with pointers to them (saves CPU) + tracks_.emplace_back(frameTrack, dataFormats_, vector(stubs.begin(), stubs.end())); + tracks.push_back(&tracks_.back()); + } + } + } + + // fill output products + void KalmanFilter::produce(StreamsStub& acceptedStubs, + StreamsTrack& acceptedTracks, + StreamsStub& lostStubs, + StreamsTrack& lostTracks, + int& numAcceptedStates, + int& numLostStates) { + auto put = [this]( + const deque& states, StreamsStub& streamsStubs, StreamsTrack& streamsTracks, int channel) { + const int streamId = region_ * dataFormats_->numChannel(Process::kf) + channel; + const int offset = streamId * setup_->numLayers(); + StreamTrack& tracks = streamsTracks[streamId]; + tracks.reserve(states.size()); + for (int layer = 0; layer < setup_->numLayers(); layer++) + streamsStubs[offset + layer].reserve(states.size()); + for (State* state : states) { + tracks.emplace_back(state->frame()); + for (const StubKF& stub : state->stubs()) + streamsStubs[offset + stub.layer()].emplace_back(stub.frame()); + // adding a gap to all layer without a stub + for (int layer : state->hitPattern().ids(false)) + streamsStubs[offset + layer].emplace_back(FrameStub()); + } + }; + auto count = [this](int& sum, const State* state) { + return sum += state && state->hitPattern().count() >= setup_->kfMinLayers() ? 1 : 0; + }; + for (int channel = 0; channel < dataFormats_->numChannel(Process::kf); channel++) { + deque stream; + deque lost; + // proto state creation + int trackId(0); + for (TrackKFin* track : input_[channel]) { + State* state = nullptr; + if (track) { + // Store states, so remainder of KF algo can work with pointers to them (saves CPU) + states_.emplace_back(dataFormats_, track, trackId++); + state = &states_.back(); + } + stream.push_back(state); + } + // Propagate state to each layer in turn, updating it with all viable stub combinations there, using KF maths + for (layer_ = 0; layer_ < setup_->numLayers(); layer_++) + addLayer(stream); + // calculate number of states before truncating + const int numUntruncatedStates = accumulate(stream.begin(), stream.end(), 0, count); + // untruncated best state selection + deque untruncatedStream = stream; + accumulator(untruncatedStream); + // apply truncation + if (enableTruncation_ && (int)stream.size() > setup_->numFrames()) + stream.resize(setup_->numFrames()); + // calculate number of states after truncating + const int numTruncatedStates = accumulate(stream.begin(), stream.end(), 0, count); + // best state per candidate selection + accumulator(stream); + deque truncatedStream = stream; + // storing of best states missed due to truncation + sort(untruncatedStream.begin(), untruncatedStream.end()); + sort(truncatedStream.begin(), truncatedStream.end()); + set_difference(untruncatedStream.begin(), + untruncatedStream.end(), + truncatedStream.begin(), + truncatedStream.end(), + back_inserter(lost)); + // store found tracks + put(stream, acceptedStubs, acceptedTracks, channel); + // store lost tracks + put(lost, lostStubs, lostTracks, channel); + // store number of states which got taken into account + numAcceptedStates += numTruncatedStates; + // store number of states which got not taken into account due to truncation + numLostStates += numUntruncatedStates - numTruncatedStates; + } + } + + // adds a layer to states + void KalmanFilter::addLayer(deque& stream) { + // Latency of KF Associator block firmware + static constexpr int latency = 5; + // dynamic state container for clock accurate emulation + deque streamOutput; + // Memory stack used to handle combinatorics + deque stack; + // static delay container + vector delay(latency, nullptr); + // each trip corresponds to a f/w clock tick + // done if no states to process left, taking as much time as needed + while (!stream.empty() || !stack.empty() || + !all_of(delay.begin(), delay.end(), [](const State* state) { return state == nullptr; })) { + State* state = pop_front(stream); + // Process a combinatoric state if no (non-combinatoric?) state available + if (!state) + state = pop_front(stack); + streamOutput.push_back(state); + // The remainder of the code in this loop deals with combinatoric states. + if (state != nullptr) + // Assign next combinatoric stub to state + comb(state); + delay.push_back(state); + state = pop_front(delay); + if (state != nullptr) + stack.push_back(state); + } + stream = streamOutput; + for (State*& state : stream) { + if (!state || !state->stub() || state->layer() != layer_) + continue; + // Update state with next stub using KF maths + update(state); + } + } + + // Assign next combinatoric (i.e. not first in layer) stub to state + void KalmanFilter::comb(State*& state) { + const TrackKFin* track = state->track(); + const StubKFin* stub = state->stub(); + const vector& stubs = track->layerStubs(layer_); + const TTBV& hitPattern = state->hitPattern(); + StubKFin* stubNext = nullptr; + // Get first stub on this layer if state reached min layers + if (!stub) { + if (hitPattern.count() < setup_->kfMaxLayers() && track->hitPattern(layer_)) + stubNext = track->layerStub(layer_); + } else if (stub->layer() == layer_) { + // Get next unused stub on this layer + const int pos = distance(stubs.begin(), find(stubs.begin(), stubs.end(), stub)) + 1; + if (pos != (int)stubs.size()) + stubNext = stubs[pos]; + // picks next stub on different layer, nullifies state if skipping layer is not valid + else { + bool valid(true); + // having already maximum number of added layers + if (hitPattern.count() == setup_->kfMaxLayers()) + valid = false; + // Impossible for this state to ever get enough layers to form valid track + if (hitPattern.count() + track->hitPattern().count(stub->layer() + 1, setup_->numLayers()) < + setup_->kfMinLayers()) + valid = false; + if (layer_ == setup_->numLayers() - 1) + valid = false; + if (valid) { + // pick next stub on next populated layer + for (int nextLayer = layer_ + 1; nextLayer < setup_->numLayers(); nextLayer++) { + if (track->hitPattern(nextLayer)) { + stubNext = track->layerStub(nextLayer); + break; + } + } + } + } + } + if (stubNext) { + // create combinatoric state + states_.emplace_back(state, stubNext); + state = &states_.back(); + } else + state = nullptr; + } + + // best state selection + void KalmanFilter::accumulator(deque& stream) { + // accumulator delivers contigious stream of best state per track + // remove gaps and not final states + stream.erase( + remove_if(stream.begin(), + stream.end(), + [this](State* state) { return !state || state->hitPattern().count() < setup_->kfMinLayers(); }), + stream.end()); + // Determine quality of completed state + for (State* state : stream) + state->finish(); + // sort in number of skipped layers + auto lessSkippedLayers = [](State* lhs, State* rhs) { return lhs->numSkippedLayers() < rhs->numSkippedLayers(); }; + stable_sort(stream.begin(), stream.end(), lessSkippedLayers); + // sort in number of consistent stubs + auto moreConsistentLayers = [](State* lhs, State* rhs) { + return lhs->numConsistentLayers() > rhs->numConsistentLayers(); + }; + stable_sort(stream.begin(), stream.end(), moreConsistentLayers); + // sort in track id + stable_sort(stream.begin(), stream.end(), [](State* lhs, State* rhs) { return lhs->trackId() < rhs->trackId(); }); + // keep first state (best due to previous sorts) per track id + stream.erase( + unique(stream.begin(), stream.end(), [](State* lhs, State* rhs) { return lhs->track() == rhs->track(); }), + stream.end()); + } + + // updates state + void KalmanFilter::update(State*& state) { + // All variable names & equations come from Fruhwirth KF paper http://dx.doi.org/10.1016/0168-9002%2887%2990887-4", where F taken as unit matrix. Stub uncertainties projected onto (phi,z), assuming no correlations between r-phi & r-z planes. + // stub phi residual wrt input helix + const double m0 = m0_->digi(state->m0()); + // stub z residual wrt input helix + const double m1 = m1_->digi(state->m1()); + // stub projected phi uncertainty squared); + const double v0 = v0_->digi(state->v0()); + // stub projected z uncertainty squared + const double v1 = v1_->digi(state->v1()); + // helix inv2R wrt input helix + double x0 = x0_->digi(state->x0()); + // helix phi at radius ChosenRofPhi wrt input helix + double x1 = x1_->digi(state->x1()); + // helix cot(Theta) wrt input helix + double x2 = x2_->digi(state->x2()); + // helix z at radius chosenRofZ wrt input helix + double x3 = x3_->digi(state->x3()); + // Derivative of predicted stub coords wrt helix params: stub radius minus chosenRofPhi + const double H00 = H00_->digi(state->H00()); + // Derivative of predicted stub coords wrt helix params: stub radius minus chosenRofZ + const double H12 = H12_->digi(state->H12()); + // cov. matrix + double C00 = C00_->digi(state->C00()); + double C01 = C01_->digi(state->C01()); + double C11 = C11_->digi(state->C11()); + double C22 = C22_->digi(state->C22()); + double C23 = C23_->digi(state->C23()); + double C33 = C33_->digi(state->C33()); + // stub phi residual wrt current state + const double r0C = x1_->digi(m0 - x1); + const double r0 = r0_->digi(r0C - x0 * H00); + // stub z residual wrt current state + const double r1C = x3_->digi(m1 - x3); + const double r1 = r1_->digi(r1C - x2 * H12); + // matrix S = H*C + const double S00 = S00_->digi(C01 + H00 * C00); + const double S01 = S01_->digi(C11 + H00 * C01); + const double S12 = S12_->digi(C23 + H12 * C22); + const double S13 = S13_->digi(C33 + H12 * C23); + // Cov. matrix of predicted residuals R = V+HCHt = C+H*St + const double R00C = S01_->digi(v0 + S01); + const double R00 = R00_->digi(R00C + H00 * S00); + const double R11C = S13_->digi(v1 + S13); + const double R11 = R11_->digi(R11C + H12 * S12); + // imrpoved dynamic cancelling + const int msb0 = max(0, (int)ceil(log2(R00 / R00_->base()))); + const int msb1 = max(0, (int)ceil(log2(R11 / R11_->base()))); + const double R00Rough = R00Rough_->digi(R00 * pow(2., 16 - msb0)); + const double invR00Approx = invR00Approx_->digi(1. / R00Rough); + const double invR00Cor = invR00Cor_->digi(2. - invR00Approx * R00Rough); + const double invR00 = invR00_->digi(invR00Approx * invR00Cor * pow(2., 16 - msb0)); + const double R11Rough = R11Rough_->digi(R11 * pow(2., 16 - msb1)); + const double invR11Approx = invR11Approx_->digi(1. / R11Rough); + const double invR11Cor = invR11Cor_->digi(2. - invR11Approx * R11Rough); + const double invR11 = invR11_->digi(invR11Approx * invR11Cor * pow(2., 16 - msb1)); + // Kalman gain matrix K = S*R(inv) + const double K00 = K00_->digi(S00 * invR00); + const double K10 = K10_->digi(S01 * invR00); + const double K21 = K21_->digi(S12 * invR11); + const double K31 = K31_->digi(S13 * invR11); + // Updated helix params & their cov. matrix + x0 = x0_->digi(x0 + r0 * K00); + x1 = x1_->digi(x1 + r0 * K10); + x2 = x2_->digi(x2 + r1 * K21); + x3 = x3_->digi(x3 + r1 * K31); + C00 = C00_->digi(C00 - S00 * K00); + C01 = C01_->digi(C01 - S01 * K00); + C11 = C11_->digi(C11 - S01 * K10); + C22 = C22_->digi(C22 - S12 * K21); + C23 = C23_->digi(C23 - S13 * K21); + C33 = C33_->digi(C33 - S13 * K31); + // create updated state + states_.emplace_back(State(state, (initializer_list){x0, x1, x2, x3, C00, C11, C22, C33, C01, C23})); + state = &states_.back(); + // update variable ranges to tune variable granularity + m0_->updateRangeActual(m0); + m1_->updateRangeActual(m1); + v0_->updateRangeActual(v0); + v1_->updateRangeActual(v1); + H00_->updateRangeActual(H00); + H12_->updateRangeActual(H12); + r0_->updateRangeActual(r0); + r1_->updateRangeActual(r1); + S00_->updateRangeActual(S00); + S01_->updateRangeActual(S01); + S12_->updateRangeActual(S12); + S13_->updateRangeActual(S13); + R00_->updateRangeActual(R00); + R11_->updateRangeActual(R11); + R00Rough_->updateRangeActual(R00Rough); + invR00Approx_->updateRangeActual(invR00Approx); + invR00Cor_->updateRangeActual(invR00Cor); + invR00_->updateRangeActual(invR00); + R11Rough_->updateRangeActual(R11Rough); + invR11Approx_->updateRangeActual(invR11Approx); + invR11Cor_->updateRangeActual(invR11Cor); + invR11_->updateRangeActual(invR11); + K00_->updateRangeActual(K00); + K10_->updateRangeActual(K10); + K21_->updateRangeActual(K21); + K31_->updateRangeActual(K31); + x0_->updateRangeActual(x0); + x1_->updateRangeActual(x1); + x2_->updateRangeActual(x2); + x3_->updateRangeActual(x3); + C00_->updateRangeActual(C00); + C01_->updateRangeActual(C01); + C11_->updateRangeActual(C11); + C22_->updateRangeActual(C22); + C23_->updateRangeActual(C23); + C33_->updateRangeActual(C33); + } + + // remove and return first element of deque, returns nullptr if empty + template + T* KalmanFilter::pop_front(deque& ts) const { + T* t = nullptr; + if (!ts.empty()) { + t = ts.front(); + ts.pop_front(); + } + return t; + } + + // remove and return first element of vector, returns nullptr if empty + template + T* KalmanFilter::pop_front(vector& ts) const { + T* t = nullptr; + if (!ts.empty()) { + t = ts.front(); + ts.erase(ts.begin()); + } + return t; + } + +} // namespace trackerTFP \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/src/KalmanFilterFormats.cc b/L1Trigger/TrackerTFP/src/KalmanFilterFormats.cc new file mode 100644 index 0000000000000..26eaabbcb4519 --- /dev/null +++ b/L1Trigger/TrackerTFP/src/KalmanFilterFormats.cc @@ -0,0 +1,447 @@ +#include "L1Trigger/TrackerTFP/interface/KalmanFilterFormats.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace edm; +using namespace tt; + +namespace trackerTFP { + + constexpr auto variableKFstrs_ = { + "x0", "x1", "x2", "x3", "H00", "H12", "m0", "m1", "v0", + "v1", "r0", "r1", "S00", "S01", "S12", "S13", "K00", "K10", + "K21", "K31", "R00", "R11", "R00Rough", "R11Rough", "invR00Approx", "invR11Approx", "invR00Cor", + "invR11Cor", "invR00", "invR11", "C00", "C01", "C11", "C22", "C23", "C33"}; + + void KalmanFilterFormats::endJob() { + const int wName = + strlen(*max_element(variableKFstrs_.begin(), variableKFstrs_.end(), [this](const auto& a, const auto& b) { + return strlen(a) < strlen(b); + })); + static constexpr int wWidth = 3; + for (VariableKF v = VariableKF::begin; v != VariableKF::end; v = VariableKF(+v + 1)) { + const pair& range = format(v).rangeActual(); + const double r = format(v).twos() ? max(abs(range.first), abs(range.second)) * 2. : range.second; + const int width = ceil(log2(r / format(v).base())); + cout << setw(wName) << *next(variableKFstrs_.begin(), +v) << ": " << setw(wWidth) << width << " " << setw(wWidth) + << format(v).width() << " | " << setw(wWidth) << format(v).width() - width << endl; + } + } + + KalmanFilterFormats::KalmanFilterFormats() : iConfig_(), dataFormats_(nullptr), setup_(nullptr) { + formats_.reserve(+VariableKF::end); + } + + KalmanFilterFormats::KalmanFilterFormats(const ParameterSet& iConfig, const DataFormats* dataFormats) + : iConfig_(dataFormats->hybrid() ? iConfig.getParameter("hybrid") + : iConfig.getParameter("tmtt")), + dataFormats_(dataFormats), + setup_(dataFormats_->setup()) { + formats_.reserve(+VariableKF::end); + fillFormats(); + } + + template + void KalmanFilterFormats::fillFormats() { + formats_.emplace_back(FormatKF(dataFormats_, iConfig_)); + if constexpr (++it != VariableKF::end) + fillFormats<++it>(); + } + + DataFormatKF::DataFormatKF(const VariableKF& v, bool twos) + : v_(v), + twos_(twos), + width_(0), + base_(1.), + range_(0.), + rangeActual_(numeric_limits::max(), numeric_limits::lowest()) {} + + // returns false if data format would oferflow for this double value + bool DataFormatKF::inRange(double d) const { + if (twos_) + return d >= -range_ / 2. && d < range_ / 2.; + return d >= 0 && d < range_; + } + + void DataFormatKF::updateRangeActual(double d) { + rangeActual_ = make_pair(min(rangeActual_.first, d), max(rangeActual_.second, d)); + if (!inRange(d)) { + string v = *next(variableKFstrs_.begin(), +v_); + cms::Exception exception("out_of_range"); + exception.addContext("trackerTFP:DataFormatKF::updateRangeActual"); + exception << "Variable " << v << " = " << d << " is out of range " << (twos_ ? -range_ / 2. : 0) << " to " + << (twos_ ? range_ / 2. : range_) << "." << endl; + if (twos_ || d >= 0.) + exception.addAdditionalInfo("Consider raising BaseShift" + v + " in KalmnaFilterFormats_cfi.py."); + throw exception; + } + } + + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig) + : DataFormatKF(VariableKF::x0, true) { + const DataFormat& input = dataFormats->format(Variable::inv2R, Process::kf); + const int baseShift = iConfig.getParameter("BaseShiftx0"); + base_ = pow(2, baseShift) * input.base(); + width_ = dataFormats->setup()->widthDSPbb(); + calcRange(); + } + + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig) + : DataFormatKF(VariableKF::x1, true) { + const DataFormat& input = dataFormats->format(Variable::phiT, Process::kf); + const int baseShift = iConfig.getParameter("BaseShiftx1"); + base_ = pow(2, baseShift) * input.base(); + width_ = dataFormats->setup()->widthDSPbb(); + calcRange(); + } + + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig) + : DataFormatKF(VariableKF::x2, true) { + const DataFormat& input = dataFormats->format(Variable::cot, Process::kf); + const int baseShift = iConfig.getParameter("BaseShiftx2"); + base_ = pow(2, baseShift) * input.base(); + width_ = dataFormats->setup()->widthDSPbb(); + calcRange(); + } + + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig) + : DataFormatKF(VariableKF::x3, true) { + const DataFormat& input = dataFormats->format(Variable::zT, Process::kf); + const int baseShift = iConfig.getParameter("BaseShiftx3"); + base_ = pow(2, baseShift) * input.base(); + width_ = dataFormats->setup()->widthDSPbb(); + calcRange(); + } + + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig) + : DataFormatKF(VariableKF::H00, true) { + const DataFormat& kfin = dataFormats->format(Variable::r, Process::kfin); + base_ = kfin.base(); + width_ = kfin.width(); + range_ = kfin.range(); + } + + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig) + : DataFormatKF(VariableKF::H12, true) { + const Setup* setup = dataFormats->setup(); + const DataFormat& kfin = dataFormats->format(Variable::r, Process::kfin); + base_ = kfin.base(); + range_ = 2. * max(abs(setup->outerRadius() - setup->chosenRofZ()), abs(setup->innerRadius() - setup->chosenRofZ())); + width_ = ceil(log2(range_ / base_)); + } + + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig) + : DataFormatKF(VariableKF::m0, true) { + const DataFormat& kfin = dataFormats->format(Variable::phi, Process::kfin); + base_ = kfin.base(); + width_ = kfin.width(); + range_ = kfin.range(); + } + + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig) + : DataFormatKF(VariableKF::m1, true) { + const DataFormat& kfin = dataFormats->format(Variable::z, Process::kfin); + base_ = kfin.base(); + width_ = kfin.width(); + range_ = kfin.range(); + } + + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig) + : DataFormatKF(VariableKF::v0, false) { + const DataFormat& x1 = dataFormats->format(Variable::phiT, Process::kf); + const int baseShift = iConfig.getParameter("BaseShiftv0"); + base_ = pow(2., baseShift) * x1.base() * x1.base(); + width_ = dataFormats->setup()->widthDSPbu(); + calcRange(); + } + + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig) + : DataFormatKF(VariableKF::v1, true) { + const DataFormat& x3 = dataFormats->format(Variable::zT, Process::kf); + const int baseShift = iConfig.getParameter("BaseShiftv1"); + base_ = pow(2., baseShift) * x3.base() * x3.base(); + width_ = dataFormats->setup()->widthDSPbu(); + calcRange(); + } + + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig) + : DataFormatKF(VariableKF::r0, true) { + const DataFormat& x1 = dataFormats->format(Variable::phiT, Process::kf); + const int baseShift = iConfig.getParameter("BaseShiftr0"); + base_ = pow(2., baseShift) * x1.base(); + width_ = dataFormats->setup()->widthDSPbb(); + calcRange(); + } + + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig) + : DataFormatKF(VariableKF::r1, true) { + const DataFormat& x3 = dataFormats->format(Variable::zT, Process::kf); + const int baseShift = iConfig.getParameter("BaseShiftr1"); + base_ = pow(2., baseShift) * x3.base(); + width_ = dataFormats->setup()->widthDSPbb(); + calcRange(); + } + + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig) + : DataFormatKF(VariableKF::S00, true) { + const DataFormat& x0 = dataFormats->format(Variable::inv2R, Process::kf); + const DataFormat& x1 = dataFormats->format(Variable::phiT, Process::kf); + const int baseShift = iConfig.getParameter("BaseShiftS00"); + base_ = pow(2., baseShift) * x0.base() * x1.base(); + width_ = dataFormats->setup()->widthDSPbb(); + calcRange(); + } + + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig) + : DataFormatKF(VariableKF::S01, true) { + const DataFormat& x1 = dataFormats->format(Variable::phiT, Process::kf); + const int baseShift = iConfig.getParameter("BaseShiftS01"); + base_ = pow(2., baseShift) * x1.base() * x1.base(); + width_ = dataFormats->setup()->widthDSPbb(); + calcRange(); + } + + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig) + : DataFormatKF(VariableKF::S12, true) { + const DataFormat& x2 = dataFormats->format(Variable::cot, Process::kf); + const DataFormat& x3 = dataFormats->format(Variable::zT, Process::kf); + const int baseShift = iConfig.getParameter("BaseShiftS12"); + base_ = pow(2., baseShift) * x2.base() * x3.base(); + width_ = dataFormats->setup()->widthDSPbb(); + calcRange(); + } + + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig) + : DataFormatKF(VariableKF::S13, true) { + const DataFormat& x3 = dataFormats->format(Variable::zT, Process::kf); + const int baseShift = iConfig.getParameter("BaseShiftS13"); + base_ = pow(2., baseShift) * x3.base() * x3.base(); + width_ = dataFormats->setup()->widthDSPbb(); + calcRange(); + } + + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig) + : DataFormatKF(VariableKF::K00, true) { + const DataFormat& x0 = dataFormats->format(Variable::inv2R, Process::kf); + const DataFormat& x1 = dataFormats->format(Variable::phiT, Process::kf); + const int baseShift = iConfig.getParameter("BaseShiftK00"); + base_ = pow(2., baseShift) * x0.base() / x1.base(); + width_ = dataFormats->setup()->widthDSPab(); + calcRange(); + } + + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig) + : DataFormatKF(VariableKF::K10, true) { + const int baseShift = iConfig.getParameter("BaseShiftK10"); + base_ = pow(2., baseShift); + width_ = dataFormats->setup()->widthDSPab(); + calcRange(); + } + + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig) + : DataFormatKF(VariableKF::K21, true) { + const DataFormat& x2 = dataFormats->format(Variable::cot, Process::kf); + const DataFormat& x3 = dataFormats->format(Variable::zT, Process::kf); + const int baseShift = iConfig.getParameter("BaseShiftK21"); + base_ = pow(2., baseShift) * x2.base() / x3.base(); + width_ = dataFormats->setup()->widthDSPab(); + calcRange(); + } + + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig) + : DataFormatKF(VariableKF::K31, true) { + const int baseShift = iConfig.getParameter("BaseShiftK31"); + base_ = pow(2., baseShift); + width_ = dataFormats->setup()->widthDSPab(); + calcRange(); + } + + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig) + : DataFormatKF(VariableKF::R00, false) { + const DataFormat& x1 = dataFormats->format(Variable::phiT, Process::kf); + const int baseShift = iConfig.getParameter("BaseShiftR00"); + base_ = pow(2., baseShift) * x1.base() * x1.base(); + width_ = dataFormats->setup()->widthDSPbu(); + calcRange(); + } + + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig) + : DataFormatKF(VariableKF::R11, false) { + const DataFormat& x3 = dataFormats->format(Variable::zT, Process::kf); + const int baseShift = iConfig.getParameter("BaseShiftR11"); + base_ = pow(2., baseShift) * x3.base() * x3.base(); + width_ = dataFormats->setup()->widthDSPbu(); + calcRange(); + } + + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig) + : DataFormatKF(VariableKF::R00Rough, false) { + const FormatKF R00(dataFormats, iConfig); + width_ = dataFormats->setup()->widthAddrBRAM18(); + range_ = R00.range(); + const int baseShift = R00.width() - width_; + base_ = pow(2., baseShift) * R00.base(); + } + + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig) + : DataFormatKF(VariableKF::R11Rough, false) { + const FormatKF R11(dataFormats, iConfig); + width_ = dataFormats->setup()->widthAddrBRAM18(); + range_ = R11.range(); + const int baseShift = R11.width() - width_; + base_ = pow(2., baseShift) * R11.base(); + } + + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig) + : DataFormatKF(VariableKF::invR00Approx, false) { + const DataFormat& x1 = dataFormats->format(Variable::phiT, Process::kf); + const int baseShift = iConfig.getParameter("BaseShiftInvR00Approx"); + base_ = pow(2., baseShift) / x1.base() / x1.base(); + width_ = dataFormats->setup()->widthDSPbu(); + calcRange(); + } + + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig) + : DataFormatKF(VariableKF::invR11Approx, false) { + const DataFormat& x3 = dataFormats->format(Variable::zT, Process::kf); + const int baseShift = iConfig.getParameter("BaseShiftInvR11Approx"); + base_ = pow(2., baseShift) / x3.base() / x3.base(); + width_ = dataFormats->setup()->widthDSPbu(); + calcRange(); + } + + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig) + : DataFormatKF(VariableKF::invR00Cor, false) { + const int baseShift = iConfig.getParameter("BaseShiftInvR00Cor"); + base_ = pow(2., baseShift); + width_ = dataFormats->setup()->widthDSPbu(); + calcRange(); + } + + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig) + : DataFormatKF(VariableKF::invR11Cor, false) { + const int baseShift = iConfig.getParameter("BaseShiftInvR11Cor"); + base_ = pow(2., baseShift); + width_ = dataFormats->setup()->widthDSPbu(); + calcRange(); + } + + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig) + : DataFormatKF(VariableKF::invR00, false) { + const DataFormat& x1 = dataFormats->format(Variable::phiT, Process::kf); + const int baseShift = iConfig.getParameter("BaseShiftInvR00"); + base_ = pow(2., baseShift) / x1.base() / x1.base(); + width_ = dataFormats->setup()->widthDSPau(); + calcRange(); + } + + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig) + : DataFormatKF(VariableKF::invR11, false) { + const DataFormat& x3 = dataFormats->format(Variable::zT, Process::kf); + const int baseShift = iConfig.getParameter("BaseShiftInvR11"); + base_ = pow(2., baseShift) / x3.base() / x3.base(); + width_ = dataFormats->setup()->widthDSPau(); + calcRange(); + } + + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig) + : DataFormatKF(VariableKF::C00, false) { + const DataFormat& x0 = dataFormats->format(Variable::inv2R, Process::kf); + const int baseShift = iConfig.getParameter("BaseShiftC00"); + base_ = pow(2., baseShift) * x0.base() * x0.base(); + width_ = dataFormats->setup()->widthDSPbu(); + calcRange(); + } + + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig) + : DataFormatKF(VariableKF::C01, true) { + const DataFormat& x0 = dataFormats->format(Variable::inv2R, Process::kf); + const DataFormat& x1 = dataFormats->format(Variable::phiT, Process::kf); + const int baseShift = iConfig.getParameter("BaseShiftC01"); + base_ = pow(2., baseShift) * x0.base() * x1.base(); + width_ = dataFormats->setup()->widthDSPbb(); + calcRange(); + } + + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig) + : DataFormatKF(VariableKF::C11, false) { + const DataFormat& x1 = dataFormats->format(Variable::phiT, Process::kf); + const int baseShift = iConfig.getParameter("BaseShiftC11"); + base_ = pow(2., baseShift) * x1.base() * x1.base(); + width_ = dataFormats->setup()->widthDSPbu(); + calcRange(); + } + + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig) + : DataFormatKF(VariableKF::C22, false) { + const DataFormat& x2 = dataFormats->format(Variable::cot, Process::kf); + const int baseShift = iConfig.getParameter("BaseShiftC22"); + base_ = pow(2., baseShift) * x2.base() * x2.base(); + width_ = dataFormats->setup()->widthDSPbu(); + calcRange(); + } + + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig) + : DataFormatKF(VariableKF::C23, true) { + const DataFormat& x2 = dataFormats->format(Variable::cot, Process::kf); + const DataFormat& x3 = dataFormats->format(Variable::zT, Process::kf); + const int baseShift = iConfig.getParameter("BaseShiftC23"); + base_ = pow(2., baseShift) * x2.base() * x3.base(); + width_ = dataFormats->setup()->widthDSPbb(); + calcRange(); + } + + template <> + FormatKF::FormatKF(const DataFormats* dataFormats, const edm::ParameterSet& iConfig) + : DataFormatKF(VariableKF::C33, false) { + const DataFormat& x3 = dataFormats->format(Variable::zT, Process::kf); + const int baseShift = iConfig.getParameter("BaseShiftC33"); + base_ = pow(2., baseShift) * x3.base() * x3.base(); + width_ = dataFormats->setup()->widthDSPbu(); + calcRange(); + } + +} // namespace trackerTFP diff --git a/L1Trigger/TrackerTFP/src/KalmanFilterFormatsRcd.cc b/L1Trigger/TrackerTFP/src/KalmanFilterFormatsRcd.cc new file mode 100644 index 0000000000000..3e5a0cbb697a0 --- /dev/null +++ b/L1Trigger/TrackerTFP/src/KalmanFilterFormatsRcd.cc @@ -0,0 +1,4 @@ +#include "L1Trigger/TrackerTFP/interface/KalmanFilterFormatsRcd.h" +#include "FWCore/Framework/interface/eventsetuprecord_registration_macro.h" + +EVENTSETUP_RECORD_REG(trackerTFP::KalmanFilterFormatsRcd); \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/src/LayerEncoding.cc b/L1Trigger/TrackerTFP/src/LayerEncoding.cc new file mode 100644 index 0000000000000..0b78181944793 --- /dev/null +++ b/L1Trigger/TrackerTFP/src/LayerEncoding.cc @@ -0,0 +1,179 @@ +#include "L1Trigger/TrackerTFP/interface/LayerEncoding.h" +#include "L1Trigger/TrackTrigger/interface/SensorModule.h" + +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace tt; + +namespace trackerTFP { + + LayerEncoding::LayerEncoding(const DataFormats* dataFormats) + : setup_(dataFormats->setup()), + dataFormats_(dataFormats), + zT_(&dataFormats->format(Variable::zT, Process::zht)), + cot_(&dataFormats->format(Variable::cot, Process::zht)), + layerEncoding_(setup_->numSectorsEta(), + vector>>(pow(2, zT_->width()), vector>(pow(2, cot_->width())))), + maybeLayer_(setup_->numSectorsEta(), + vector>>(pow(2, zT_->width()), vector>(pow(2, cot_->width())))) { + // number of boundaries of fiducial area in r-z plane for a given set of rough r-z track parameter + static constexpr int boundaries = 2; + // find unique sensor mouldes in r-z + // allowed distance in r and z in cm between modules to consider them not unique + static constexpr double delta = 1.e-3; + vector sensorModules; + sensorModules.reserve(setup_->sensorModules().size()); + for (const SensorModule& sm : setup_->sensorModules()) + sensorModules.push_back(&sm); + auto smallerR = [](const SensorModule* lhs, const SensorModule* rhs) { return lhs->r() < rhs->r(); }; + auto smallerZ = [](const SensorModule* lhs, const SensorModule* rhs) { return lhs->z() < rhs->z(); }; + auto equalRZ = [](const SensorModule* lhs, const SensorModule* rhs) { + return abs(lhs->r() - rhs->r()) < delta && abs(lhs->z() - rhs->z()) < delta; + }; + stable_sort(sensorModules.begin(), sensorModules.end(), smallerR); + stable_sort(sensorModules.begin(), sensorModules.end(), smallerZ); + sensorModules.erase(unique(sensorModules.begin(), sensorModules.end(), equalRZ), sensorModules.end()); + // find set of moudles for each set of rough r-z track parameter + // loop over eta sectors + for (int binEta = 0; binEta < setup_->numSectorsEta(); binEta++) { + // cotTheta of eta sector centre + const double sectorCot = (sinh(setup_->boundarieEta(binEta + 1)) + sinh(setup_->boundarieEta(binEta))) / 2.; + // z at radius choenRofZ of eta sector centre + const double sectorZT = setup_->chosenRofZ() * sectorCot; + // range of z at radius chosenRofZ this eta sector covers + const double rangeZT = + setup_->chosenRofZ() * (sinh(setup_->boundarieEta(binEta + 1)) - sinh(setup_->boundarieEta(binEta))) / 2.; + // loop over bins in zT + for (int binZT = 0; binZT < pow(2, zT_->width()); binZT++) { + // z at radius chosenRofZ wrt zT of sectorZT of this bin centre + const double zT = zT_->floating(zT_->toSigned(binZT)); + // skip this bin if zT is outside of eta sector + if (abs(zT) > rangeZT + zT_->base() / 2.) + continue; + // z at radius chosenRofZ wrt zT of sectorZT of this bin boundaries + const vector zTs = {sectorZT + zT - zT_->base() / 2., sectorZT + zT + zT_->base() / 2.}; + // loop over bins in cotTheta + for (int binCot = 0; binCot < pow(2, cot_->width()); binCot++) { + // cotTheta wrt sectorCot of this bin centre + const double cot = cot_->floating(cot_->toSigned(binCot)); + // global z0 of this set of r-z parameter + const double z0 = zT - cot * setup_->chosenRofZ(); + // skip this bin if z0 is outside of fiducial area (+- 15 cm) + if (abs(z0) > setup_->beamWindowZ() + cot_->base() * setup_->chosenRofZ() / 2.) + continue; + // layer ids crossed by left and right rough r-z parameter shape boundaries + vector> layers(boundaries); + // cotTheta wrt sectorCot of this bin boundaries + const vector cots = {sectorCot + cot - cot_->base() / 2., sectorCot + cot + cot_->base() / 2.}; + // loop over all unique modules + for (const SensorModule* sm : sensorModules) { + // check if module is crossed by left and right rough r-z parameter shape boundaries + for (int i = 0; i < boundaries; i++) { + const int j = boundaries - i - 1; + const double zTi = zTs[sm->r() > setup_->chosenRofZ() ? i : j]; + const double coti = cots[sm->r() > setup_->chosenRofZ() ? j : i]; + // distance between module and boundary in moudle tilt angle direction + const double d = + (zTi - sm->z() + (sm->r() - setup_->chosenRofZ()) * coti) / (sm->cosTilt() - sm->sinTilt() * coti); + // compare distance with module size and add module layer id to layers if module is crossed + if (abs(d) < sm->numColumns() * sm->pitchCol() / 2.) + layers[i].insert(sm->layerId()); + } + } + // mayber layers are given by layer ids crossed by only one booundary + set maybeLayer; + set_symmetric_difference(layers[0].begin(), + layers[0].end(), + layers[1].begin(), + layers[1].end(), + inserter(maybeLayer, maybeLayer.end())); + // layerEncoding is given by sorted layer ids crossed by any booundary + set layerEncoding; + set_union(layers[0].begin(), + layers[0].end(), + layers[1].begin(), + layers[1].end(), + inserter(layerEncoding, layerEncoding.end())); + vector& le = layerEncoding_[binEta][binZT][binCot]; + le = vector(layerEncoding.begin(), layerEncoding.end()); + vector& ml = maybeLayer_[binEta][binZT][binCot]; + ml.reserve(maybeLayer.size()); + for (int m : maybeLayer) { + int layer = distance(le.begin(), find(le.begin(), le.end(), m)); + if (layer >= setup_->numLayers()) + layer = setup_->numLayers() - 1; + ml.push_back(layer); + } + } + } + } + const bool print = false; + if (!print) + return; + static constexpr int widthLayer = 3; + static constexpr auto layerIds = {1, 2, 3, 4, 5, 6, 11, 12, 13, 14, 15}; + stringstream ss; + for (int layer : layerIds) { + auto encode = [layer, this](const vector& layers, int& l) { + const auto it = find(layers.begin(), layers.end(), layer); + if (it == layers.end()) + return false; + l = distance(layers.begin(), it); + if (l >= setup_->numLayers()) + l = setup_->numLayers() - 1; + return true; + }; + for (int binEta = 0; binEta < setup_->numSectorsEta(); binEta++) { + for (int binZT = 0; binZT < pow(2, zT_->width()); binZT++) { + for (int binCot = 0; binCot < pow(2, cot_->width()); binCot++) { + const int zT = + binZT < pow(2, zT_->width() - 1) ? binZT + pow(2, zT_->width() - 1) : binZT - pow(2, zT_->width() - 1); + const int cot = binCot < pow(2, cot_->width() - 1) ? binCot + pow(2, cot_->width() - 1) + : binCot - pow(2, cot_->width() - 1); + const vector& layers = layerEncoding_[binEta][zT][cot]; + const vector& maybes = maybeLayer_[binEta][zT][cot]; + int layerKF(-1); + if (encode(layers, layerKF)) + ss << "1" << TTBV(layerKF, widthLayer) << (encode(maybes, layerKF) ? "1" : "0"); + else + ss << "00000"; + ss << endl; + } + } + } + } + fstream file; + file.open("layerEncoding.txt", ios::out); + file << ss.rdbuf(); + file.close(); + } + + // encoded layer id for given eta sector, bin in zT, bin in cotThea and decoed layer id, returns -1 if layer incositent with track + const int LayerEncoding::layerIdKF(int binEta, int binZT, int binCot, int layerId) const { + const vector& layers = layerEncoding_[binEta][binZT][binCot]; + const auto it = find(layers.begin(), layers.end(), layerId); + if (it == layers.end()) + return -1; + int layer = distance(layers.begin(), it); + if (layer >= setup_->numLayers()) + layer = setup_->numLayers() - 1; + return layer; + } + + // pattern of maybe layers for given eta sector, bin in zT and bin in cotThea + TTBV LayerEncoding::maybePattern(int binEta, int binZT, int binCot) const { + TTBV ttBV(0, setup_->numLayers()); + const vector& layers = layerEncoding_[binEta][binZT][binCot]; + const vector& maybes = maybeLayer_[binEta][binZT][binCot]; + for (int m : maybes) + ttBV.set(distance(layers.begin(), find(layers.begin(), layers.end(), m))); + return ttBV; + } + +} // namespace trackerTFP \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/src/LayerEncodingRcd.cc b/L1Trigger/TrackerTFP/src/LayerEncodingRcd.cc new file mode 100644 index 0000000000000..dce78b3eb02cf --- /dev/null +++ b/L1Trigger/TrackerTFP/src/LayerEncodingRcd.cc @@ -0,0 +1,4 @@ +#include "L1Trigger/TrackerTFP/interface/LayerEncodingRcd.h" +#include "FWCore/Framework/interface/eventsetuprecord_registration_macro.h" + +EVENTSETUP_RECORD_REG(trackerTFP::LayerEncodingRcd); \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/src/MiniHoughTransform.cc b/L1Trigger/TrackerTFP/src/MiniHoughTransform.cc new file mode 100644 index 0000000000000..1091739d471b0 --- /dev/null +++ b/L1Trigger/TrackerTFP/src/MiniHoughTransform.cc @@ -0,0 +1,317 @@ +#include "L1Trigger/TrackerTFP/interface/MiniHoughTransform.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace edm; +using namespace tt; + +namespace trackerTFP { + + MiniHoughTransform::MiniHoughTransform(const ParameterSet& iConfig, + const Setup* setup, + const DataFormats* dataFormats, + int region) + : enableTruncation_(iConfig.getParameter("EnableTruncation")), + setup_(setup), + dataFormats_(dataFormats), + inv2R_(dataFormats_->format(Variable::inv2R, Process::ht)), + phiT_(dataFormats_->format(Variable::phiT, Process::ht)), + region_(region), + numBinsInv2R_(setup_->htNumBinsInv2R()), + numCells_(setup_->mhtNumCells()), + numNodes_(setup_->mhtNumDLBNodes()), + numChannel_(setup_->mhtNumDLBChannel()), + input_(numBinsInv2R_) {} + + // read in and organize input product (fill vector input_) + void MiniHoughTransform::consume(const StreamsStub& streams) { + auto valid = [](int& sum, const FrameStub& frame) { return sum += (frame.first.isNonnull() ? 1 : 0); }; + int nStubsHT(0); + for (int binInv2R = 0; binInv2R < numBinsInv2R_; binInv2R++) { + const StreamStub& stream = streams[region_ * numBinsInv2R_ + binInv2R]; + nStubsHT += accumulate(stream.begin(), stream.end(), 0, valid); + } + stubsHT_.reserve(nStubsHT); + stubsMHT_.reserve(nStubsHT * numCells_); + for (int binInv2R = 0; binInv2R < numBinsInv2R_; binInv2R++) { + const int inv2R = inv2R_.toSigned(binInv2R); + const StreamStub& stream = streams[region_ * numBinsInv2R_ + binInv2R]; + vector& stubs = input_[binInv2R]; + stubs.reserve(stream.size()); + // Store input stubs in vector, so rest of MHT algo can work with pointers to them (saves CPU) + for (const FrameStub& frame : stream) { + StubHT* stub = nullptr; + if (frame.first.isNonnull()) { + stubsHT_.emplace_back(frame, dataFormats_, inv2R); + stub = &stubsHT_.back(); + } + stubs.push_back(stub); + } + } + } + + // fill output products + void MiniHoughTransform::produce(StreamsStub& accepted, StreamsStub& lost) { + // fill MHT cells + vector> stubsCells(numBinsInv2R_ * numCells_); + for (int channel = 0; channel < numBinsInv2R_; channel++) + fill(channel, input_[channel], stubsCells); + // perform static load balancing + vector> streamsSLB(numBinsInv2R_); + for (int channel = 0; channel < numBinsInv2R_; channel++) { + vector> tmp(numCells_); + // gather streams to mux together: same MHT cell of 4 adjacent MHT input streams + for (int k = 0; k < numCells_; k++) + swap(tmp[k], stubsCells[(channel / numCells_) * numBinsInv2R_ + channel % numCells_ + k * numCells_]); + slb(tmp, streamsSLB[channel], lost[channel]); + } + // dynamic load balancing stage 1 + vector> streamsDLB(numBinsInv2R_); + for (int node = 0; node < numNodes_; node++) { + vector> tmp(numChannel_); + // gather streams to dynamically balance them + for (int k = 0; k < numChannel_; k++) + swap(tmp[k], streamsSLB[(node / numCells_) * numNodes_ + node % numCells_ + k * numCells_]); + dlb(tmp); + for (int k = 0; k < numChannel_; k++) + swap(tmp[k], streamsDLB[node * numChannel_ + k]); + } + // dynamic load balancing stage 2 + vector> streamsMHT(numBinsInv2R_); + for (int node = 0; node < numNodes_; node++) { + vector> tmp(numChannel_); + // gather streams to dynamically balance them + for (int k = 0; k < numChannel_; k++) + swap(tmp[k], streamsDLB[node + k * numNodes_]); + dlb(tmp); + for (int k = 0; k < numChannel_; k++) + swap(tmp[k], streamsMHT[node * numChannel_ + k]); + } + // fill output product + for (int channel = 0; channel < numBinsInv2R_; channel++) { + const vector& stubs = streamsMHT[channel]; + StreamStub& stream = accepted[region_ * numBinsInv2R_ + channel]; + stream.reserve(stubs.size()); + for (StubMHT* stub : stubs) + stream.emplace_back(stub ? stub->frame() : FrameStub()); + } + } + + // perform finer pattern recognition per track + void MiniHoughTransform::fill(int channel, const vector& stubs, vector>& streams) { + if (stubs.empty()) + return; + int id; + auto differentHT = [&id](StubHT* stub) { return id != stub->trackId(); }; + auto differentMHT = [&id](StubMHT* stub) { return !stub || id != stub->trackId(); }; + for (auto it = stubs.begin(); it != stubs.end();) { + const auto start = it; + id = (*it)->trackId(); + it = find_if(it, stubs.end(), differentHT); + const int size = distance(start, it); + // create finer track candidates stub container + vector> mhtCells(numCells_); + for (vector& mhtCell : mhtCells) + mhtCell.reserve(size); + // fill finer track candidates stub container + for (auto stub = start; stub != it; stub++) { + const double r = (*stub)->r(); + const double chi = (*stub)->phi(); + // identify finer track candidates for this stub + // 0 and 1 belong to the MHT cells with larger inv2R; 0 and 2 belong to those with smaller track PhiT + vector cells; + cells.reserve(numCells_); + const bool compA = 2. * abs(chi) < phiT_.base(); + const bool compB = 2. * abs(chi) < abs(r * inv2R_.base()); + const bool compAB = compA && compB; + if (chi >= 0. && r >= 0.) { + cells.push_back(3); + if (compA) + cells.push_back(1); + if (compAB) + cells.push_back(2); + } + if (chi >= 0. && r < 0.) { + cells.push_back(1); + if (compA) + cells.push_back(3); + if (compAB) + cells.push_back(0); + } + if (chi < 0. && r >= 0.) { + cells.push_back(0); + if (compA) + cells.push_back(2); + if (compAB) + cells.push_back(1); + } + if (chi < 0. && r < 0.) { + cells.push_back(2); + if (compA) + cells.push_back(0); + if (compAB) + cells.push_back(3); + } + // organise stubs in finer track candidates + for (int cell : cells) { + const int inv2R = cell / setup_->mhtNumBinsPhiT(); + const int phiT = cell % setup_->mhtNumBinsPhiT(); + stubsMHT_.emplace_back(**stub, phiT, inv2R); + mhtCells[cell].push_back(&stubsMHT_.back()); + } + } + // perform pattern recognition + for (int sel = 0; sel < numCells_; sel++) { + deque& stream = streams[channel * numCells_ + sel]; + vector& mhtCell = mhtCells[sel]; + set layers; + auto toLayer = [](StubMHT* stub) { return stub->layer(); }; + transform(mhtCell.begin(), mhtCell.end(), inserter(layers, layers.begin()), toLayer); + if ((int)layers.size() < setup_->mhtMinLayers()) + mhtCell.clear(); + for (StubMHT* stub : mhtCell) + stream.push_back(stub); + stream.insert(stream.end(), size - (int)mhtCell.size(), nullptr); + } + } + for (int sel = 0; sel < numCells_; sel++) { + deque& stream = streams[channel * numCells_ + sel]; + // remove all gaps between end and last stub + for (auto it = stream.end(); it != stream.begin();) + it = (*--it) ? stream.begin() : stream.erase(it); + // read out fine track cannot start before rough track has read in completely, add gaps to take this into account + int pos(0); + for (auto it = stream.begin(); it != stream.end();) { + if (!(*it)) { + it = stream.erase(it); + continue; + } + id = (*it)->trackId(); + const int s = distance(it, find_if(it, stream.end(), differentMHT)); + const int d = distance(stream.begin(), it); + pos += s; + if (d < pos) { + const int diff = pos - d; + it = stream.insert(it, diff, nullptr); + it = next(it, diff); + } else + it = stream.erase(remove(next(stream.begin(), pos), it, nullptr), it); + it = next(it, s); + } + // adjust stream start so that first output stub is in first place in case of quickest track + if (!stream.empty()) + stream.erase(stream.begin(), next(stream.begin(), setup_->mhtMinLayers())); + } + } + + // Static load balancing of inputs: mux 4 streams to 1 stream + void MiniHoughTransform::slb(vector>& inputs, vector& accepted, StreamStub& lost) const { + if (all_of(inputs.begin(), inputs.end(), [](const deque& stubs) { return stubs.empty(); })) + return; + auto size = [](int& sum, const deque& stubs) { return sum += stubs.size(); }; + const int nFrames = accumulate(inputs.begin(), inputs.end(), 0, size); + accepted.reserve(nFrames); + // input fifos + vector> stacks(numCells_); + // helper for handshake + TTBV empty(-1, numCells_, true); + TTBV enable(0, numCells_); + // clock accurate firmware emulation, each while trip describes one clock tick, one stub in and one stub out per tick + while (!all_of(inputs.begin(), inputs.end(), [](const deque& d) { return d.empty(); }) or + !all_of(stacks.begin(), stacks.end(), [](const deque& d) { return d.empty(); })) { + // store stub in fifo + for (int channel = 0; channel < numCells_; channel++) { + StubMHT* stub = pop_front(inputs[channel]); + if (stub) + stacks[channel].push_back(stub); + } + // identify empty fifos + for (int channel = 0; channel < numCells_; channel++) + empty[channel] = stacks[channel].empty(); + // chose new fifo to read from if current fifo got empty + const int iEnableOld = enable.plEncode(); + if (enable.none() || empty[iEnableOld]) { + enable.reset(); + const int iNotEmpty = empty.plEncode(false); + if (iNotEmpty < numCells_) + enable.set(iNotEmpty); + } + // read from chosen fifo + const int iEnable = enable.plEncode(); + if (enable.any()) + accepted.push_back(pop_front(stacks[iEnable])); + else + // gap if no fifo has been chosen + accepted.push_back(nullptr); + } + // perform truncation if desired + if (enableTruncation_ && (int)accepted.size() > setup_->numFrames()) { + const auto limit = next(accepted.begin(), setup_->numFrames()); + auto valid = [](int& sum, StubMHT* stub) { return sum += stub ? 1 : 0; }; + const int nLost = accumulate(limit, accepted.end(), 0, valid); + lost.reserve(nLost); + for (auto it = limit; it != accepted.end(); it++) + if (*it) + lost.emplace_back((*it)->frame()); + accepted.erase(limit, accepted.end()); + } + // cosmetics -- remove gaps at the end of stream + for (auto it = accepted.end(); it != accepted.begin();) + it = (*--it) == nullptr ? accepted.erase(it) : accepted.begin(); + } + + // Dynamic load balancing of inputs: swapping parts of streams to balance the amount of tracks per stream + void MiniHoughTransform::dlb(vector>& streams) const { + if (all_of(streams.begin(), streams.end(), [](const vector& stubs) { return stubs.empty(); })) + return; + auto maxSize = [](int& size, const vector& stream) { return size = max(size, (int)stream.size()); }; + const int nMax = accumulate(streams.begin(), streams.end(), 0, maxSize); + for (vector& stream : streams) + stream.resize(nMax, nullptr); + vector prevTrks(numChannel_, -1); + bool swapping(false); + vector loads(numChannel_, 0); + for (int i = 0; i < nMax; i++) { + TTBV newTrks(0, numChannel_); + for (int k = 0; k < numChannel_; k++) + if (!streams[numChannel_ - k - 1][i] && streams[k][i] && streams[k][i]->trackId() != prevTrks[k]) + newTrks.set(k); + for (int k = 0; k < numChannel_; k++) + if (newTrks[k]) + if ((swapping && loads[numChannel_ - k - 1] > loads[k]) || + (!swapping && loads[k] > loads[numChannel_ - k - 1])) + swapping = !swapping; + for (int k = 0; k < numChannel_; k++) { + if (streams[k][i]) + loads[swapping ? numChannel_ - k - 1 : k]++; + prevTrks[k] = streams[k][i] ? streams[k][i]->trackId() : -1; + } + if (swapping) + swap(streams[0][i], streams[1][i]); + } + // remove all gaps between end and last stub + for (vector& stream : streams) + for (auto it = stream.end(); it != stream.begin();) + it = (*--it) ? stream.begin() : stream.erase(it); + } + + // remove and return first element of deque, returns nullptr if empty + template + T* MiniHoughTransform::pop_front(deque& ts) const { + T* t = nullptr; + if (!ts.empty()) { + t = ts.front(); + ts.pop_front(); + } + return t; + } + +} // namespace trackerTFP \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/src/State.cc b/L1Trigger/TrackerTFP/src/State.cc new file mode 100644 index 0000000000000..90e9aca2cea02 --- /dev/null +++ b/L1Trigger/TrackerTFP/src/State.cc @@ -0,0 +1,127 @@ +#include "L1Trigger/TrackerTFP/interface/State.h" + +using namespace std; +using namespace tt; + +namespace trackerTFP { + + // default constructor + State::State(State* state) + : dataFormats_(state->dataFormats_), + setup_(state->setup_), + track_(state->track_), + trackId_(state->trackId_), + parent_(state->parent_), + stub_(state->stub_), + layerMap_(state->layerMap_), + hitPattern_(state->hitPattern_), + x0_(state->x0_), + x1_(state->x1_), + x2_(state->x2_), + x3_(state->x3_), + C00_(state->C00_), + C01_(state->C01_), + C11_(state->C11_), + C22_(state->C22_), + C23_(state->C23_), + C33_(state->C33_), + numSkippedLayers_(state->numSkippedLayers_), + numConsistentLayers_(state->numConsistentLayers_) {} + + // proto state constructor + State::State(const DataFormats* dataFormats, TrackKFin* track, int trackId) + : dataFormats_(dataFormats), + setup_(dataFormats->setup()), + track_(track), + trackId_(trackId), + parent_(nullptr), + stub_(nullptr), + layerMap_(setup_->numLayers()), + hitPattern_(0, setup_->numLayers()), + numSkippedLayers_(0), + numConsistentLayers_(0) { + // initial track parameter residuals w.r.t. found track + x0_ = 0.; + x1_ = 0.; + x2_ = 0.; + x3_ = 0.; + // initial uncertainties + C00_ = pow(dataFormats_->base(Variable::inv2R, Process::kfin), 2); + C11_ = pow(dataFormats_->base(Variable::phiT, Process::kfin), 2); + C22_ = pow(dataFormats_->base(Variable::cot, Process::kfin), 2); + C33_ = pow(dataFormats_->base(Variable::zT, Process::kfin), 2); + C01_ = 0.; + C23_ = 0.; + // first stub from first layer on input track with stubs + stub_ = track->layerStub(track->hitPattern().plEncode()); + } + + // combinatoric state constructor + State::State(State* state, StubKFin* stub) : State(state) { + parent_ = state->parent(); + stub_ = stub; + } + + // updated state constructor + State::State(State* state, const std::vector& doubles) : State(state) { + parent_ = state; + // updated track parameter and uncertainties + x0_ = doubles[0]; + x1_ = doubles[1]; + x2_ = doubles[2]; + x3_ = doubles[3]; + C00_ = doubles[4]; + C11_ = doubles[5]; + C22_ = doubles[6]; + C33_ = doubles[7]; + C01_ = doubles[8]; + C23_ = doubles[9]; + // update maps + const int layer = stub_->layer(); + hitPattern_.set(layer); + const vector& stubs = track_->layerStubs(layer); + layerMap_[layer] = distance(stubs.begin(), find(stubs.begin(), stubs.end(), stub_)); + // pick next stub (first stub in next layer with stub) + stub_ = nullptr; + if (hitPattern_.count() == setup_->kfMinLayers()) + return; + for (int nextLayer = layer + 1; nextLayer < setup_->numLayers(); nextLayer++) { + if (track_->hitPattern(nextLayer)) { + stub_ = track_->layerStub(nextLayer); + break; + } + } + } + + // collection of stubs added so far to state + vector State::stubs() const { + vector stubs; + stubs.reserve(hitPattern_.count()); + State* s = parent_; + while (s) { + stubs.emplace_back(*(s->stub()), x0_, x1_, x2_, x3_); + s = s->parent(); + } + return stubs; + } + + // Determine quality of completed state + void State::finish() { + const vector& stubs = this->stubs(); + auto consistent = [this](int& sum, const StubKF& stub) { + auto inConsistentRange = [](float v, float r, float d) { return abs(v) <= (r + d) / 2.; }; + // Check stub consistent with helix, allowing for stub & digi uncertainty + const bool inRange0 = + inConsistentRange(stub.phi(), stub.dPhi(), dataFormats_->format(Variable::dPhi, Process::kf).base()); + const bool inRange1 = + inConsistentRange(stub.z(), stub.dZ(), dataFormats_->format(Variable::dZ, Process::kf).base()); + return sum += (inRange0 && inRange1 ? 1 : 0); + }; + numConsistentLayers_ = accumulate(stubs.begin(), stubs.end(), 0, consistent); + TTBV pattern = hitPattern_; + pattern |= maybePattern(); + // Skipped layers before final stub on state + numSkippedLayers_ = pattern.count(0, hitPattern_.pmEncode(), false); + } + +} // namespace trackerTFP \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/src/ZHoughTransform.cc b/L1Trigger/TrackerTFP/src/ZHoughTransform.cc new file mode 100644 index 0000000000000..3b694013fc542 --- /dev/null +++ b/L1Trigger/TrackerTFP/src/ZHoughTransform.cc @@ -0,0 +1,322 @@ +#include "L1Trigger/TrackerTFP/interface/ZHoughTransform.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace edm; +using namespace tt; + +namespace trackerTFP { + + ZHoughTransform::ZHoughTransform(const ParameterSet& iConfig, + const Setup* setup, + const DataFormats* dataFormats, + int region) + : enableTruncation_(iConfig.getParameter("EnableTruncation")), + setup_(setup), + dataFormats_(dataFormats), + region_(region), + input_(dataFormats->numChannel(Process::mht)), + stage_(0) {} + + // read in and organize input product (fill vector input_) + void ZHoughTransform::consume(const StreamsStub& streams) { + auto valid = [](int& sum, const FrameStub& frame) { return sum += (frame.first.isNonnull() ? 1 : 0); }; + const int offset = region_ * dataFormats_->numChannel(Process::mht); + int nStubsMHT(0); + for (int channel = 0; channel < dataFormats_->numChannel(Process::mht); channel++) { + const StreamStub& stream = streams[offset + channel]; + nStubsMHT += accumulate(stream.begin(), stream.end(), 0, valid); + } + stubsZHT_.reserve(nStubsMHT * (setup_->zhtNumCells() * setup_->zhtNumStages())); + for (int channel = 0; channel < dataFormats_->numChannel(Process::mht); channel++) { + const StreamStub& stream = streams[offset + channel]; + vector& stubs = input_[channel]; + stubs.reserve(stream.size()); + // Store input stubs in vector, so rest of ZHT algo can work with pointers to them (saves CPU) + for (const FrameStub& frame : stream) { + StubZHT* stub = nullptr; + if (frame.first.isNonnull()) { + StubMHT stubMHT(frame, dataFormats_); + stubsZHT_.emplace_back(stubMHT); + stub = &stubsZHT_.back(); + } + stubs.push_back(stub); + } + } + } + + // fill output products + void ZHoughTransform::produce(StreamsStub& accepted, StreamsStub& lost) { + vector> streams(dataFormats_->numChannel(Process::mht)); + for (int channel = 0; channel < dataFormats_->numChannel(Process::mht); channel++) + streams[channel] = deque(input_[channel].begin(), input_[channel].end()); + vector> stubsCells(dataFormats_->numChannel(Process::mht) * setup_->zhtNumCells()); + for (stage_ = 0; stage_ < setup_->zhtNumStages(); stage_++) { + // fill ZHT cells + for (int channel = 0; channel < dataFormats_->numChannel(Process::mht); channel++) + fill(channel, streams[channel], stubsCells); + // perform static load balancing + for (int channel = 0; channel < dataFormats_->numChannel(Process::mht); channel++) { + vector> tmp(setup_->zhtNumCells()); + // gather streams to mux together: same ZHT cell of 4 adjacent ZHT input streams + for (int k = 0; k < setup_->zhtNumCells(); k++) + //swap(tmp[k], stubsCells[(channel / setup_->zhtNumCells()) * dataFormats_->numChannel(Process::mht) + channel % setup_->zhtNumCells() + k * setup_->zhtNumCells()]); + swap(tmp[k], stubsCells[channel * setup_->zhtNumCells() + k]); + slb(tmp, streams[channel], lost[channel]); + } + } + // fill output product + for (int channel = 0; channel < dataFormats_->numChannel(Process::mht); channel++) { + deque& stubs = streams[channel]; + StreamStub& stream = accepted[region_ * dataFormats_->numChannel(Process::mht) + channel]; + merge(stubs, stream); + } + } + + // perform finer pattern recognition per track + void ZHoughTransform::fill(int channel, const deque& stubs, vector>& streams) { + if (stubs.empty()) + return; + const double baseZT = + dataFormats_->format(Variable::zT, Process::zht).base() * pow(2, setup_->zhtNumStages() - stage_); + const double baseCot = + dataFormats_->format(Variable::cot, Process::zht).base() * pow(2, setup_->zhtNumStages() - stage_); + int id; + auto different = [&id](StubZHT* stub) { return !stub || id != stub->trackId(); }; + for (auto it = stubs.begin(); it != stubs.end();) { + if (!*it) { + const auto begin = find_if(it, stubs.end(), [](StubZHT* stub) { return stub; }); + const int nGaps = distance(it, begin); + for (deque& stream : streams) + stream.insert(stream.end(), nGaps, nullptr); + it = begin; + continue; + } + const auto start = it; + const double cotGlobal = (*start)->cotf() + setup_->sectorCot((*start)->sectorEta()); + id = (*it)->trackId(); + it = find_if(it, stubs.end(), different); + const int size = distance(start, it); + // create finer track candidates stub container + vector> mhtCells(setup_->zhtNumCells()); + for (vector& mhtCell : mhtCells) + mhtCell.reserve(size); + // fill finer track candidates stub container + for (auto stub = start; stub != it; stub++) { + const double r = (*stub)->r() + setup_->chosenRofPhi() - setup_->chosenRofZ(); + const double chi = (*stub)->chi(); + const double dChi = setup_->dZ((*stub)->ttStubRef(), cotGlobal); + // identify finer track candidates for this stub + // 0 and 1 belong to the ZHT cells with smaller cot; 0 and 2 belong to those with smaller zT + vector cells; + cells.reserve(setup_->zhtNumCells()); + const bool compA = 2. * abs(chi) < baseZT + dChi; + const bool compB = 2. * abs(chi) < abs(r) * baseCot + dChi; + const bool compC = 2. * abs(chi) < dChi; + if (chi >= 0. && r >= 0.) { + cells.push_back(1); + if (compA) + cells.push_back(3); + if (compB) + cells.push_back(0); + if (compC) + cells.push_back(2); + } + if (chi >= 0. && r < 0.) { + cells.push_back(3); + if (compA) + cells.push_back(1); + if (compB) + cells.push_back(2); + if (compC) + cells.push_back(0); + } + if (chi < 0. && r >= 0.) { + cells.push_back(2); + if (compA) + cells.push_back(0); + if (compB) + cells.push_back(3); + if (compC) + cells.push_back(1); + } + if (chi < 0. && r < 0.) { + cells.push_back(0); + if (compA) + cells.push_back(2); + if (compB) + cells.push_back(1); + if (compC) + cells.push_back(3); + } + for (int cell : cells) { + const double cot = (cell / setup_->zhtNumBinsZT() - .5) * baseCot / 2.; + const double zT = (cell % setup_->zhtNumBinsZT() - .5) * baseZT / 2.; + stubsZHT_.emplace_back(**stub, zT, cot, cell); + mhtCells[cell].push_back(&stubsZHT_.back()); + } + } + // perform pattern recognition + for (int sel = 0; sel < setup_->zhtNumCells(); sel++) { + deque& stream = streams[channel * setup_->zhtNumCells() + sel]; + vector& mhtCell = mhtCells[sel]; + set layers; + auto toLayer = [](StubZHT* stub) { return stub->layer(); }; + transform(mhtCell.begin(), mhtCell.end(), inserter(layers, layers.begin()), toLayer); + if ((int)layers.size() < setup_->mhtMinLayers()) + mhtCell.clear(); + for (StubZHT* stub : mhtCell) + stream.push_back(stub); + stream.insert(stream.end(), size - (int)mhtCell.size(), nullptr); + } + } + for (int sel = 0; sel < setup_->zhtNumCells(); sel++) { + deque& stream = streams[channel * setup_->zhtNumCells() + sel]; + // remove all gaps between end and last stub + for (auto it = stream.end(); it != stream.begin();) + it = (*--it) ? stream.begin() : stream.erase(it); + // read out fine track cannot start before rough track has read in completely, add gaps to take this into account + int pos(0); + for (auto it = stream.begin(); it != stream.end();) { + if (!(*it)) { + it = stream.erase(it); + continue; + } + id = (*it)->trackId(); + const int s = distance(it, find_if(it, stream.end(), different)); + const int d = distance(stream.begin(), it); + pos += s; + if (d < pos) { + const int diff = pos - d; + it = stream.insert(it, diff, nullptr); + it = next(it, diff); + } else + it = stream.erase(remove(next(stream.begin(), pos), it, nullptr), it); + it = next(it, s); + } + // adjust stream start so that first output stub is in first place in case of quickest track + if (!stream.empty()) + stream.erase(stream.begin(), next(stream.begin(), setup_->mhtMinLayers())); + } + } + + // Static load balancing of inputs: mux 4 streams to 1 stream + void ZHoughTransform::slb(vector>& inputs, deque& accepted, StreamStub& lost) const { + accepted.clear(); + if (all_of(inputs.begin(), inputs.end(), [](const deque& stubs) { return stubs.empty(); })) + return; + // input fifos + vector> stacks(setup_->zhtNumCells()); + // helper for handshake + TTBV empty(-1, setup_->zhtNumCells(), true); + TTBV enable(0, setup_->zhtNumCells()); + // clock accurate firmware emulation, each while trip describes one clock tick, one stub in and one stub out per tick + while (!all_of(inputs.begin(), inputs.end(), [](const deque& d) { return d.empty(); }) or + !all_of(stacks.begin(), stacks.end(), [](const deque& d) { return d.empty(); })) { + // store stub in fifo + for (int channel = 0; channel < setup_->zhtNumCells(); channel++) { + StubZHT* stub = pop_front(inputs[channel]); + if (stub) + stacks[channel].push_back(stub); + } + // identify empty fifos + for (int channel = 0; channel < setup_->zhtNumCells(); channel++) + empty[channel] = stacks[channel].empty(); + // chose new fifo to read from if current fifo got empty + const int iEnableOld = enable.plEncode(); + if (enable.none() || empty[iEnableOld]) { + enable.reset(); + const int iNotEmpty = empty.plEncode(false); + if (iNotEmpty < setup_->zhtNumCells()) + enable.set(iNotEmpty); + } + // read from chosen fifo + const int iEnable = enable.plEncode(); + if (enable.any()) + accepted.push_back(pop_front(stacks[iEnable])); + else + // gap if no fifo has been chosen + accepted.push_back(nullptr); + } + // perform truncation if desired + if (enableTruncation_ && (int)accepted.size() > setup_->numFrames()) { + const auto limit = next(accepted.begin(), setup_->numFrames()); + auto valid = [](int& sum, StubZHT* stub) { return sum += stub ? 1 : 0; }; + const int nLost = accumulate(limit, accepted.end(), 0, valid); + lost.reserve(nLost); + for (auto it = limit; it != accepted.end(); it++) + if (*it) + lost.emplace_back((*it)->frame()); + accepted.erase(limit, accepted.end()); + } + // cosmetics -- remove gaps at the end of stream + for (auto it = accepted.end(); it != accepted.begin();) + it = (*--it) == nullptr ? accepted.erase(it) : accepted.begin(); + } + + // + void ZHoughTransform::merge(deque& stubs, StreamStub& stream) const { + stubs.erase(remove(stubs.begin(), stubs.end(), nullptr), stubs.end()); + /*stream.reserve(stubs.size()); + transform(stubs.begin(), stubs.end(), back_inserter(stream), [](StubZHT* stub){ return stub->frame(); }); + return;*/ + map>> candidates; + const int weight = setup_->zhtNumCells() * pow(2, setup_->zhtNumStages()); + for (const StubZHT* stub : stubs) + candidates[stub->trackId() / weight].emplace(stub->cot(), stub->zT()); + vector> tracks(candidates.size()); + for (auto it = stubs.begin(); it != stubs.end();) { + const auto start = it; + const int id = (*it)->trackId(); + const int candId = id / weight; + const auto m = candidates.find(candId); + pair cotp(9e9, -9e9); + pair zTp(9e9, -9e9); + for (const pair& para : m->second) { + cotp = {min(cotp.first, para.first), max(cotp.second, para.first)}; + zTp = {min(zTp.first, para.second), max(zTp.second, para.second)}; + } + const int cot = (cotp.first + cotp.second) / 2; + const int zT = (cotp.first + cotp.second) / 2; + const int pos = distance(candidates.begin(), m); + deque& track = tracks[pos]; + auto different = [id](const StubZHT* stub) { return id != stub->trackId(); }; + it = find_if(it, stubs.end(), different); + for (auto s = start; s != it; s++) { + if (find_if(track.begin(), track.end(), [s](const FrameStub& stub) { + return (*s)->ttStubRef() == stub.first; + }) != track.end()) + continue; + const StubZHT stub(**s, cot, zT); + track.push_back(stub.frame()); + } + } + const int size = accumulate(tracks.begin(), tracks.end(), 0, [](int& sum, const deque& stubs) { + return sum += (int)stubs.size(); + }); + stream.reserve(size); + for (deque& track : tracks) + for (const FrameStub& stub : track) + stream.push_back(stub); + } + + // remove and return first element of deque, returns nullptr if empty + template + T* ZHoughTransform::pop_front(deque& ts) const { + T* t = nullptr; + if (!ts.empty()) { + t = ts.front(); + ts.pop_front(); + } + return t; + } + +} // namespace trackerTFP \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/test/AnalyzerDemonstrator.cc b/L1Trigger/TrackerTFP/test/AnalyzerDemonstrator.cc new file mode 100644 index 0000000000000..4cfd96b91d92f --- /dev/null +++ b/L1Trigger/TrackerTFP/test/AnalyzerDemonstrator.cc @@ -0,0 +1,155 @@ +#include "FWCore/Framework/interface/one/EDAnalyzer.h" +#include "FWCore/Framework/interface/Run.h" +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/EventSetup.h" +#include "FWCore/Framework/interface/MakerMacros.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/Utilities/interface/EDGetToken.h" +#include "FWCore/Utilities/interface/ESGetToken.h" +#include "FWCore/Utilities/interface/InputTag.h" +#include "FWCore/Utilities/interface/Exception.h" +#include "DataFormats/Common/interface/Handle.h" + +#include "L1Trigger/TrackerTFP/interface/Demonstrator.h" + +#include + +using namespace std; +using namespace edm; +using namespace tt; + +namespace trackerTFP { + + /*! \class trackerTFP::AnalyzerDemonstrator + * \brief Class to demontrate correctness of track trigger emulators + * by comparing FW with SW + * \author Thomas Schuh + * \date 2020, Nov + */ + class AnalyzerDemonstrator : public one::EDAnalyzer { + public: + AnalyzerDemonstrator(const ParameterSet& iConfig); + void beginJob() override {} + void beginRun(const Run& iEvent, const EventSetup& iSetup) override; + void analyze(const Event& iEvent, const EventSetup& iSetup) override; + void endRun(const Run& iEvent, const EventSetup& iSetup) override {} + void endJob() override {} + + private: + // + void convert(const Event& iEvent, + const EDGetTokenT& tokenTracks, + const EDGetTokenT& tokenStubs, + vector>& bits) const; + // + template + void convert(const T& collection, vector>& bits) const; + // ED input token of Tracks + EDGetTokenT edGetTokenStubsIn_; + EDGetTokenT edGetTokenStubsOut_; + // ED input token of Stubs + EDGetTokenT edGetTokenTracksIn_; + EDGetTokenT edGetTokenTracksOut_; + // Setup token + ESGetToken esGetTokenSetup_; + // Demonstrator token + ESGetToken esGetTokenDemonstrator_; + // + const Setup* setup_; + // + const Demonstrator* demonstrator_; + }; + + AnalyzerDemonstrator::AnalyzerDemonstrator(const ParameterSet& iConfig) { + // book in- and output ED products + const string& labelIn = iConfig.getParameter("LabelIn"); + const string& labelOut = iConfig.getParameter("LabelOut"); + const string& branchStubs = iConfig.getParameter("BranchAcceptedStubs"); + const string& branchTracks = iConfig.getParameter("BranchAcceptedTracks"); + edGetTokenStubsIn_ = consumes(InputTag(labelIn, branchStubs)); + if (labelIn == "TrackerTFPProducerKFin" || labelIn == "TrackerTFPProducerKF") + edGetTokenTracksIn_ = consumes(InputTag(labelIn, branchTracks)); + if (labelOut == "TrackerTFPProducerKF" || labelOut == "TrackerTFPProducerDR") + edGetTokenTracksOut_ = consumes(InputTag(labelOut, branchTracks)); + // book ES products + esGetTokenSetup_ = esConsumes(); + esGetTokenDemonstrator_ = esConsumes(); + // initial ES product + setup_ = nullptr; + demonstrator_ = nullptr; + } + + void AnalyzerDemonstrator::beginRun(const Run& iEvent, const EventSetup& iSetup) { + // + setup_ = &iSetup.getData(esGetTokenSetup_); + // + demonstrator_ = &iSetup.getData(esGetTokenDemonstrator_); + } + + void AnalyzerDemonstrator::analyze(const Event& iEvent, const EventSetup& iSetup) { + vector> input; + vector> output; + convert(iEvent, edGetTokenTracksIn_, edGetTokenStubsIn_, input); + convert(iEvent, edGetTokenTracksOut_, edGetTokenStubsOut_, output); + if (!demonstrator_->analyze(input, output)) { + cms::Exception exception("RunTimeError."); + exception.addContext("trackerTFP::AnalyzerDemonstrator::analyze"); + exception << "Bit error detected."; + throw exception; + } + } + + // + void AnalyzerDemonstrator::convert(const Event& iEvent, + const EDGetTokenT& tokenTracks, + const EDGetTokenT& tokenStubs, + vector>& bits) const { + const bool tracks = !tokenTracks.isUninitialized(); + const bool stubs = !tokenStubs.isUninitialized(); + Handle handleStubs; + Handle handleTracks; + int numChannelStubs(0); + if (stubs) { + iEvent.getByToken(tokenStubs, handleStubs); + numChannelStubs = handleStubs->size(); + } + int numChannelTracks(0); + if (tracks) { + iEvent.getByToken(tokenTracks, handleTracks); + numChannelTracks = handleTracks->size(); + } + numChannelTracks /= setup_->numRegions(); + numChannelStubs /= (setup_->numRegions() * (tracks ? numChannelTracks : 1)); + bits.reserve(numChannelTracks + numChannelStubs); + for (int region = 0; region < setup_->numRegions(); region++) { + if (tracks) { + const int offsetTracks = region * numChannelTracks; + for (int channelTracks = 0; channelTracks < numChannelTracks; channelTracks++) { + const int offsetStubs = (region * numChannelTracks + channelTracks) * numChannelStubs; + if (tracks) + convert(handleTracks->at(offsetTracks + channelTracks), bits); + if (stubs) { + for (int channelStubs = 0; channelStubs < numChannelStubs; channelStubs++) + convert(handleStubs->at(offsetStubs + channelStubs), bits); + } + } + } else { + const int offsetStubs = region * numChannelStubs; + for (int channelStubs = 0; channelStubs < numChannelStubs; channelStubs++) + convert(handleStubs->at(offsetStubs + channelStubs), bits); + } + } + } + + // + template + void AnalyzerDemonstrator::convert(const T& collection, vector>& bits) const { + bits.emplace_back(); + vector& bvs = bits.back(); + bvs.reserve(collection.size()); + transform(collection.begin(), collection.end(), back_inserter(bvs), [](const auto& frame) { return frame.second; }); + } + +} // namespace trackerTFP + +DEFINE_FWK_MODULE(trackerTFP::AnalyzerDemonstrator); \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/test/AnalyzerGP.cc b/L1Trigger/TrackerTFP/test/AnalyzerGP.cc new file mode 100644 index 0000000000000..422b729696efb --- /dev/null +++ b/L1Trigger/TrackerTFP/test/AnalyzerGP.cc @@ -0,0 +1,192 @@ +#include "FWCore/Framework/interface/one/EDAnalyzer.h" +#include "FWCore/Framework/interface/Run.h" +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/EventSetup.h" +#include "FWCore/Framework/interface/MakerMacros.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/ServiceRegistry/interface/Service.h" +#include "FWCore/MessageLogger/interface/MessageLogger.h" +#include "FWCore/Utilities/interface/EDGetToken.h" +#include "FWCore/Utilities/interface/InputTag.h" +#include "FWCore/Utilities/interface/Exception.h" +#include "CommonTools/UtilAlgos/interface/TFileService.h" +#include "DataFormats/Common/interface/Handle.h" + +#include "SimTracker/TrackTriggerAssociation/interface/StubAssociation.h" +#include "L1Trigger/TrackTrigger/interface/Setup.h" + +#include +#include + +#include +#include +#include +#include + +using namespace std; +using namespace edm; +using namespace tt; + +namespace trackerTFP { + + /*! \class trackerTFP::AnalyzerGP + * \brief Class to analyze hardware like structured TTStub Collection generated by Geometric Processor + * \author Thomas Schuh + * \date 2020, Apr + */ + class AnalyzerGP : public one::EDAnalyzer { + public: + AnalyzerGP(const ParameterSet& iConfig); + void beginJob() override {} + void beginRun(const Run& iEvent, const EventSetup& iSetup) override; + void analyze(const Event& iEvent, const EventSetup& iSetup) override; + void endRun(const Run& iEvent, const EventSetup& iSetup) override {} + void endJob() override; + + private: + // ED input token of stubs + EDGetTokenT edGetTokenAccepted_; + // ED input token of lost stubs + EDGetTokenT edGetTokenLost_; + // ED input token of TTStubRef to TPPtr association for tracking efficiency + EDGetTokenT edGetTokenAss_; + // Setup token + ESGetToken esGetToken_; + // stores, calculates and provides run-time constants + const Setup* setup_; + // enables analyze of TPs + bool useMCTruth_; + // + int nEvents_; + + // Histograms + + TProfile* prof_; + TProfile* profChannel_; + TH1F* hisChannel_; + + // printout + stringstream log_; + }; + + AnalyzerGP::AnalyzerGP(const ParameterSet& iConfig) + : useMCTruth_(iConfig.getParameter("UseMCTruth")), nEvents_(0) { + usesResource("TFileService"); + // book in- and output ED products + const string& label = iConfig.getParameter("LabelGP"); + const string& branchAccepted = iConfig.getParameter("BranchAcceptedStubs"); + const string& branchLost = iConfig.getParameter("BranchLostStubs"); + edGetTokenAccepted_ = consumes(InputTag(label, branchAccepted)); + edGetTokenLost_ = consumes(InputTag(label, branchLost)); + if (useMCTruth_) { + const auto& inputTagAss = iConfig.getParameter("InputTagSelection"); + edGetTokenAss_ = consumes(inputTagAss); + } + // book ES product + esGetToken_ = esConsumes(); + setup_ = nullptr; + // log config + log_.setf(ios::fixed, ios::floatfield); + log_.precision(4); + } + + void AnalyzerGP::beginRun(const Run& iEvent, const EventSetup& iSetup) { + // helper class to store configurations + setup_ = &iSetup.getData(esGetToken_); + // book histograms + Service fs; + TFileDirectory dir; + dir = fs->mkdir("GP"); + prof_ = dir.make("Counts", ";", 4, 0.5, 4.5); + prof_->GetXaxis()->SetBinLabel(1, "Stubs"); + prof_->GetXaxis()->SetBinLabel(2, "Lost Stubs"); + prof_->GetXaxis()->SetBinLabel(3, "Found TPs"); + prof_->GetXaxis()->SetBinLabel(4, "Selected TPs"); + // channel occupancy + constexpr int maxOcc = 180; + const int numChannels = setup_->numSectors(); + hisChannel_ = dir.make("His Channel Occupancy", ";", maxOcc, -.5, maxOcc - .5); + profChannel_ = dir.make("Prof Channel Occupancy", ";", numChannels, -.5, numChannels - .5); + } + + void AnalyzerGP::analyze(const Event& iEvent, const EventSetup& iSetup) { + // read in gp products + Handle handleAccepted; + iEvent.getByToken(edGetTokenAccepted_, handleAccepted); + Handle handleLost; + iEvent.getByToken(edGetTokenLost_, handleLost); + // read in MCTruth + const StubAssociation* stubAssociation = nullptr; + if (useMCTruth_) { + Handle handleAss; + iEvent.getByToken(edGetTokenAss_, handleAss); + stubAssociation = handleAss.product(); + prof_->Fill(4, stubAssociation->numTPs()); + } + // analyze gp products and find still reconstrucable TrackingParticles + set setTPPtr; + for (int region = 0; region < setup_->numRegions(); region++) { + int nStubs(0); + int nLost(0); + map> mapTPsTTStubs; + for (int channel = 0; channel < setup_->numSectors(); channel++) { + const int index = region * setup_->numSectors() + channel; + const StreamStub& accepted = handleAccepted->at(index); + hisChannel_->Fill(accepted.size()); + profChannel_->Fill(channel, accepted.size()); + for (const FrameStub& frame : accepted) { + if (frame.first.isNull()) + continue; + nStubs++; + if (!useMCTruth_) + continue; + const vector& tpPtrs = stubAssociation->findTrackingParticlePtrs(frame.first); + for (const TPPtr& tpPtr : tpPtrs) { + auto it = mapTPsTTStubs.find(tpPtr); + if (it == mapTPsTTStubs.end()) { + it = mapTPsTTStubs.emplace(tpPtr, vector()).first; + it->second.reserve(stubAssociation->findTTStubRefs(tpPtr).size()); + } + it->second.push_back(frame.first); + } + } + nLost += handleLost->at(index).size(); + } + for (const auto& p : mapTPsTTStubs) + if (setup_->reconstructable(p.second)) + setTPPtr.insert(p.first); + prof_->Fill(1, nStubs); + prof_->Fill(2, nLost); + } + prof_->Fill(3, setTPPtr.size()); + nEvents_++; + } + + void AnalyzerGP::endJob() { + if (nEvents_ == 0) + return; + // printout GP summary + const double numStubs = prof_->GetBinContent(1); + const double numStubsLost = prof_->GetBinContent(2); + const double errStubs = prof_->GetBinError(1); + const double errStubsLost = prof_->GetBinError(2); + const double numTPs = prof_->GetBinContent(3); + const double totalTPs = prof_->GetBinContent(4); + const double eff = numTPs / totalTPs; + const double errEff = sqrt(eff * (1. - eff) / totalTPs / nEvents_); + const vector nums = {numStubs, numStubsLost}; + const vector errs = {errStubs, errStubsLost}; + const int wNums = ceil(log10(*max_element(nums.begin(), nums.end()))) + 5; + const int wErrs = ceil(log10(*max_element(errs.begin(), errs.end()))) + 5; + log_ << " GP SUMMARY " << endl; + log_ << "number of stubs per TFP = " << setw(wNums) << numStubs << " +- " << setw(wErrs) << errStubs << endl; + log_ << "number of lost stubs per TFP = " << setw(wNums) << numStubsLost << " +- " << setw(wErrs) << errStubsLost + << endl; + log_ << " max tracking efficiency = " << setw(wNums) << eff << " +- " << setw(wErrs) << errEff << endl; + log_ << "============================================================="; + LogPrint("L1Trigger/TrackerTFP") << log_.str(); + } + +} // namespace trackerTFP + +DEFINE_FWK_MODULE(trackerTFP::AnalyzerGP); \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/test/AnalyzerHT.cc b/L1Trigger/TrackerTFP/test/AnalyzerHT.cc new file mode 100644 index 0000000000000..8e6aec346474a --- /dev/null +++ b/L1Trigger/TrackerTFP/test/AnalyzerHT.cc @@ -0,0 +1,278 @@ +#include "FWCore/Framework/interface/one/EDAnalyzer.h" +#include "FWCore/Framework/interface/Run.h" +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/EventSetup.h" +#include "FWCore/Framework/interface/MakerMacros.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/ServiceRegistry/interface/Service.h" +#include "FWCore/MessageLogger/interface/MessageLogger.h" +#include "FWCore/Utilities/interface/EDGetToken.h" +#include "FWCore/Utilities/interface/InputTag.h" +#include "FWCore/Utilities/interface/Exception.h" +#include "CommonTools/UtilAlgos/interface/TFileService.h" +#include "DataFormats/Common/interface/Handle.h" + +#include "SimTracker/TrackTriggerAssociation/interface/StubAssociation.h" +#include "L1Trigger/TrackTrigger/interface/Setup.h" +#include "L1Trigger/TrackerTFP/interface/DataFormats.h" + +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace edm; +using namespace tt; + +namespace trackerTFP { + + /*! \class trackerTFP::AnalyzerHT + * \brief Class to analyze hardware like structured TTStub Collection generated by Geometric Processor + * \author Thomas Schuh + * \date 2020, Apr + */ + class AnalyzerHT : public one::EDAnalyzer { + public: + AnalyzerHT(const ParameterSet& iConfig); + void beginJob() override {} + void beginRun(const Run& iEvent, const EventSetup& iSetup) override; + void analyze(const Event& iEvent, const EventSetup& iSetup) override; + void endRun(const Run& iEvent, const EventSetup& iSetup) override {} + void endJob() override; + + private: + // + void formTracks(const StreamStub& stream, vector>& tracks, int qOverPt) const; + // + void associate(const vector>& tracks, const StubAssociation* ass, set& tps, int& sum) const; + + // ED input token of stubs + EDGetTokenT edGetTokenAccepted_; + // ED input token of lost stubs + EDGetTokenT edGetTokenLost_; + // ED input token of TTStubRef to TPPtr association for tracking efficiency + EDGetTokenT edGetTokenSelection_; + // ED input token of TTStubRef to recontructable TPPtr association + EDGetTokenT edGetTokenReconstructable_; + // Setup token + ESGetToken esGetTokenSetup_; + // DataFormats token + ESGetToken esGetTokenDataFormats_; + // stores, calculates and provides run-time constants + const Setup* setup_; + // helper class to extract structured data from tt::Frames + const DataFormats* dataFormats_; + // enables analyze of TPs + bool useMCTruth_; + // + int nEvents_; + + // Histograms + + TProfile* prof_; + TProfile* profChannel_; + TH1F* hisChannel_; + + // printout + stringstream log_; + }; + + AnalyzerHT::AnalyzerHT(const ParameterSet& iConfig) + : useMCTruth_(iConfig.getParameter("UseMCTruth")), nEvents_(0) { + usesResource("TFileService"); + // book in- and output ED products + const string& label = iConfig.getParameter("LabelHT"); + const string& branchAccepted = iConfig.getParameter("BranchAcceptedStubs"); + const string& branchLost = iConfig.getParameter("BranchLostStubs"); + edGetTokenAccepted_ = consumes(InputTag(label, branchAccepted)); + edGetTokenLost_ = consumes(InputTag(label, branchLost)); + if (useMCTruth_) { + const auto& inputTagSelecttion = iConfig.getParameter("InputTagSelection"); + const auto& inputTagReconstructable = iConfig.getParameter("InputTagReconstructable"); + edGetTokenSelection_ = consumes(inputTagSelecttion); + edGetTokenReconstructable_ = consumes(inputTagReconstructable); + } + // book ES products + esGetTokenSetup_ = esConsumes(); + esGetTokenDataFormats_ = esConsumes(); + // initial ES products + setup_ = nullptr; + dataFormats_ = nullptr; + // log config + log_.setf(ios::fixed, ios::floatfield); + log_.precision(4); + } + + void AnalyzerHT::beginRun(const Run& iEvent, const EventSetup& iSetup) { + // helper class to store configurations + setup_ = &iSetup.getData(esGetTokenSetup_); + // helper class to extract structured data from tt::Frames + dataFormats_ = &iSetup.getData(esGetTokenDataFormats_); + // book histograms + Service fs; + TFileDirectory dir; + dir = fs->mkdir("HT"); + prof_ = dir.make("Counts", ";", 9, 0.5, 9.5); + prof_->GetXaxis()->SetBinLabel(1, "Stubs"); + prof_->GetXaxis()->SetBinLabel(2, "Tracks"); + prof_->GetXaxis()->SetBinLabel(3, "Lost Tracks"); + prof_->GetXaxis()->SetBinLabel(4, "Matched Tracks"); + prof_->GetXaxis()->SetBinLabel(5, "All Tracks"); + prof_->GetXaxis()->SetBinLabel(6, "Found TPs"); + prof_->GetXaxis()->SetBinLabel(7, "Found selected TPs"); + prof_->GetXaxis()->SetBinLabel(8, "Lost TPs"); + prof_->GetXaxis()->SetBinLabel(9, "All TPs"); + // binInv2R occupancy + constexpr int maxOcc = 180; + const int numChannel = dataFormats_->numChannel(Process::ht); + hisChannel_ = dir.make("His binInv2R Occupancy", ";", maxOcc, -.5, maxOcc - .5); + profChannel_ = dir.make("Prof binInv2R Occupancy", ";", numChannel, -.5, numChannel - .5); + } + + void AnalyzerHT::analyze(const Event& iEvent, const EventSetup& iSetup) { + // read in ht products + Handle handleAccepted; + iEvent.getByToken(edGetTokenAccepted_, handleAccepted); + Handle handleLost; + iEvent.getByToken(edGetTokenLost_, handleLost); + // read in MCTruth + const StubAssociation* selection = nullptr; + const StubAssociation* reconstructable = nullptr; + if (useMCTruth_) { + Handle handleSelection; + iEvent.getByToken(edGetTokenSelection_, handleSelection); + selection = handleSelection.product(); + prof_->Fill(9, selection->numTPs()); + Handle handleReconstructable; + iEvent.getByToken(edGetTokenReconstructable_, handleReconstructable); + reconstructable = handleReconstructable.product(); + } + // analyze ht products and associate found tracks with reconstrucable TrackingParticles + set tpPtrs; + set tpPtrsSelection; + set tpPtrsLost; + int allMatched(0); + int allTracks(0); + for (int region = 0; region < setup_->numRegions(); region++) { + int nStubs(0); + int nTracks(0); + int nLost(0); + for (int channel = 0; channel < dataFormats_->numChannel(Process::ht); channel++) { + const int inv2R = dataFormats_->format(Variable::inv2R, Process::ht).toSigned(channel); + const int index = region * dataFormats_->numChannel(Process::ht) + channel; + const StreamStub& accepted = handleAccepted->at(index); + hisChannel_->Fill(accepted.size()); + profChannel_->Fill(channel, accepted.size()); + nStubs += accepted.size(); + vector> tracks; + vector> lost; + formTracks(accepted, tracks, inv2R); + formTracks(handleLost->at(index), lost, inv2R); + nTracks += tracks.size(); + allTracks += tracks.size(); + nLost += lost.size(); + if (!useMCTruth_) + continue; + int tmp(0); + associate(tracks, selection, tpPtrsSelection, tmp); + associate(lost, selection, tpPtrsLost, tmp); + associate(tracks, reconstructable, tpPtrs, allMatched); + } + prof_->Fill(1, nStubs); + prof_->Fill(2, nTracks); + prof_->Fill(3, nLost); + } + vector recovered; + recovered.reserve(tpPtrsLost.size()); + set_intersection(tpPtrsLost.begin(), tpPtrsLost.end(), tpPtrs.begin(), tpPtrs.end(), back_inserter(recovered)); + for (const TPPtr& tpPtr : recovered) + tpPtrsLost.erase(tpPtr); + prof_->Fill(4, allMatched); + prof_->Fill(5, allTracks); + prof_->Fill(6, tpPtrs.size()); + prof_->Fill(7, tpPtrsSelection.size()); + prof_->Fill(8, tpPtrsLost.size()); + nEvents_++; + } + + void AnalyzerHT::endJob() { + if (nEvents_ == 0) + return; + // printout HT summary + const double totalTPs = prof_->GetBinContent(9); + const double numStubs = prof_->GetBinContent(1); + const double numTracks = prof_->GetBinContent(2); + const double numTracksLost = prof_->GetBinContent(3); + const double totalTracks = prof_->GetBinContent(5); + const double numTracksMatched = prof_->GetBinContent(4); + const double numTPsAll = prof_->GetBinContent(6); + const double numTPsEff = prof_->GetBinContent(7); + const double numTPsLost = prof_->GetBinContent(8); + const double errStubs = prof_->GetBinError(1); + const double errTracks = prof_->GetBinError(2); + const double errTracksLost = prof_->GetBinError(3); + const double fracFake = (totalTracks - numTracksMatched) / totalTracks; + const double fracDup = (numTracksMatched - numTPsAll) / totalTracks; + const double eff = numTPsEff / totalTPs; + const double errEff = sqrt(eff * (1. - eff) / totalTPs / nEvents_); + const double effLoss = numTPsLost / totalTPs; + const double errEffLoss = sqrt(effLoss * (1. - effLoss) / totalTPs / nEvents_); + const vector nums = {numStubs, numTracks, numTracksLost}; + const vector errs = {errStubs, errTracks, errTracksLost}; + const int wNums = ceil(log10(*max_element(nums.begin(), nums.end()))) + 5; + const int wErrs = ceil(log10(*max_element(errs.begin(), errs.end()))) + 5; + log_ << " HT SUMMARY " << endl; + log_ << "number of stubs per TFP = " << setw(wNums) << numStubs << " +- " << setw(wErrs) << errStubs << endl; + log_ << "number of tracks per TFP = " << setw(wNums) << numTracks << " +- " << setw(wErrs) << errTracks + << endl; + log_ << "number of lost tracks per TFP = " << setw(wNums) << numTracksLost << " +- " << setw(wErrs) << errTracksLost + << endl; + log_ << " max tracking efficiency = " << setw(wNums) << eff << " +- " << setw(wErrs) << errEff << endl; + log_ << " lost tracking efficiency = " << setw(wNums) << effLoss << " +- " << setw(wErrs) << errEffLoss << endl; + log_ << " fake rate = " << setw(wNums) << fracFake << endl; + log_ << " duplicate rate = " << setw(wNums) << fracDup << endl; + log_ << "============================================================="; + LogPrint("L1Trigger/TrackerTFP") << log_.str(); + } + + // + void AnalyzerHT::formTracks(const StreamStub& stream, vector>& tracks, int inv2R) const { + vector stubs; + stubs.reserve(stream.size()); + for (const FrameStub& frame : stream) + stubs.emplace_back(frame, dataFormats_, inv2R); + for (auto it = stubs.begin(); it != stubs.end();) { + const auto start = it; + const int id = it->trackId(); + auto different = [id](const StubHT& stub) { return id != stub.trackId(); }; + it = find_if(it, stubs.end(), different); + vector ttStubRefs; + ttStubRefs.reserve(distance(start, it)); + transform(start, it, back_inserter(ttStubRefs), [](const StubHT& stub) { return stub.ttStubRef(); }); + tracks.push_back(ttStubRefs); + } + } + + // + void AnalyzerHT::associate(const vector>& tracks, + const StubAssociation* ass, + set& tps, + int& sum) const { + for (const vector& ttStubRefs : tracks) { + const vector& tpPtrs = ass->associate(ttStubRefs); + if (tpPtrs.empty()) + continue; + sum++; + copy(tpPtrs.begin(), tpPtrs.end(), inserter(tps, tps.begin())); + } + } + +} // namespace trackerTFP + +DEFINE_FWK_MODULE(trackerTFP::AnalyzerHT); \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/test/AnalyzerKF.cc b/L1Trigger/TrackerTFP/test/AnalyzerKF.cc new file mode 100644 index 0000000000000..ace5f917d4631 --- /dev/null +++ b/L1Trigger/TrackerTFP/test/AnalyzerKF.cc @@ -0,0 +1,394 @@ +#include "FWCore/Framework/interface/one/EDAnalyzer.h" +#include "FWCore/Framework/interface/Run.h" +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/EventSetup.h" +#include "FWCore/Framework/interface/MakerMacros.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/ServiceRegistry/interface/Service.h" +#include "FWCore/MessageLogger/interface/MessageLogger.h" +#include "FWCore/Utilities/interface/EDGetToken.h" +#include "FWCore/Utilities/interface/InputTag.h" +#include "FWCore/Utilities/interface/Exception.h" +#include "CommonTools/UtilAlgos/interface/TFileService.h" +#include "DataFormats/Common/interface/Handle.h" + +#include "SimTracker/TrackTriggerAssociation/interface/StubAssociation.h" +#include "L1Trigger/TrackTrigger/interface/Setup.h" +#include "L1Trigger/TrackerTFP/interface/DataFormats.h" +#include "L1Trigger/TrackerTFP/interface/LayerEncoding.h" +#include "L1Trigger/TrackerTFP/interface/KalmanFilterFormats.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace edm; +using namespace tt; + +namespace trackerTFP { + + /*! \class trackerTFP::AnalyzerKF + * \brief Class to analyze hardware like structured TTTrack Collection generated by Kalman Filter + * \author Thomas Schuh + * \date 2020, Sep + */ + class AnalyzerKF : public one::EDAnalyzer { + public: + AnalyzerKF(const ParameterSet& iConfig); + void beginJob() override {} + void beginRun(const Run& iEvent, const EventSetup& iSetup) override; + void analyze(const Event& iEvent, const EventSetup& iSetup) override; + void endRun(const Run& iEvent, const EventSetup& iSetup) override {} + void endJob() override; + + private: + // + void associate(const TTTracks& ttTracks, + const StubAssociation* ass, + set& tps, + int& sum, + const vector& his, + TProfile* prof) const; + + // ED input token of accepted Tracks + EDGetTokenT edGetTokenAcceptedStubs_; + // ED input token of accepted Stubs + EDGetTokenT edGetTokenAcceptedTracks_; + // ED input token of lost Stubs + EDGetTokenT edGetTokenLostStubs_; + // ED input token of lost Tracks + EDGetTokenT edGetTokenLostTracks_; + // ED input token for number of accepted States + EDGetTokenT edGetTokenNumAcceptedStates_; + // ED input token for number of lost States + EDGetTokenT edGetTokenNumLostStates_; + // ED input token of TTStubRef to TPPtr association for tracking efficiency + EDGetTokenT edGetTokenSelection_; + // ED input token of TTStubRef to recontructable TPPtr association + EDGetTokenT edGetTokenReconstructable_; + // Setup token + ESGetToken esGetTokenSetup_; + // DataFormats token + ESGetToken esGetTokenDataFormats_; + // LayerEncoding token + ESGetToken esGetTokenLayerEncoding_; + // stores, calculates and provides run-time constants + const Setup* setup_; + // + const DataFormats* dataFormats_; + // + const LayerEncoding* layerEncoding_; + // enables analyze of TPs + bool useMCTruth_; + // + int nEvents_; + + // Histograms + + TProfile* prof_; + TProfile* profChannel_; + TH1F* hisChannel_; + vector hisRes_; + TProfile* profResZ0_; + TH1F* hisEffEta_; + TH1F* hisEffEtaTotal_; + TEfficiency* effEta_; + TH1F* hisEffInv2R_; + TH1F* hisEffInv2RTotal_; + TEfficiency* effInv2R_; + TH1F* hisChi2_; + TH1F* hisPhi_; + + // printout + stringstream log_; + }; + + AnalyzerKF::AnalyzerKF(const ParameterSet& iConfig) + : useMCTruth_(iConfig.getParameter("UseMCTruth")), nEvents_(0), hisRes_(4) { + usesResource("TFileService"); + // book in- and output ED products + const string& label = iConfig.getParameter("LabelKF"); + const string& branchAcceptedStubs = iConfig.getParameter("BranchAcceptedStubs"); + const string& branchAcceptedTracks = iConfig.getParameter("BranchAcceptedTracks"); + const string& branchLostStubs = iConfig.getParameter("BranchLostStubs"); + const string& branchLostTracks = iConfig.getParameter("BranchLostTracks"); + edGetTokenAcceptedStubs_ = consumes(InputTag(label, branchAcceptedStubs)); + edGetTokenAcceptedTracks_ = consumes(InputTag(label, branchAcceptedTracks)); + edGetTokenLostStubs_ = consumes(InputTag(label, branchLostStubs)); + edGetTokenLostTracks_ = consumes(InputTag(label, branchLostTracks)); + edGetTokenNumAcceptedStates_ = consumes(InputTag(label, branchAcceptedTracks)); + ; + edGetTokenNumLostStates_ = consumes(InputTag(label, branchLostTracks)); + ; + if (useMCTruth_) { + const auto& inputTagSelecttion = iConfig.getParameter("InputTagSelection"); + const auto& inputTagReconstructable = iConfig.getParameter("InputTagReconstructable"); + edGetTokenSelection_ = consumes(inputTagSelecttion); + edGetTokenReconstructable_ = consumes(inputTagReconstructable); + } + // book ES products + esGetTokenSetup_ = esConsumes(); + esGetTokenDataFormats_ = esConsumes(); + esGetTokenLayerEncoding_ = esConsumes(); + // initial ES products + setup_ = nullptr; + dataFormats_ = nullptr; + layerEncoding_ = nullptr; + // log config + log_.setf(ios::fixed, ios::floatfield); + log_.precision(4); + } + + void AnalyzerKF::beginRun(const Run& iEvent, const EventSetup& iSetup) { + // helper class to store configurations + setup_ = &iSetup.getData(esGetTokenSetup_); + dataFormats_ = &iSetup.getData(esGetTokenDataFormats_); + layerEncoding_ = &iSetup.getData(esGetTokenLayerEncoding_); + // book histograms + Service fs; + TFileDirectory dir; + dir = fs->mkdir("KF"); + prof_ = dir.make("Counts", ";", 11, 0.5, 11.5); + prof_->GetXaxis()->SetBinLabel(1, "Stubs"); + prof_->GetXaxis()->SetBinLabel(2, "Tracks"); + prof_->GetXaxis()->SetBinLabel(3, "Lost Tracks"); + prof_->GetXaxis()->SetBinLabel(4, "Matched Tracks"); + prof_->GetXaxis()->SetBinLabel(5, "All Tracks"); + prof_->GetXaxis()->SetBinLabel(6, "Found TPs"); + prof_->GetXaxis()->SetBinLabel(7, "Found selected TPs"); + prof_->GetXaxis()->SetBinLabel(8, "Lost TPs"); + prof_->GetXaxis()->SetBinLabel(9, "All TPs"); + prof_->GetXaxis()->SetBinLabel(10, "states"); + prof_->GetXaxis()->SetBinLabel(11, "lost states"); + // channel occupancy + constexpr int maxOcc = 180; + const int numChannels = dataFormats_->numChannel(Process::kf); + hisChannel_ = dir.make("His Channel Occupancy", ";", maxOcc, -.5, maxOcc - .5); + profChannel_ = dir.make("Prof Channel Occupancy", ";", numChannels, -.5, numChannels - .5); + // resoultions + static const vector names = {"phiT", "inv2R", "zT", "cot"}; + static const vector ranges = {.01, .1, 5, .1}; + for (int i = 0; i < 4; i++) { + const double range = ranges[i]; + hisRes_[i] = dir.make(("HisRes" + names[i]).c_str(), ";", 100, -range, range); + } + profResZ0_ = dir.make("ProfResZ0", ";", 32, 0, 2.5); + // Efficiencies + hisEffEtaTotal_ = dir.make("HisTPEtaTotal", ";", 128, -2.5, 2.5); + hisEffEta_ = dir.make("HisTPEta", ";", 128, -2.5, 2.5); + effEta_ = dir.make("EffEta", ";", 128, -2.5, 2.5); + const double rangeInv2R = dataFormats_->format(Variable::inv2R, Process::dr).range(); + hisEffInv2R_ = dir.make("HisTPInv2R", ";", 32, -rangeInv2R / 2., rangeInv2R / 2.); + hisEffInv2RTotal_ = dir.make("HisTPInv2RTotal", ";", 32, -rangeInv2R / 2., rangeInv2R / 2.); + effInv2R_ = dir.make("EffInv2R", ";", 32, -rangeInv2R / 2., rangeInv2R / 2.); + // chi2 + hisChi2_ = dir.make("HisChi2", ";", 100, -.5, 99.5); + const double rangePhi = dataFormats_->format(Variable::phi0, Process::dr).range(); + hisPhi_ = dir.make("HisPhi", ";", 100, -rangePhi, rangePhi); + } + + void AnalyzerKF::analyze(const Event& iEvent, const EventSetup& iSetup) { + auto fill = [this](const TPPtr& tpPtr, TH1F* hisEta, TH1F* hisInv2R) { + hisEta->Fill(tpPtr->eta()); + hisInv2R->Fill(tpPtr->charge() / tpPtr->pt() * setup_->invPtToDphi()); + }; + // read in kf products + Handle handleAcceptedStubs; + iEvent.getByToken(edGetTokenAcceptedStubs_, handleAcceptedStubs); + const StreamsStub& acceptedStubs = *handleAcceptedStubs; + Handle handleAcceptedTracks; + iEvent.getByToken(edGetTokenAcceptedTracks_, handleAcceptedTracks); + Handle handleLostStubs; + iEvent.getByToken(edGetTokenLostStubs_, handleLostStubs); + const StreamsStub& lostStubs = *handleLostStubs; + Handle handleLostTracks; + iEvent.getByToken(edGetTokenLostTracks_, handleLostTracks); + Handle handleNumAcceptedStates; + iEvent.getByToken(edGetTokenNumAcceptedStates_, handleNumAcceptedStates); + Handle handleNumLostStates; + iEvent.getByToken(edGetTokenNumLostStates_, handleNumLostStates); + // read in MCTruth + const StubAssociation* selection = nullptr; + const StubAssociation* reconstructable = nullptr; + if (useMCTruth_) { + Handle handleSelection; + iEvent.getByToken(edGetTokenSelection_, handleSelection); + selection = handleSelection.product(); + prof_->Fill(9, selection->numTPs()); + Handle handleReconstructable; + iEvent.getByToken(edGetTokenReconstructable_, handleReconstructable); + reconstructable = handleReconstructable.product(); + for (const auto& p : selection->getTrackingParticleToTTStubsMap()) + fill(p.first, hisEffEtaTotal_, hisEffInv2RTotal_); + } + // analyze kf products and associate found tracks with reconstrucable TrackingParticles + set tpPtrs; + set tpPtrsSelection; + set tpPtrsLost; + int allMatched(0); + int allTracks(0); + auto consume = [this](const StreamTrack& tracks, const StreamsStub& streams, int channel, TTTracks& ttTracks) { + const int offset = channel * setup_->numLayers(); + int pos(0); + for (const FrameTrack& frameTrack : tracks) { + vector stubs; + stubs.reserve(setup_->numLayers()); + for (int layer = 0; layer < setup_->numLayers(); layer++) { + const FrameStub& frameStub = streams[offset + layer][pos]; + if (frameStub.first.isNonnull()) + stubs.emplace_back(frameStub, dataFormats_, layer); + } + TrackKF track(frameTrack, dataFormats_); + ttTracks.emplace_back(track.ttTrack(stubs)); + pos++; + } + }; + for (int region = 0; region < setup_->numRegions(); region++) { + int nStubsRegion(0); + int nTracksRegion(0); + int nLostRegion(0); + for (int channel = 0; channel < dataFormats_->numChannel(Process::kf); channel++) { + const int index = region * dataFormats_->numChannel(Process::kf) + channel; + const StreamTrack& accepted = handleAcceptedTracks->at(index); + const StreamTrack& lost = handleLostTracks->at(index); + hisChannel_->Fill(accepted.size()); + profChannel_->Fill(channel, accepted.size()); + TTTracks tracks; + const int nTracks = accumulate(accepted.begin(), accepted.end(), 0, [](int& sum, const FrameTrack& frame) { + return sum += frame.first.isNonnull() ? 1 : 0; + }); + nTracksRegion += nTracks; + tracks.reserve(nTracks); + consume(accepted, acceptedStubs, index, tracks); + for (const TTTrack& ttTrack : tracks) + hisPhi_->Fill(ttTrack.momentum().phi()); + nStubsRegion += accumulate(tracks.begin(), tracks.end(), 0, [](int& sum, const auto& ttTrack) { + return sum += (int)ttTrack.getStubRefs().size(); + }); + TTTracks tracksLost; + const int nLost = accumulate(lost.begin(), lost.end(), 0, [](int& sum, const FrameTrack& frame) { + return sum += frame.first.isNonnull() ? 1 : 0; + }); + nLostRegion += nLost; + tracksLost.reserve(nLost); + consume(lost, lostStubs, index, tracksLost); + allTracks += nTracks; + if (!useMCTruth_) + continue; + int tmp(0); + associate(tracks, selection, tpPtrsSelection, tmp, hisRes_, profResZ0_); + associate(tracksLost, selection, tpPtrsLost, tmp, vector(), nullptr); + associate(tracks, reconstructable, tpPtrs, allMatched, vector(), nullptr); + } + prof_->Fill(1, nStubsRegion); + prof_->Fill(2, nTracksRegion); + prof_->Fill(3, nLostRegion); + } + for (const TPPtr& tpPtr : tpPtrsSelection) + fill(tpPtr, hisEffEta_, hisEffInv2R_); + deque tpPtrsRealLost; + set_difference(tpPtrsLost.begin(), tpPtrsLost.end(), tpPtrs.begin(), tpPtrs.end(), back_inserter(tpPtrsRealLost)); + prof_->Fill(4, allMatched); + prof_->Fill(5, allTracks); + prof_->Fill(6, tpPtrs.size()); + prof_->Fill(7, tpPtrsSelection.size()); + prof_->Fill(8, tpPtrsRealLost.size()); + prof_->Fill(10, *handleNumAcceptedStates); + prof_->Fill(11, *handleNumLostStates); + nEvents_++; + } + + void AnalyzerKF::endJob() { + if (nEvents_ == 0) + return; + // effi + effEta_->SetPassedHistogram(*hisEffEta_, "f"); + effEta_->SetTotalHistogram(*hisEffEtaTotal_, "f"); + effInv2R_->SetPassedHistogram(*hisEffInv2R_, "f"); + effInv2R_->SetTotalHistogram(*hisEffInv2RTotal_, "f"); + // printout SF summary + const double totalTPs = prof_->GetBinContent(9); + const double numStubs = prof_->GetBinContent(1); + const double numTracks = prof_->GetBinContent(2); + const double numTracksLost = prof_->GetBinContent(3); + const double totalTracks = prof_->GetBinContent(5); + const double numTracksMatched = prof_->GetBinContent(4); + const double numTPsAll = prof_->GetBinContent(6); + const double numTPsEff = prof_->GetBinContent(7); + const double numTPsLost = prof_->GetBinContent(8); + const double errStubs = prof_->GetBinError(1); + const double errTracks = prof_->GetBinError(2); + const double errTracksLost = prof_->GetBinError(3); + const double fracFake = (totalTracks - numTracksMatched) / totalTracks; + const double fracDup = (numTracksMatched - numTPsAll) / totalTracks; + const double eff = numTPsEff / totalTPs; + const double errEff = sqrt(eff * (1. - eff) / totalTPs / nEvents_); + const double effLoss = numTPsLost / totalTPs; + const double errEffLoss = sqrt(effLoss * (1. - effLoss) / totalTPs / nEvents_); + const int numStates = prof_->GetBinContent(10); + const int numStatesLost = prof_->GetBinContent(11); + const double fracSatest = numStates / (double)(numStates + numStatesLost); + const vector nums = {numStubs, numTracks, numTracksLost}; + const vector errs = {errStubs, errTracks, errTracksLost}; + const int wNums = ceil(log10(*max_element(nums.begin(), nums.end()))) + 5; + const int wErrs = ceil(log10(*max_element(errs.begin(), errs.end()))) + 5; + log_ << " KF SUMMARY " << endl; + log_ << "number of stubs per TFP = " << setw(wNums) << numStubs << " +- " << setw(wErrs) << errStubs << endl; + log_ << "number of tracks per TFP = " << setw(wNums) << numTracks << " +- " << setw(wErrs) << errTracks + << endl; + log_ << "number of lost tracks per TFP = " << setw(wNums) << numTracksLost << " +- " << setw(wErrs) << errTracksLost + << endl; + log_ << " tracking efficiency = " << setw(wNums) << eff << " +- " << setw(wErrs) << errEff << endl; + log_ << " lost tracking efficiency = " << setw(wNums) << effLoss << " +- " << setw(wErrs) << errEffLoss << endl; + log_ << " fake rate = " << setw(wNums) << fracFake << endl; + log_ << " duplicate rate = " << setw(wNums) << fracDup << endl; + log_ << " state assessment fraction = " << setw(wNums) << fracSatest << endl; + log_ << "============================================================="; + LogPrint("L1Trigger/TrackerTFP") << log_.str(); + } + + // + void AnalyzerKF::associate(const TTTracks& ttTracks, + const StubAssociation* ass, + set& tps, + int& sum, + const vector& his, + TProfile* prof) const { + for (const TTTrack& ttTrack : ttTracks) { + const vector& ttStubRefs = ttTrack.getStubRefs(); + const vector& tpPtrs = ass->associateFinal(ttStubRefs); + if (tpPtrs.empty()) + continue; + sum++; + copy(tpPtrs.begin(), tpPtrs.end(), inserter(tps, tps.begin())); + if (his.empty()) + continue; + for (const TPPtr& tpPtr : tpPtrs) { + const double phi0 = tpPtr->phi(); + const double cot = sinh(tpPtr->eta()); + const double inv2R = setup_->invPtToDphi() * tpPtr->charge() / tpPtr->pt(); + const math::XYZPointD& v = tpPtr->vertex(); + const double z0 = v.z() - cot * (v.x() * cos(phi0) + v.y() * sin(phi0)); + const double dCot = cot - ttTrack.tanL(); + const double dZ0 = z0 - ttTrack.z0(); + const double dInv2R = inv2R - ttTrack.rInv(); + const double dPhi0 = deltaPhi(phi0 - ttTrack.phi()); + const vector ds = {dPhi0, dInv2R, dZ0, dCot}; + for (int i = 0; i < (int)ds.size(); i++) + his[i]->Fill(ds[i]); + prof->Fill(abs(tpPtr->eta()), abs(dZ0)); + } + } + } + +} // namespace trackerTFP + +DEFINE_FWK_MODULE(trackerTFP::AnalyzerKF); \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/test/AnalyzerKFin.cc b/L1Trigger/TrackerTFP/test/AnalyzerKFin.cc new file mode 100644 index 0000000000000..98383ca7c6873 --- /dev/null +++ b/L1Trigger/TrackerTFP/test/AnalyzerKFin.cc @@ -0,0 +1,318 @@ +#include "FWCore/Framework/interface/one/EDAnalyzer.h" +#include "FWCore/Framework/interface/Run.h" +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/EventSetup.h" +#include "FWCore/Framework/interface/MakerMacros.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/ServiceRegistry/interface/Service.h" +#include "FWCore/MessageLogger/interface/MessageLogger.h" +#include "FWCore/Utilities/interface/EDGetToken.h" +#include "FWCore/Utilities/interface/InputTag.h" +#include "FWCore/Utilities/interface/Exception.h" +#include "CommonTools/UtilAlgos/interface/TFileService.h" +#include "DataFormats/Common/interface/Handle.h" + +#include "SimTracker/TrackTriggerAssociation/interface/StubAssociation.h" +#include "L1Trigger/TrackTrigger/interface/Setup.h" +#include "L1Trigger/TrackerTFP/interface/DataFormats.h" + +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace edm; +using namespace trackerTFP; +using namespace tt; + +namespace trackerTFP { + + /*! \class trackerTFP::AnalyzerKFin + * \brief Class to analyze hardware like structured TTStub Collection generated by Seed Filter + * \author Thomas Schuh + * \date 2020, April + */ + class AnalyzerKFin : public one::EDAnalyzer { + public: + AnalyzerKFin(const ParameterSet& iConfig); + void beginJob() override {} + void beginRun(const Run& iEvent, const EventSetup& iSetup) override; + void analyze(const Event& iEvent, const EventSetup& iSetup) override; + void endRun(const Run& iEvent, const EventSetup& iSetup) override {} + void endJob() override; + + private: + // + void formTracks(const StreamsTrack& streamsTrack, + const StreamsStub& streamsStubs, + vector>& tracks, + int channel) const; + // + void associate(const vector>& tracks, const StubAssociation* ass, set& tps, int& sum) const; + + // ED input token of stubs + EDGetTokenT edGetTokenAcceptedStubs_; + // ED input token of tracks + EDGetTokenT edGetTokenAcceptedTracks_; + // ED input token of lost stubs + EDGetTokenT edGetTokenLostStubs_; + // ED input token of lost tracks + EDGetTokenT edGetTokenLostTracks_; + // ED input token of TTStubRef to TPPtr association for tracking efficiency + EDGetTokenT edGetTokenSelection_; + // ED input token of TTStubRef to recontructable TPPtr association + EDGetTokenT edGetTokenReconstructable_; + // Setup token + ESGetToken esGetTokenSetup_; + // DataFormats token + ESGetToken esGetTokenDataFormats_; + // stores, calculates and provides run-time constants + const Setup* setup_; + // helper class to extract structured data from tt::Frames + const DataFormats* dataFormats_; + // enables analyze of TPs + bool useMCTruth_; + // + int nEvents_; + + // Histograms + + TProfile* prof_; + TProfile* profChannel_; + TH1F* hisChannel_; + + // printout + stringstream log_; + }; + + AnalyzerKFin::AnalyzerKFin(const ParameterSet& iConfig) + : useMCTruth_(iConfig.getParameter("UseMCTruth")), nEvents_(0) { + usesResource("TFileService"); + // book in- and output ED products + const string& label = iConfig.getParameter("LabelKFin"); + const string& branchAcceptedStubs = iConfig.getParameter("BranchAcceptedStubs"); + const string& branchAcceptedTracks = iConfig.getParameter("BranchAcceptedTracks"); + const string& branchLostStubs = iConfig.getParameter("BranchLostStubs"); + const string& branchLostTracks = iConfig.getParameter("BranchLostTracks"); + edGetTokenAcceptedStubs_ = consumes(InputTag(label, branchAcceptedStubs)); + edGetTokenAcceptedTracks_ = consumes(InputTag(label, branchAcceptedTracks)); + edGetTokenLostStubs_ = consumes(InputTag(label, branchLostStubs)); + edGetTokenLostTracks_ = consumes(InputTag(label, branchLostTracks)); + if (useMCTruth_) { + const auto& inputTagSelecttion = iConfig.getParameter("InputTagSelection"); + const auto& inputTagReconstructable = iConfig.getParameter("InputTagReconstructable"); + edGetTokenSelection_ = consumes(inputTagSelecttion); + edGetTokenReconstructable_ = consumes(inputTagReconstructable); + } + // book ES products + esGetTokenSetup_ = esConsumes(); + esGetTokenDataFormats_ = esConsumes(); + // initial ES products + setup_ = nullptr; + dataFormats_ = nullptr; + // log config + log_.setf(ios::fixed, ios::floatfield); + log_.precision(4); + } + + void AnalyzerKFin::beginRun(const Run& iEvent, const EventSetup& iSetup) { + // helper class to store configurations + setup_ = &iSetup.getData(esGetTokenSetup_); + // helper class to extract structured data from tt::Frames + dataFormats_ = &iSetup.getData(esGetTokenDataFormats_); + // book histograms + Service fs; + TFileDirectory dir; + dir = fs->mkdir("KFin"); + prof_ = dir.make("Counts", ";", 9, 0.5, 9.5); + prof_->GetXaxis()->SetBinLabel(1, "Stubs"); + prof_->GetXaxis()->SetBinLabel(2, "Tracks"); + prof_->GetXaxis()->SetBinLabel(3, "Lost Tracks"); + prof_->GetXaxis()->SetBinLabel(4, "Matched Tracks"); + prof_->GetXaxis()->SetBinLabel(5, "All Tracks"); + prof_->GetXaxis()->SetBinLabel(6, "Found TPs"); + prof_->GetXaxis()->SetBinLabel(7, "Found selected TPs"); + prof_->GetXaxis()->SetBinLabel(8, "Lost TPs"); + prof_->GetXaxis()->SetBinLabel(9, "All TPs"); + // channel occupancy + constexpr int maxOcc = 180; + const int numChannels = dataFormats_->numChannel(Process::kfin); + hisChannel_ = dir.make("His Channel Occupancy", ";", maxOcc, -.5, maxOcc - .5); + profChannel_ = dir.make("Prof Channel Occupancy", ";", numChannels, -.5, numChannels - .5); + } + + void AnalyzerKFin::analyze(const Event& iEvent, const EventSetup& iSetup) { + // read in ht products + Handle handleAcceptedStubs; + iEvent.getByToken(edGetTokenAcceptedStubs_, handleAcceptedStubs); + const StreamsStub& acceptedStubs = *handleAcceptedStubs; + Handle handleAcceptedTracks; + iEvent.getByToken(edGetTokenAcceptedTracks_, handleAcceptedTracks); + const StreamsTrack& acceptedTracks = *handleAcceptedTracks; + Handle handleLostStubs; + iEvent.getByToken(edGetTokenLostStubs_, handleLostStubs); + const StreamsStub& lostStubs = *handleLostStubs; + Handle handleLostTracks; + iEvent.getByToken(edGetTokenLostTracks_, handleLostTracks); + const StreamsTrack& lostTracks = *handleLostTracks; + // read in MCTruth + const StubAssociation* selection = nullptr; + const StubAssociation* reconstructable = nullptr; + if (useMCTruth_) { + Handle handleSelection; + iEvent.getByToken(edGetTokenSelection_, handleSelection); + selection = handleSelection.product(); + prof_->Fill(9, selection->numTPs()); + Handle handleReconstructable; + iEvent.getByToken(edGetTokenReconstructable_, handleReconstructable); + reconstructable = handleReconstructable.product(); + } + // analyze ht products and associate found tracks with reconstrucable TrackingParticles + set tpPtrs; + set tpPtrsSelection; + set tpPtrsLost; + int allMatched(0); + int allTracks(0); + for (int region = 0; region < setup_->numRegions(); region++) { + const int offset = region * dataFormats_->numChannel(Process::kf); + int nStubs(0); + int nTracks(0); + int nLost(0); + for (int channel = 0; channel < dataFormats_->numChannel(Process::kf); channel++) { + vector> tracks; + formTracks(acceptedTracks, acceptedStubs, tracks, offset + channel); + vector> lost; + formTracks(lostTracks, lostStubs, lost, offset + channel); + nTracks += tracks.size(); + nStubs += accumulate(tracks.begin(), tracks.end(), 0, [](int& sum, const vector& track) { + return sum += (int)track.size(); + }); + nLost += lost.size(); + allTracks += tracks.size(); + if (!useMCTruth_) + continue; + int tmp(0); + associate(tracks, selection, tpPtrsSelection, tmp); + associate(lost, selection, tpPtrsLost, tmp); + associate(tracks, reconstructable, tpPtrs, allMatched); + } + prof_->Fill(1, nStubs); + prof_->Fill(2, nTracks); + prof_->Fill(3, nLost); + } + vector recovered; + recovered.reserve(tpPtrsLost.size()); + set_intersection(tpPtrsLost.begin(), tpPtrsLost.end(), tpPtrs.begin(), tpPtrs.end(), back_inserter(recovered)); + for (const TPPtr& tpPtr : recovered) + tpPtrsLost.erase(tpPtr); + prof_->Fill(4, allMatched); + prof_->Fill(5, allTracks); + prof_->Fill(6, tpPtrs.size()); + prof_->Fill(7, tpPtrsSelection.size()); + prof_->Fill(8, tpPtrsLost.size()); + nEvents_++; + } + + void AnalyzerKFin::endJob() { + if (nEvents_ == 0) + return; + // printout SF summary + const double totalTPs = prof_->GetBinContent(9); + const double numStubs = prof_->GetBinContent(1); + const double numTracks = prof_->GetBinContent(2); + const double numTracksLost = prof_->GetBinContent(3); + const double totalTracks = prof_->GetBinContent(5); + const double numTracksMatched = prof_->GetBinContent(4); + const double numTPsAll = prof_->GetBinContent(6); + const double numTPsEff = prof_->GetBinContent(7); + const double numTPsLost = prof_->GetBinContent(8); + const double errStubs = prof_->GetBinError(1); + const double errTracks = prof_->GetBinError(2); + const double errTracksLost = prof_->GetBinError(3); + const double fracFake = (totalTracks - numTracksMatched) / totalTracks; + const double fracDup = (numTracksMatched - numTPsAll) / totalTracks; + const double eff = numTPsEff / totalTPs; + const double errEff = sqrt(eff * (1. - eff) / totalTPs / nEvents_); + const double effLoss = numTPsLost / totalTPs; + const double errEffLoss = sqrt(effLoss * (1. - effLoss) / totalTPs / nEvents_); + const vector nums = {numStubs, numTracks, numTracksLost}; + const vector errs = {errStubs, errTracks, errTracksLost}; + const int wNums = ceil(log10(*max_element(nums.begin(), nums.end()))) + 5; + const int wErrs = ceil(log10(*max_element(errs.begin(), errs.end()))) + 5; + log_ << " KFin SUMMARY " << endl; + log_ << "number of stubs per TFP = " << setw(wNums) << numStubs << " +- " << setw(wErrs) << errStubs << endl; + log_ << "number of tracks per TFP = " << setw(wNums) << numTracks << " +- " << setw(wErrs) << errTracks + << endl; + log_ << "number of lost tracks per TFP = " << setw(wNums) << numTracksLost << " +- " << setw(wErrs) << errTracksLost + << endl; + log_ << " max tracking efficiency = " << setw(wNums) << eff << " +- " << setw(wErrs) << errEff << endl; + log_ << " lost tracking efficiency = " << setw(wNums) << effLoss << " +- " << setw(wErrs) << errEffLoss << endl; + log_ << " fake rate = " << setw(wNums) << fracFake << endl; + log_ << " duplicate rate = " << setw(wNums) << fracDup << endl; + log_ << "============================================================="; + LogPrint("L1Trigger/TrackerTFP") << log_.str(); + } + + // + void AnalyzerKFin::formTracks(const StreamsTrack& streamsTrack, + const StreamsStub& streamsStubs, + vector>& tracks, + int channel) const { + const int offset = channel * setup_->numLayers(); + const StreamTrack& streamTrack = streamsTrack[channel]; + const int numTracks = accumulate(streamTrack.begin(), streamTrack.end(), 0, [](int& sum, const FrameTrack& frame) { + return sum += (frame.first.isNonnull() ? 1 : 0); + }); + tracks.reserve(numTracks); + for (int frame = 0; frame < (int)streamTrack.size(); frame++) { + const FrameTrack& frameTrack = streamTrack[frame]; + if (frameTrack.first.isNull()) + continue; + const auto end = find_if(next(streamTrack.begin(), frame + 1), streamTrack.end(), [](const FrameTrack& frame) { + return frame.first.isNonnull(); + }); + const int size = distance(next(streamTrack.begin(), frame), end); + int numStubs(0); + for (int layer = 0; layer < setup_->numLayers(); layer++) { + const StreamStub& stream = streamsStubs[offset + layer]; + numStubs += + accumulate(stream.begin() + frame, stream.begin() + frame + size, 0, [](int& sum, const FrameStub& frame) { + return sum += (frame.first.isNonnull() ? 1 : 0); + }); + } + vector stubs; + stubs.reserve(numStubs); + for (int layer = 0; layer < setup_->numLayers(); layer++) { + for (int f = frame; f < frame + size; f++) { + const FrameStub& stub = streamsStubs[offset + layer][f]; + if (stub.first.isNonnull()) + stubs.push_back(stub.first); + } + } + tracks.push_back(stubs); + } + } + + // + void AnalyzerKFin::associate(const vector>& tracks, + const StubAssociation* ass, + set& tps, + int& sum) const { + for (const vector& ttStubRefs : tracks) { + const vector& tpPtrs = ass->associate(ttStubRefs); + if (tpPtrs.empty()) + continue; + sum++; + copy(tpPtrs.begin(), tpPtrs.end(), inserter(tps, tps.begin())); + } + } + +} // namespace trackerTFP + +DEFINE_FWK_MODULE(trackerTFP::AnalyzerKFin); \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/test/AnalyzerMHT.cc b/L1Trigger/TrackerTFP/test/AnalyzerMHT.cc new file mode 100644 index 0000000000000..2ecb8dbe43d7c --- /dev/null +++ b/L1Trigger/TrackerTFP/test/AnalyzerMHT.cc @@ -0,0 +1,296 @@ +#include "FWCore/Framework/interface/one/EDAnalyzer.h" +#include "FWCore/Framework/interface/Run.h" +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/EventSetup.h" +#include "FWCore/Framework/interface/MakerMacros.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/ServiceRegistry/interface/Service.h" +#include "FWCore/MessageLogger/interface/MessageLogger.h" +#include "FWCore/Utilities/interface/EDGetToken.h" +#include "FWCore/Utilities/interface/InputTag.h" +#include "FWCore/Utilities/interface/Exception.h" +#include "CommonTools/UtilAlgos/interface/TFileService.h" +#include "DataFormats/Common/interface/Handle.h" + +#include "SimTracker/TrackTriggerAssociation/interface/StubAssociation.h" +#include "L1Trigger/TrackTrigger/interface/Setup.h" +#include "L1Trigger/TrackerTFP/interface/DataFormats.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace edm; +using namespace tt; + +namespace trackerTFP { + + /*! \class trackerTFP::AnalyzerMHT + * \brief Class to analyze hardware like structured TTStub Collection generated by Mini Hough Transform + * \author Thomas Schuh + * \date 2020, Apr + */ + class AnalyzerMHT : public one::EDAnalyzer { + public: + AnalyzerMHT(const ParameterSet& iConfig); + void beginJob() override {} + void beginRun(const Run& iEvent, const EventSetup& iSetup) override; + void analyze(const Event& iEvent, const EventSetup& iSetup) override; + void endRun(const Run& iEvent, const EventSetup& iSetup) override {} + void endJob() override; + + private: + // + void formTracks(const StreamStub& stream, vector>& tracks) const; + // + void associate(const vector>& tracks, const StubAssociation* ass, set& tps, int& sum) const; + + // ED input token of stubs + EDGetTokenT edGetTokenAccepted_; + // ED input token of lost stubs + EDGetTokenT edGetTokenLost_; + // ED input token of TTStubRef to TPPtr association for tracking efficiency + EDGetTokenT edGetTokenSelection_; + // ED input token of TTStubRef to recontructable TPPtr association + EDGetTokenT edGetTokenReconstructable_; + // Setup token + ESGetToken esGetTokenSetup_; + // DataFormats token + ESGetToken esGetTokenDataFormats_; + // stores, calculates and provides run-time constants + const Setup* setup_; + // helper class to extract structured data from tt::Frames + const DataFormats* dataFormats_; + // enables analyze of TPs + bool useMCTruth_; + // + int nEvents_; + + // Histograms + + TProfile* prof_; + TProfile* profChannel_; + TH1F* hisChannel_; + TH1F* hisEff_; + TH1F* hisEffTotal_; + TEfficiency* eff_; + + // printout + stringstream log_; + }; + + AnalyzerMHT::AnalyzerMHT(const ParameterSet& iConfig) + : useMCTruth_(iConfig.getParameter("UseMCTruth")), nEvents_(0) { + usesResource("TFileService"); + // book in- and output ED products + const string& label = iConfig.getParameter("LabelMHT"); + const string& branchAccepted = iConfig.getParameter("BranchAcceptedStubs"); + const string& branchLost = iConfig.getParameter("BranchLostStubs"); + edGetTokenAccepted_ = consumes(InputTag(label, branchAccepted)); + edGetTokenLost_ = consumes(InputTag(label, branchLost)); + if (useMCTruth_) { + const auto& inputTagSelecttion = iConfig.getParameter("InputTagSelection"); + const auto& inputTagReconstructable = iConfig.getParameter("InputTagReconstructable"); + edGetTokenSelection_ = consumes(inputTagSelecttion); + edGetTokenReconstructable_ = consumes(inputTagReconstructable); + } + // book ES products + esGetTokenSetup_ = esConsumes(); + esGetTokenDataFormats_ = esConsumes(); + // initial ES products + setup_ = nullptr; + dataFormats_ = nullptr; + // log config + log_.setf(ios::fixed, ios::floatfield); + log_.precision(4); + } + + void AnalyzerMHT::beginRun(const Run& iEvent, const EventSetup& iSetup) { + // helper class to store configurations + setup_ = &iSetup.getData(esGetTokenSetup_); + // helper class to extract structured data from tt::Frames + dataFormats_ = &iSetup.getData(esGetTokenDataFormats_); + // book histograms + Service fs; + TFileDirectory dir; + dir = fs->mkdir("MHT"); + prof_ = dir.make("Counts", ";", 9, 0.5, 9.5); + prof_->GetXaxis()->SetBinLabel(1, "Stubs"); + prof_->GetXaxis()->SetBinLabel(2, "Tracks"); + prof_->GetXaxis()->SetBinLabel(3, "Lost Tracks"); + prof_->GetXaxis()->SetBinLabel(4, "Matched Tracks"); + prof_->GetXaxis()->SetBinLabel(5, "All Tracks"); + prof_->GetXaxis()->SetBinLabel(6, "Found TPs"); + prof_->GetXaxis()->SetBinLabel(7, "Found selected TPs"); + prof_->GetXaxis()->SetBinLabel(8, "Lost TPs"); + prof_->GetXaxis()->SetBinLabel(9, "All TPs"); + // channel occupancy + constexpr int maxOcc = 180; + const int numChannels = dataFormats_->numChannel(Process::mht); + hisChannel_ = dir.make("His Channel Occupancy", ";", maxOcc, -.5, maxOcc - .5); + profChannel_ = dir.make("Prof Channel Occupancy", ";", numChannels, -.5, numChannels - .5); + // Efficiencies + hisEffTotal_ = dir.make("HisTPEtaTotal", ";", 128, -2.5, 2.5); + hisEff_ = dir.make("HisTPEta", ";", 128, -2.5, 2.5); + eff_ = dir.make("EffEta", ";", 128, -2.5, 2.5); + } + + void AnalyzerMHT::analyze(const Event& iEvent, const EventSetup& iSetup) { + auto fill = [this](const TPPtr& tpPtr, TH1F* his) { his->Fill(tpPtr->eta()); }; + // read in ht products + Handle handleAccepted; + iEvent.getByToken(edGetTokenAccepted_, handleAccepted); + Handle handleLost; + iEvent.getByToken(edGetTokenLost_, handleLost); + // read in MCTruth + const StubAssociation* selection = nullptr; + const StubAssociation* reconstructable = nullptr; + if (useMCTruth_) { + Handle handleSelection; + iEvent.getByToken(edGetTokenSelection_, handleSelection); + selection = handleSelection.product(); + prof_->Fill(9, selection->numTPs()); + Handle handleReconstructable; + iEvent.getByToken(edGetTokenReconstructable_, handleReconstructable); + reconstructable = handleReconstructable.product(); + for (const auto& p : selection->getTrackingParticleToTTStubsMap()) + fill(p.first, hisEffTotal_); + } + // analyze ht products and associate found tracks with reconstrucable TrackingParticles + set tpPtrs; + set tpPtrsSelection; + set tpPtrsLost; + int allMatched(0); + int allTracks(0); + for (int region = 0; region < setup_->numRegions(); region++) { + int nStubs(0); + int nTracks(0); + int nLost(0); + for (int channel = 0; channel < dataFormats_->numChannel(Process::mht); channel++) { + const int index = region * dataFormats_->numChannel(Process::mht) + channel; + const StreamStub& accepted = handleAccepted->at(index); + hisChannel_->Fill(accepted.size()); + profChannel_->Fill(channel, accepted.size()); + nStubs += accumulate(accepted.begin(), accepted.end(), 0, [](int& sum, const FrameStub& frame) { + return sum += frame.first.isNonnull() ? 1 : 0; + }); + vector> tracks; + vector> lost; + formTracks(accepted, tracks); + formTracks(handleLost->at(index), lost); + nTracks += tracks.size(); + allTracks += tracks.size(); + nLost += lost.size(); + if (!useMCTruth_) + continue; + int tmp(0); + associate(tracks, selection, tpPtrsSelection, tmp); + associate(lost, selection, tpPtrsLost, tmp); + associate(tracks, reconstructable, tpPtrs, allMatched); + } + prof_->Fill(1, nStubs); + prof_->Fill(2, nTracks); + prof_->Fill(3, nLost); + } + for (const TPPtr& tpPtr : tpPtrsSelection) + fill(tpPtr, hisEff_); + vector recovered; + recovered.reserve(tpPtrsLost.size()); + set_intersection(tpPtrsLost.begin(), tpPtrsLost.end(), tpPtrs.begin(), tpPtrs.end(), back_inserter(recovered)); + for (const TPPtr& tpPtr : recovered) + tpPtrsLost.erase(tpPtr); + prof_->Fill(4, allMatched); + prof_->Fill(5, allTracks); + prof_->Fill(6, tpPtrs.size()); + prof_->Fill(7, tpPtrsSelection.size()); + prof_->Fill(8, tpPtrsLost.size()); + nEvents_++; + } + + void AnalyzerMHT::endJob() { + if (nEvents_ == 0) + return; + // effi + eff_->SetPassedHistogram(*hisEff_, "f"); + eff_->SetTotalHistogram(*hisEffTotal_, "f"); + // printout MHT summary + const double totalTPs = prof_->GetBinContent(9); + const double numStubs = prof_->GetBinContent(1); + const double numTracks = prof_->GetBinContent(2); + const double numTracksLost = prof_->GetBinContent(3); + const double totalTracks = prof_->GetBinContent(5); + const double numTracksMatched = prof_->GetBinContent(4); + const double numTPsAll = prof_->GetBinContent(6); + const double numTPsEff = prof_->GetBinContent(7); + const double numTPsLost = prof_->GetBinContent(8); + const double errStubs = prof_->GetBinError(1); + const double errTracks = prof_->GetBinError(2); + const double errTracksLost = prof_->GetBinError(3); + const double fracFake = (totalTracks - numTracksMatched) / totalTracks; + const double fracDup = (numTracksMatched - numTPsAll) / totalTracks; + const double eff = numTPsEff / totalTPs; + const double errEff = sqrt(eff * (1. - eff) / totalTPs / nEvents_); + const double effLoss = numTPsLost / totalTPs; + const double errEffLoss = sqrt(effLoss * (1. - effLoss) / totalTPs / nEvents_); + const vector nums = {numStubs, numTracks, numTracksLost}; + const vector errs = {errStubs, errTracks, errTracksLost}; + const int wNums = ceil(log10(*max_element(nums.begin(), nums.end()))) + 5; + const int wErrs = ceil(log10(*max_element(errs.begin(), errs.end()))) + 5; + log_ << " MHT SUMMARY " << endl; + log_ << "number of stubs per TFP = " << setw(wNums) << numStubs << " +- " << setw(wErrs) << errStubs << endl; + log_ << "number of tracks per TFP = " << setw(wNums) << numTracks << " +- " << setw(wErrs) << errTracks + << endl; + log_ << "number of lost tracks per TFP = " << setw(wNums) << numTracksLost << " +- " << setw(wErrs) << errTracksLost + << endl; + log_ << " max tracking efficiency = " << setw(wNums) << eff << " +- " << setw(wErrs) << errEff << endl; + log_ << " lost tracking efficiency = " << setw(wNums) << effLoss << " +- " << setw(wErrs) << errEffLoss << endl; + log_ << " fake rate = " << setw(wNums) << fracFake << endl; + log_ << " duplicate rate = " << setw(wNums) << fracDup << endl; + log_ << "============================================================="; + LogPrint("L1Trigger/TrackerTFP") << log_.str(); + } + + // + void AnalyzerMHT::formTracks(const StreamStub& stream, vector>& tracks) const { + vector stubs; + stubs.reserve(stream.size()); + for (const FrameStub& frame : stream) + if (frame.first.isNonnull()) + stubs.emplace_back(frame, dataFormats_); + for (auto it = stubs.begin(); it != stubs.end();) { + const auto start = it; + const int id = it->trackId(); + auto different = [id](const StubMHT& stub) { return id != stub.trackId(); }; + it = find_if(it, stubs.end(), different); + vector ttStubRefs; + ttStubRefs.reserve(distance(start, it)); + transform(start, it, back_inserter(ttStubRefs), [](const StubMHT& stub) { return stub.ttStubRef(); }); + tracks.push_back(ttStubRefs); + } + } + + // + void AnalyzerMHT::associate(const vector>& tracks, + const StubAssociation* ass, + set& tps, + int& sum) const { + for (const vector& ttStubRefs : tracks) { + const vector& tpPtrs = ass->associate(ttStubRefs); + if (tpPtrs.empty()) + continue; + sum++; + copy(tpPtrs.begin(), tpPtrs.end(), inserter(tps, tps.begin())); + } + } + +} // namespace trackerTFP + +DEFINE_FWK_MODULE(trackerTFP::AnalyzerMHT); \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/test/AnalyzerTT.cc b/L1Trigger/TrackerTFP/test/AnalyzerTT.cc new file mode 100644 index 0000000000000..07c2558d2587d --- /dev/null +++ b/L1Trigger/TrackerTFP/test/AnalyzerTT.cc @@ -0,0 +1,133 @@ +#include "FWCore/Framework/interface/one/EDAnalyzer.h" +#include "FWCore/Framework/interface/Run.h" +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/EventSetup.h" +#include "FWCore/Framework/interface/MakerMacros.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/Utilities/interface/EDGetToken.h" +#include "FWCore/Utilities/interface/InputTag.h" +#include "FWCore/Utilities/interface/Exception.h" +#include "DataFormats/Common/interface/Handle.h" + +#include "SimTracker/TrackTriggerAssociation/interface/StubAssociation.h" +#include "L1Trigger/TrackTrigger/interface/Setup.h" + +using namespace std; +using namespace edm; +using namespace tt; + +namespace trackerTFP { + + /*! \class trackerTFP::AnalyzerTT + * \brief Class to analyze TTTracks + * \author Thomas Schuh + * \date 2020, Oct + */ + class AnalyzerTT : public one::EDAnalyzer { + public: + AnalyzerTT(const ParameterSet& iConfig); + void beginJob() override {} + void beginRun(const Run& iEvent, const EventSetup& iSetup) override; + void analyze(const Event& iEvent, const EventSetup& iSetup) override; + void endRun(const Run& iEvent, const EventSetup& iSetup) override {} + void endJob() override {} + + private: + // ED input token of tt::TTTrackRefMap + EDGetTokenT edGetTokenTTTrackMap_; + // ED input token of TTStubRef to TPPtr association for tracking efficiency + EDGetTokenT edGetTokenStubAssociation_; + // Setup token + ESGetToken esGetTokenSetup_; + // stores, calculates and provides run-time constants + const Setup* setup_; + }; + + AnalyzerTT::AnalyzerTT(const ParameterSet& iConfig) { + // book in- and output ED products + const auto& label = iConfig.getParameter("LabelAS"); + const auto& branch = iConfig.getParameter("BranchAcceptedTracks"); + const auto& inputTag = iConfig.getParameter("InputTagSelection"); + edGetTokenTTTrackMap_ = consumes(InputTag(label, branch)); + edGetTokenStubAssociation_ = consumes(inputTag); + // book ES products + esGetTokenSetup_ = esConsumes(); + // initial ES products + setup_ = nullptr; + } + + void AnalyzerTT::beginRun(const Run& iEvent, const EventSetup& iSetup) { + // helper class to store configurations + setup_ = &iSetup.getData(esGetTokenSetup_); + } + + void AnalyzerTT::analyze(const Event& iEvent, const EventSetup& iSetup) { + Handle handleTTTrackMap; + iEvent.getByToken(edGetTokenTTTrackMap_, handleTTTrackMap); + Handle handleStubAssociation; + iEvent.getByToken(edGetTokenStubAssociation_, handleStubAssociation); + if (false) + return; + for (const pair& p : *handleTTTrackMap) { + const TTTrackRef& found = p.second; + const TTTrackRef& fitted = p.first; + const vector& ttStubRefsFound = found->getStubRefs(); + const vector& tpPtrsFound = handleStubAssociation->associate(ttStubRefsFound); + if (tpPtrsFound.empty()) + continue; + const vector& ttStubRefsFitted = fitted->getStubRefs(); + const vector& tpPtrsFitted = handleStubAssociation->associate(ttStubRefsFitted); + if (!tpPtrsFitted.empty()) + continue; + const TPPtr& tpPtr = tpPtrsFound.front(); + const double off = (found->phiSector() - .5) * 2. * M_PI / setup_->numRegions() / setup_->numSectorsPhi(); + cout << setprecision(8); + cout << found->phiSector() << " " << found->etaSector() << " " << endl; + cout << "Found" << endl; + for (const TTStubRef& ttStubRef : ttStubRefsFound) { + const GlobalPoint& gp = setup_->stubPos(ttStubRef); + cout << gp.perp() << " " << gp.phi() << " " << gp.z() << " " << setup_->layerId(ttStubRef) << endl; + } + cout << "Fitted" << endl; + for (const TTStubRef& ttStubRef : ttStubRefsFitted) { + const GlobalPoint& gp = setup_->stubPos(ttStubRef); + cout << gp.perp() << " " << gp.phi() << " " << gp.z() << " " << setup_->layerId(ttStubRef) << endl; + } + cout << "TP" << endl; + for (const TTStubRef& ttStubRef : handleStubAssociation->findTTStubRefs(tpPtr)) { + const GlobalPoint& gp = setup_->stubPos(ttStubRef); + cout << gp.perp() << " " << gp.phi() << " " << gp.z() << " " << setup_->layerId(ttStubRef) << endl; + } + cout << found->hitPattern() << " " << found->trackSeedType() << endl; + cout << "m0SF = " + << " " << -found->rInv() << endl; + cout << "c0SF = " + << " " << deltaPhi(found->phi() + found->rInv() * setup_->chosenRofPhi() + off) << endl; + cout << "m1SF = " + << " " << found->tanL() + setup_->sectorCot(found->etaSector()) << endl; + cout << "c1SF = " + << " " << found->z0() - found->tanL() * setup_->chosenRofZ() << endl; + cout << "m0KF = " + << " " << -fitted->rInv() * setup_->invPtToDphi() << endl; + cout << "c0KF = " + << " " << fitted->phi() << endl; + cout << "m1KF = " + << " " << fitted->tanL() << endl; + cout << "c1KF = " + << " " << fitted->z0() << endl; + cout << "m0TP = " + << " " << -tpPtr->charge() / tpPtr->pt() * setup_->invPtToDphi() << endl; + cout << "c0TP = " + << " " << tpPtr->phi() << endl; + cout << "m1TP = " + << " " << sinh(tpPtr->eta()) << endl; + const math::XYZPointD& v = tpPtr->vertex(); + cout << "c1TP = " + << " " << v.z() - sinh(tpPtr->eta()) * (v.x() * cos(tpPtr->phi()) + v.y() * sin(tpPtr->phi())) << endl; + throw cms::Exception("..."); + } + } + +} // namespace trackerTFP + +DEFINE_FWK_MODULE(trackerTFP::AnalyzerTT); \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/test/AnalyzerZHT.cc b/L1Trigger/TrackerTFP/test/AnalyzerZHT.cc new file mode 100644 index 0000000000000..32fe2356badaa --- /dev/null +++ b/L1Trigger/TrackerTFP/test/AnalyzerZHT.cc @@ -0,0 +1,298 @@ +#include "FWCore/Framework/interface/one/EDAnalyzer.h" +#include "FWCore/Framework/interface/Run.h" +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/EventSetup.h" +#include "FWCore/Framework/interface/MakerMacros.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/ServiceRegistry/interface/Service.h" +#include "FWCore/MessageLogger/interface/MessageLogger.h" +#include "FWCore/Utilities/interface/EDGetToken.h" +#include "FWCore/Utilities/interface/InputTag.h" +#include "FWCore/Utilities/interface/Exception.h" +#include "CommonTools/UtilAlgos/interface/TFileService.h" +#include "DataFormats/Common/interface/Handle.h" + +#include "SimTracker/TrackTriggerAssociation/interface/StubAssociation.h" +#include "L1Trigger/TrackTrigger/interface/Setup.h" +#include "L1Trigger/TrackerTFP/interface/DataFormats.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace edm; +using namespace tt; + +namespace trackerTFP { + + /*! \class trackerTFP::AnalyzerZHT + * \brief Class to analyze hardware like structured TTStub Collection generated by Z Hough Transform + * \author Thomas Schuh + * \date 2021, May + */ + class AnalyzerZHT : public one::EDAnalyzer { + public: + AnalyzerZHT(const ParameterSet& iConfig); + void beginJob() override {} + void beginRun(const Run& iEvent, const EventSetup& iSetup) override; + void analyze(const Event& iEvent, const EventSetup& iSetup) override; + void endRun(const Run& iEvent, const EventSetup& iSetup) override {} + void endJob() override; + + private: + // + void formTracks(const StreamStub& stream, vector>& tracks) const; + // + void associate(const vector>& tracks, const StubAssociation* ass, set& tps, int& sum) const; + + // ED input token of stubs + EDGetTokenT edGetTokenAccepted_; + // ED input token of lost stubs + EDGetTokenT edGetTokenLost_; + // ED input token of TTStubRef to TPPtr association for tracking efficiency + EDGetTokenT edGetTokenSelection_; + // ED input token of TTStubRef to recontructable TPPtr association + EDGetTokenT edGetTokenReconstructable_; + // Setup token + ESGetToken esGetTokenSetup_; + // DataFormats token + ESGetToken esGetTokenDataFormats_; + // stores, calculates and provides run-time constants + const Setup* setup_; + // helper class to extract structured data from tt::Frames + const DataFormats* dataFormats_; + // enables analyze of TPs + bool useMCTruth_; + // + int nEvents_; + + // Histograms + + TProfile* prof_; + TProfile* profChannel_; + TH1F* hisChannel_; + TH1F* hisEff_; + TH1F* hisEffTotal_; + TEfficiency* eff_; + + // printout + stringstream log_; + }; + + AnalyzerZHT::AnalyzerZHT(const ParameterSet& iConfig) + : useMCTruth_(iConfig.getParameter("UseMCTruth")), nEvents_(0) { + usesResource("TFileService"); + // book in- and output ED products + const string& label = iConfig.getParameter("LabelZHT"); + const string& branchAccepted = iConfig.getParameter("BranchAcceptedStubs"); + const string& branchLost = iConfig.getParameter("BranchLostStubs"); + edGetTokenAccepted_ = consumes(InputTag(label, branchAccepted)); + edGetTokenLost_ = consumes(InputTag(label, branchLost)); + if (useMCTruth_) { + const auto& inputTagSelecttion = iConfig.getParameter("InputTagSelection"); + const auto& inputTagReconstructable = iConfig.getParameter("InputTagReconstructable"); + edGetTokenSelection_ = consumes(inputTagSelecttion); + edGetTokenReconstructable_ = consumes(inputTagReconstructable); + } + // book ES products + esGetTokenSetup_ = esConsumes(); + esGetTokenDataFormats_ = esConsumes(); + // initial ES products + setup_ = nullptr; + dataFormats_ = nullptr; + // log config + log_.setf(ios::fixed, ios::floatfield); + log_.precision(4); + } + + void AnalyzerZHT::beginRun(const Run& iEvent, const EventSetup& iSetup) { + // helper class to store configurations + setup_ = &iSetup.getData(esGetTokenSetup_); + // helper class to extract structured data from tt::Frames + dataFormats_ = &iSetup.getData(esGetTokenDataFormats_); + // book histograms + Service fs; + TFileDirectory dir; + dir = fs->mkdir("ZHT"); + prof_ = dir.make("Counts", ";", 9, 0.5, 9.5); + prof_->GetXaxis()->SetBinLabel(1, "Stubs"); + prof_->GetXaxis()->SetBinLabel(2, "Tracks"); + prof_->GetXaxis()->SetBinLabel(3, "Lost Tracks"); + prof_->GetXaxis()->SetBinLabel(4, "Matched Tracks"); + prof_->GetXaxis()->SetBinLabel(5, "All Tracks"); + prof_->GetXaxis()->SetBinLabel(6, "Found TPs"); + prof_->GetXaxis()->SetBinLabel(7, "Found selected TPs"); + prof_->GetXaxis()->SetBinLabel(8, "Lost TPs"); + prof_->GetXaxis()->SetBinLabel(9, "All TPs"); + // channel occupancy + constexpr int maxOcc = 180; + const int numChannels = dataFormats_->numChannel(Process::zht); + hisChannel_ = dir.make("His Channel Occupancy", ";", maxOcc, -.5, maxOcc - .5); + profChannel_ = dir.make("Prof Channel Occupancy", ";", numChannels, -.5, numChannels - .5); + // Efficiencies + hisEffTotal_ = dir.make("HisTPEtaTotal", ";", 128, -2.5, 2.5); + hisEff_ = dir.make("HisTPEta", ";", 128, -2.5, 2.5); + eff_ = dir.make("EffEta", ";", 128, -2.5, 2.5); + } + + void AnalyzerZHT::analyze(const Event& iEvent, const EventSetup& iSetup) { + auto fill = [this](const TPPtr& tpPtr, TH1F* his) { his->Fill(tpPtr->eta()); }; + // read in ht products + Handle handleAccepted; + iEvent.getByToken(edGetTokenAccepted_, handleAccepted); + Handle handleLost; + iEvent.getByToken(edGetTokenLost_, handleLost); + // read in MCTruth + const StubAssociation* selection = nullptr; + const StubAssociation* reconstructable = nullptr; + if (useMCTruth_) { + Handle handleSelection; + iEvent.getByToken(edGetTokenSelection_, handleSelection); + selection = handleSelection.product(); + prof_->Fill(9, selection->numTPs()); + Handle handleReconstructable; + iEvent.getByToken(edGetTokenReconstructable_, handleReconstructable); + reconstructable = handleReconstructable.product(); + for (const auto& p : selection->getTrackingParticleToTTStubsMap()) + fill(p.first, hisEffTotal_); + } + // analyze ht products and associate found tracks with reconstrucable TrackingParticles + set tpPtrs; + set tpPtrsSelection; + set tpPtrsLost; + int allMatched(0); + int allTracks(0); + for (int region = 0; region < setup_->numRegions(); region++) { + int nStubs(0); + int nTracks(0); + int nLost(0); + for (int channel = 0; channel < dataFormats_->numChannel(Process::mht); channel++) { + const int index = region * dataFormats_->numChannel(Process::mht) + channel; + const StreamStub& accepted = handleAccepted->at(index); + hisChannel_->Fill(accepted.size()); + profChannel_->Fill(channel, accepted.size()); + nStubs += accumulate(accepted.begin(), accepted.end(), 0, [](int& sum, const FrameStub& frame) { + return sum += frame.first.isNonnull() ? 1 : 0; + }); + vector> tracks; + vector> lost; + formTracks(accepted, tracks); + formTracks(handleLost->at(index), lost); + nTracks += tracks.size(); + allTracks += tracks.size(); + nLost += lost.size(); + if (!useMCTruth_) + continue; + int tmp(0); + associate(tracks, selection, tpPtrsSelection, tmp); + associate(lost, selection, tpPtrsLost, tmp); + associate(tracks, reconstructable, tpPtrs, allMatched); + } + prof_->Fill(1, nStubs); + prof_->Fill(2, nTracks); + prof_->Fill(3, nLost); + } + for (const TPPtr& tpPtr : tpPtrsSelection) + fill(tpPtr, hisEff_); + vector recovered; + recovered.reserve(tpPtrsLost.size()); + set_intersection(tpPtrsLost.begin(), tpPtrsLost.end(), tpPtrs.begin(), tpPtrs.end(), back_inserter(recovered)); + for (const TPPtr& tpPtr : recovered) + tpPtrsLost.erase(tpPtr); + prof_->Fill(4, allMatched); + prof_->Fill(5, allTracks); + prof_->Fill(6, tpPtrs.size()); + prof_->Fill(7, tpPtrsSelection.size()); + prof_->Fill(8, tpPtrsLost.size()); + nEvents_++; + //if ((int)tpPtrsSelection.size() != selection->numTPs()) + //throw cms::Exception("..."); + } + + void AnalyzerZHT::endJob() { + if (nEvents_ == 0) + return; + // effi + eff_->SetPassedHistogram(*hisEff_, "f"); + eff_->SetTotalHistogram(*hisEffTotal_, "f"); + // printout SF summary + const double totalTPs = prof_->GetBinContent(9); + const double numStubs = prof_->GetBinContent(1); + const double numTracks = prof_->GetBinContent(2); + const double numTracksLost = prof_->GetBinContent(3); + const double totalTracks = prof_->GetBinContent(5); + const double numTracksMatched = prof_->GetBinContent(4); + const double numTPsAll = prof_->GetBinContent(6); + const double numTPsEff = prof_->GetBinContent(7); + const double numTPsLost = prof_->GetBinContent(8); + const double errStubs = prof_->GetBinError(1); + const double errTracks = prof_->GetBinError(2); + const double errTracksLost = prof_->GetBinError(3); + const double fracFake = (totalTracks - numTracksMatched) / totalTracks; + const double fracDup = (numTracksMatched - numTPsAll) / totalTracks; + const double eff = numTPsEff / totalTPs; + const double errEff = sqrt(eff * (1. - eff) / totalTPs / nEvents_); + const double effLoss = numTPsLost / totalTPs; + const double errEffLoss = sqrt(effLoss * (1. - effLoss) / totalTPs / nEvents_); + const vector nums = {numStubs, numTracks, numTracksLost}; + const vector errs = {errStubs, errTracks, errTracksLost}; + const int wNums = ceil(log10(*max_element(nums.begin(), nums.end()))) + 5; + const int wErrs = ceil(log10(*max_element(errs.begin(), errs.end()))) + 5; + log_ << " ZHT SUMMARY " << endl; + log_ << "number of stubs per TFP = " << setw(wNums) << numStubs << " +- " << setw(wErrs) << errStubs << endl; + log_ << "number of tracks per TFP = " << setw(wNums) << numTracks << " +- " << setw(wErrs) << errTracks + << endl; + log_ << "number of lost tracks per TFP = " << setw(wNums) << numTracksLost << " +- " << setw(wErrs) << errTracksLost + << endl; + log_ << " max tracking efficiency = " << setw(wNums) << eff << " +- " << setw(wErrs) << errEff << endl; + log_ << " lost tracking efficiency = " << setw(wNums) << effLoss << " +- " << setw(wErrs) << errEffLoss << endl; + log_ << " fake rate = " << setw(wNums) << fracFake << endl; + log_ << " duplicate rate = " << setw(wNums) << fracDup << endl; + log_ << "============================================================="; + LogPrint("L1Trigger/TrackerTFP") << log_.str(); + } + + // + void AnalyzerZHT::formTracks(const StreamStub& stream, vector>& tracks) const { + vector stubs; + stubs.reserve(stream.size()); + for (const FrameStub& frame : stream) + if (frame.first.isNonnull()) + stubs.emplace_back(frame, dataFormats_); + for (auto it = stubs.begin(); it != stubs.end();) { + const auto start = it; + const int id = it->trackId(); + auto different = [id](const StubZHT& stub) { return id != stub.trackId(); }; + it = find_if(it, stubs.end(), different); + vector ttStubRefs; + ttStubRefs.reserve(distance(start, it)); + transform(start, it, back_inserter(ttStubRefs), [](const StubZHT& stub) { return stub.ttStubRef(); }); + tracks.push_back(ttStubRefs); + } + } + + // + void AnalyzerZHT::associate(const vector>& tracks, + const StubAssociation* ass, + set& tps, + int& sum) const { + for (const vector& ttStubRefs : tracks) { + const vector& tpPtrs = ass->associate(ttStubRefs); + if (tpPtrs.empty()) + continue; + sum++; + copy(tpPtrs.begin(), tpPtrs.end(), inserter(tps, tps.begin())); + } + } + +} // namespace trackerTFP + +DEFINE_FWK_MODULE(trackerTFP::AnalyzerZHT); \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/test/BuildFile.xml b/L1Trigger/TrackerTFP/test/BuildFile.xml new file mode 100644 index 0000000000000..726dde4748124 --- /dev/null +++ b/L1Trigger/TrackerTFP/test/BuildFile.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/test/ProducerAS.cc b/L1Trigger/TrackerTFP/test/ProducerAS.cc new file mode 100644 index 0000000000000..b5f8040b47994 --- /dev/null +++ b/L1Trigger/TrackerTFP/test/ProducerAS.cc @@ -0,0 +1,99 @@ +#include "FWCore/Framework/interface/stream/EDProducer.h" +#include "FWCore/Framework/interface/Run.h" +#include "FWCore/Framework/interface/EventSetup.h" +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/MakerMacros.h" +#include "FWCore/Utilities/interface/EDGetToken.h" +#include "FWCore/Utilities/interface/EDPutToken.h" +#include "FWCore/Utilities/interface/ESGetToken.h" +#include "FWCore/Utilities/interface/InputTag.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "DataFormats/Common/interface/Handle.h" + +#include "DataFormats/L1TrackTrigger/interface/TTTypes.h" +#include "L1Trigger/TrackTrigger/interface/Setup.h" + +#include + +using namespace std; +using namespace edm; +using namespace tt; + +namespace trackerTFP { + + /*! \class trackerTFP::ProducerAS + * \brief Associate the TTTracks output by KF fitter with the tracks input to KF fitter. + * \author Thomas Schuh + * \date 2020, Oct + */ + class ProducerAS : public stream::EDProducer<> { + public: + explicit ProducerAS(const ParameterSet&); + ~ProducerAS() override {} + + private: + void beginRun(const Run&, const EventSetup&) override; + void produce(Event&, const EventSetup&) override; + void endJob() {} + + // ED input token of kf tracks + EDGetTokenT edGetTokenKF_; + // ED input token of kf TTtracks + EDGetTokenT edGetTokenTT_; + // ED output token for TTTrackRefMap + EDPutTokenT edPutToken_; + // Setup token + ESGetToken esGetTokenSetup_; + // configuration + ParameterSet iConfig_; + // helper class to store configurations + const Setup* setup_; + }; + + ProducerAS::ProducerAS(const ParameterSet& iConfig) : iConfig_(iConfig) { + const string& labelKF = iConfig.getParameter("LabelKF"); + const string& labelTT = iConfig.getParameter("LabelTT"); + const string& branch = iConfig.getParameter("BranchAcceptedTracks"); + // book in- and output ED products + edGetTokenKF_ = consumes(InputTag(labelKF, branch)); + edGetTokenTT_ = consumes(InputTag(labelTT, branch)); + edPutToken_ = produces(branch); + // book ES products + esGetTokenSetup_ = esConsumes(); + // initial ES products + setup_ = nullptr; + } + + void ProducerAS::beginRun(const Run& iRun, const EventSetup& iSetup) { + // helper class to store configurations + setup_ = &iSetup.getData(esGetTokenSetup_); + if (!setup_->configurationSupported()) + return; + // check process history if desired + if (iConfig_.getParameter("CheckHistory")) + setup_->checkHistory(iRun.processHistory()); + } + + void ProducerAS::produce(Event& iEvent, const EventSetup& iSetup) { + // empty KFTTTrack product + TTTrackRefMap ttTrackMap; + // read in KF Product and produce AssociatorKF product + if (setup_->configurationSupported()) { + Handle handleKF; + iEvent.getByToken(edGetTokenKF_, handleKF); + const StreamsTrack& streams = *handleKF.product(); + Handle handleTT; + iEvent.getByToken(edGetTokenTT_, handleTT); + int i(0); + for (const StreamTrack& stream : streams) + for (const FrameTrack& frame : stream) + if (frame.first.isNonnull()) + ttTrackMap.emplace(TTTrackRef(handleTT, i++), frame.first); + } + // store products + iEvent.emplace(edPutToken_, move(ttTrackMap)); + } + +} // namespace trackerTFP + +DEFINE_FWK_MODULE(trackerTFP::ProducerAS); \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/test/demonstrator_cfg.py b/L1Trigger/TrackerTFP/test/demonstrator_cfg.py new file mode 100644 index 0000000000000..6778baed03186 --- /dev/null +++ b/L1Trigger/TrackerTFP/test/demonstrator_cfg.py @@ -0,0 +1,71 @@ +# this compares event by event the output of the C++ emulation with the ModelSim simulation of the firmware +import FWCore.ParameterSet.Config as cms + +process = cms.Process( "Demo" ) +process.load( 'FWCore.MessageService.MessageLogger_cfi' ) +process.load( 'Configuration.Geometry.GeometryExtended2026D76Reco_cff' ) +process.load( 'Configuration.Geometry.GeometryExtended2026D76_cff' ) +process.load( 'Configuration.StandardSequences.MagneticField_cff' ) +process.load( 'Configuration.StandardSequences.FrontierConditions_GlobalTag_cff' ) +process.load( 'L1Trigger.TrackTrigger.TrackTrigger_cff' ) + +from Configuration.AlCa.GlobalTag import GlobalTag +process.GlobalTag = GlobalTag(process.GlobalTag, 'auto:phase2_realistic', '') + +# load code that produces DTCStubs +process.load( 'L1Trigger.TrackerDTC.ProducerED_cff' ) +# cosutmize TT algorithm +#from L1Trigger.TrackerDTC.Customize_cff import * +#producerUseTMTT(process) +#analyzerUseTMTT(process) +#--- Load code that produces tfp Stubs +process.load( 'L1Trigger.TrackerTFP.Producer_cff' ) +#--- Load code that demonstrates tfp Stubs +process.load( 'L1Trigger.TrackerTFP.Demonstrator_cff' ) + +# build schedule +process.tt = cms.Sequence ( process.TrackerDTCProducer + + process.TrackerTFPProducerGP + + process.TrackerTFPProducerHT + + process.TrackerTFPProducerMHT + + process.TrackerTFPProducerZHT + + process.TrackerTFPProducerZHTout + + process.TrackerTFPProducerKFin + + process.TrackerTFPProducerKF + ) +process.demo = cms.Path( process.tt + process.TrackerTFPDemonstrator ) +process.schedule = cms.Schedule( process.demo ) + +# create options +import FWCore.ParameterSet.VarParsing as VarParsing +options = VarParsing.VarParsing( 'analysis' ) +# specify input MC +Samples = [ + #'/store/relval/CMSSW_11_3_0_pre6/RelValSingleMuFlatPt2To100/GEN-SIM-DIGI-RAW/113X_mcRun4_realistic_v6_2026D76noPU-v1/10000/05f802b7-b0b3-4cca-8b70-754682c3bb4c.root' + #'/store/relval/CMSSW_11_3_0_pre6/RelValDisplacedMuPt2To100Dxy100/GEN-SIM-DIGI-RAW/113X_mcRun4_realistic_v6_2026D76noPU-v1/00000/011da61a-9524-4a96-b91f-03e8690af3bd.root' + '/store/relval/CMSSW_11_3_0_pre6/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/00000/00026541-6200-4eed-b6f8-d3a1fd720e9c.root', + '/store/relval/CMSSW_11_3_0_pre6/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/00000/013d0125-8f6e-496b-8335-614398c9210d.root', + '/store/relval/CMSSW_11_3_0_pre6/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/00000/058bd134-86de-47e1-bcde-379ed9b79e1b.root', + '/store/relval/CMSSW_11_3_0_pre6/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/00000/0915d66c-cbd4-4ef6-9971-7dd59e198b56.root', + '/store/relval/CMSSW_11_3_0_pre6/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/00000/09823c8d-e443-4066-8347-8c704929cb2b.root', + '/store/relval/CMSSW_11_3_0_pre6/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/00000/0c39a1aa-93ee-41c1-8543-6d90c09114a7.root', + '/store/relval/CMSSW_11_3_0_pre6/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/00000/0fcdcc53-fb9f-4f0b-8529-a4d60d914c14.root', + '/store/relval/CMSSW_11_3_0_pre6/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/00000/16760a5c-9cd2-41c3-82e5-399bb962d537.root', + '/store/relval/CMSSW_11_3_0_pre6/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/00000/1752640f-2001-4d14-9276-063ec07cea92.root', + '/store/relval/CMSSW_11_3_0_pre6/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/00000/180712c9-31a5-4f2a-bf92-a7fbee4dabad.root' +] +options.register( 'inputMC', Samples, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.string, "Files to be processed" ) +# specify number of events to process. +options.register( 'Events',100,VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.int, "Number of Events to analyze" ) +options.parseArguments() + +process.options = cms.untracked.PSet( wantSummary = cms.untracked.bool(False) ) +process.maxEvents = cms.untracked.PSet( input = cms.untracked.int32(options.Events) ) +process.source = cms.Source( + "PoolSource", + fileNames = cms.untracked.vstring( options.inputMC ), + #skipEvents = cms.untracked.uint32( 914 ), + secondaryFileNames = cms.untracked.vstring(), + duplicateCheckMode = cms.untracked.string( 'noDuplicateCheck' ) +) +process.Timing = cms.Service( "Timing", summaryOnly = cms.untracked.bool( True ) ) \ No newline at end of file diff --git a/L1Trigger/TrackerTFP/test/test_cfg.py b/L1Trigger/TrackerTFP/test/test_cfg.py new file mode 100644 index 0000000000000..6f09abfed25a1 --- /dev/null +++ b/L1Trigger/TrackerTFP/test/test_cfg.py @@ -0,0 +1,87 @@ +################################################################################################ +# Run bit-accurate TMTT L1 tracking emulation. +# +# To run execute do +# cmsRun L1Trigger/L1TTrackerTFP/test/test_cfg.py +# where the arguments take default values if you don't specify them. You can change defaults below. +################################################################################################# + +import FWCore.ParameterSet.Config as cms + +process = cms.Process( "Demo" ) +process.load( 'FWCore.MessageService.MessageLogger_cfi' ) +process.load( 'Configuration.Geometry.GeometryExtended2026D76Reco_cff' ) +process.load( 'Configuration.Geometry.GeometryExtended2026D76_cff' ) +process.load( 'Configuration.StandardSequences.MagneticField_cff' ) +process.load( 'Configuration.StandardSequences.FrontierConditions_GlobalTag_cff' ) +process.load( 'L1Trigger.TrackTrigger.TrackTrigger_cff' ) + +from Configuration.AlCa.GlobalTag import GlobalTag +process.GlobalTag = GlobalTag(process.GlobalTag, 'auto:phase2_realistic', '') + +# load code that associates stubs with mctruth +process.load( 'SimTracker.TrackTriggerAssociation.StubAssociator_cff' ) +# load code that produces DTCStubs +process.load( 'L1Trigger.TrackerDTC.ProducerED_cff' ) +# load code that analyzes DTCStubs +process.load( 'L1Trigger.TrackerDTC.Analyzer_cff' ) +# cosutmize TT algorithm +from L1Trigger.TrackerDTC.Customize_cff import * +producerUseTMTT( process ) +analyzerUseTMTT( process ) +#--- Load code that produces tfp Stubs +process.load( 'L1Trigger.TrackerTFP.Producer_cff' ) +from L1Trigger.TrackerTFP.Customize_cff import * +setupUseTMTT( process ) +#--- Load code that analyzes tfp Stubs +process.load( 'L1Trigger.TrackerTFP.Analyzer_cff' ) + +# build schedule +process.mc = cms.Sequence( process.StubAssociator ) +process.dtc = cms.Sequence( process.TrackerDTCProducer + process.TrackerDTCAnalyzer ) +process.gp = cms.Sequence( process.TrackerTFPProducerGP + process.TrackerTFPAnalyzerGP ) +process.ht = cms.Sequence( process.TrackerTFPProducerHT + process.TrackerTFPAnalyzerHT ) +process.mht = cms.Sequence( process.TrackerTFPProducerMHT + process.TrackerTFPAnalyzerMHT ) +process.zht = cms.Sequence( process.TrackerTFPProducerZHT + process.TrackerTFPAnalyzerZHT ) +process.interIn = cms.Sequence( process.TrackerTFPProducerZHTout + process.TrackerTFPProducerKFin + process.TrackerTFPAnalyzerKFin ) +process.kf = cms.Sequence( process.TrackerTFPProducerKF + process.TrackerTFPAnalyzerKF ) +process.interOut = cms.Sequence( process.TrackerTFPProducerTT + process.TrackerTFPProducerAS )#+ process.TrackerTFPAnalyzerTT ) +process.tt = cms.Path( process.mc + process.dtc + process.gp + process.ht + process.mht + process.zht + process.interIn + process.kf )#+ process.interOut ) +process.schedule = cms.Schedule( process.tt ) + +# create options +import FWCore.ParameterSet.VarParsing as VarParsing +options = VarParsing.VarParsing( 'analysis' ) +# specify input MC +Samples = [ + #'/store/relval/CMSSW_11_3_0_pre6/RelValSingleMuFlatPt2To100/GEN-SIM-DIGI-RAW/113X_mcRun4_realistic_v6_2026D76noPU-v1/10000/05f802b7-b0b3-4cca-8b70-754682c3bb4c.root' + #'/store/relval/CMSSW_11_3_0_pre6/RelValDisplacedMuPt2To100Dxy100/GEN-SIM-DIGI-RAW/113X_mcRun4_realistic_v6_2026D76noPU-v1/00000/011da61a-9524-4a96-b91f-03e8690af3bd.root' + '/store/relval/CMSSW_11_3_0_pre6/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/00000/00026541-6200-4eed-b6f8-d3a1fd720e9c.root', + '/store/relval/CMSSW_11_3_0_pre6/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/00000/013d0125-8f6e-496b-8335-614398c9210d.root', + '/store/relval/CMSSW_11_3_0_pre6/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/00000/058bd134-86de-47e1-bcde-379ed9b79e1b.root', + '/store/relval/CMSSW_11_3_0_pre6/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/00000/0915d66c-cbd4-4ef6-9971-7dd59e198b56.root', + '/store/relval/CMSSW_11_3_0_pre6/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/00000/09823c8d-e443-4066-8347-8c704929cb2b.root', + '/store/relval/CMSSW_11_3_0_pre6/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/00000/0c39a1aa-93ee-41c1-8543-6d90c09114a7.root', + '/store/relval/CMSSW_11_3_0_pre6/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/00000/0fcdcc53-fb9f-4f0b-8529-a4d60d914c14.root', + '/store/relval/CMSSW_11_3_0_pre6/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/00000/16760a5c-9cd2-41c3-82e5-399bb962d537.root', + '/store/relval/CMSSW_11_3_0_pre6/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/00000/1752640f-2001-4d14-9276-063ec07cea92.root', + '/store/relval/CMSSW_11_3_0_pre6/RelValTTbar_14TeV/GEN-SIM-DIGI-RAW/PU_113X_mcRun4_realistic_v6_2026D76PU200-v1/00000/180712c9-31a5-4f2a-bf92-a7fbee4dabad.root' +] +options.register( 'inputMC', Samples, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.string, "Files to be processed" ) +# specify number of events to process. +options.register( 'Events',100,VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.int, "Number of Events to analyze" ) +options.parseArguments() + +process.options = cms.untracked.PSet( wantSummary = cms.untracked.bool(False) ) +process.maxEvents = cms.untracked.PSet( input = cms.untracked.int32(options.Events) ) +process.source = cms.Source( + "PoolSource", + fileNames = cms.untracked.vstring( options.inputMC ), + #skipEvents = cms.untracked.uint32( 3 + 8 ), + noEventSort = cms.untracked.bool( True ), + secondaryFileNames = cms.untracked.vstring(), + duplicateCheckMode = cms.untracked.string( 'noDuplicateCheck' ) +) +#process.Timing = cms.Service( "Timing", summaryOnly = cms.untracked.bool( True ) ) +process.MessageLogger.cerr.enableStatistics = False +process.TFileService = cms.Service( "TFileService", fileName = cms.string( "Hist.root" ) ) diff --git a/SimTracker/TrackTriggerAssociation/BuildFile.xml b/SimTracker/TrackTriggerAssociation/BuildFile.xml index fe4a86de3884f..bce23d26a9c74 100644 --- a/SimTracker/TrackTriggerAssociation/BuildFile.xml +++ b/SimTracker/TrackTriggerAssociation/BuildFile.xml @@ -14,6 +14,7 @@ + diff --git a/SimTracker/TrackTriggerAssociation/interface/StubAssociation.h b/SimTracker/TrackTriggerAssociation/interface/StubAssociation.h new file mode 100644 index 0000000000000..5820b3910150f --- /dev/null +++ b/SimTracker/TrackTriggerAssociation/interface/StubAssociation.h @@ -0,0 +1,63 @@ +#ifndef SimTracker_TrackTriggerAssociation_StubAssociation_h +#define SimTracker_TrackTriggerAssociation_StubAssociation_h + +#include "SimTracker/TrackTriggerAssociation/interface/TTTypes.h" +#include "L1Trigger/TrackTrigger/interface/Setup.h" + +#include +#include + +namespace tt { + + /*! \class tt::StubAssociation + * \brief Class to associate reconstrucable TrackingParticles with TTStubs and vice versa. + * It may associate multiple TPs with a TTStub and can therefore be used to associate + * TTTracks with TrackingParticles. + * \author Thomas Schuh + * \date 2020, Apr + */ + class StubAssociation { + public: + StubAssociation() { setup_ = nullptr; } + StubAssociation(const Setup* setup) : setup_(setup) {} + ~StubAssociation() {} + + // insert a TPPtr and its associated collection of TTstubRefs into the underlayering maps + void insert(const TPPtr& tpPtr, const std::vector& ttSTubRefs); + // returns map containing TTStubRef and their associated collection of TPPtrs + const std::map>& getTTStubToTrackingParticlesMap() const { + return mapTTStubRefsTPPtrs_; + } + // returns map containing TPPtr and their associated collection of TTStubRefs + const std::map>& getTrackingParticleToTTStubsMap() const { + return mapTPPtrsTTStubRefs_; + } + // returns collection of TPPtrs associated to given TTstubRef + std::vector findTrackingParticlePtrs(const TTStubRef& ttStubRef) const; + // returns collection of TTStubRefs associated to given TPPtr + std::vector findTTStubRefs(const TPPtr& tpPtr) const; + // total number of stubs associated with TPs + int numStubs() const { return mapTTStubRefsTPPtrs_.size(); }; + // total number of TPs associated with stubs + int numTPs() const { return mapTPPtrsTTStubRefs_.size(); }; + // Get all TPs that are matched to these stubs in at least 'tpMinLayers' layers and 'tpMinLayersPS' ps layers + std::vector associate(const std::vector& ttStubRefs) const; + // Get all TPs that are matched to these stubs in at least 'tpMinLayers' layers and 'tpMinLayersPS' ps layers with not more then 'tpMaxBadStubs2S' not associated 2S stubs and not more then 'tpMaxBadStubsPS' associated PS stubs + std::vector associateFinal(const std::vector& ttStubRefs) const; + + private: + // stores, calculates and provides run-time constants + const Setup* setup_; + // map containing TTStubRef and their associated collection of TPPtrs + std::map> mapTTStubRefsTPPtrs_; + // map containing TPPtr and their associated collection of TTStubRefs + std::map> mapTPPtrsTTStubRefs_; + // empty container of TPPtr + const std::vector emptyTPPtrs_; + // empty container of TTStubRef + const std::vector emptyTTStubRefs_; + }; + +} // namespace tt + +#endif \ No newline at end of file diff --git a/SimTracker/TrackTriggerAssociation/interface/TTTypes.h b/SimTracker/TrackTriggerAssociation/interface/TTTypes.h new file mode 100644 index 0000000000000..24afd24f83577 --- /dev/null +++ b/SimTracker/TrackTriggerAssociation/interface/TTTypes.h @@ -0,0 +1,16 @@ +#ifndef SimTracker_TrackTriggerAssociation_TTTypes_h +#define SimTracker_TrackTriggerAssociation_TTTypes_h + +#include "DataFormats/Common/interface/Ptr.h" +#include "DataFormats/L1TrackTrigger/interface/TTTypes.h" +#include "SimDataFormats/TrackingAnalysis/interface/TrackingParticle.h" +#include "SimTracker/TrackTriggerAssociation/interface/TTStubAssociationMap.h" +#include "SimTracker/TrackTriggerAssociation/interface/TTClusterAssociationMap.h" +#include "SimTracker/TrackTriggerAssociation/interface/TTTrackAssociationMap.h" + +typedef edm::Ptr TPPtr; +typedef TTStubAssociationMap TTStubAssMap; +typedef TTClusterAssociationMap TTClusterAssMap; +typedef TTTrackAssociationMap TTTrackAssMap; + +#endif \ No newline at end of file diff --git a/SimTracker/TrackTriggerAssociation/plugins/StubAssociator.cc b/SimTracker/TrackTriggerAssociation/plugins/StubAssociator.cc new file mode 100644 index 0000000000000..8646c335f6fbd --- /dev/null +++ b/SimTracker/TrackTriggerAssociation/plugins/StubAssociator.cc @@ -0,0 +1,116 @@ +#include "FWCore/Framework/interface/stream/EDProducer.h" +#include "FWCore/Framework/interface/Run.h" +#include "FWCore/Framework/interface/EventSetup.h" +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/MakerMacros.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/Utilities/interface/InputTag.h" +#include "FWCore/Utilities/interface/EDGetToken.h" +#include "FWCore/Utilities/interface/EDPutToken.h" +#include "DataFormats/Common/interface/Handle.h" + +#include "SimTracker/TrackTriggerAssociation/interface/TTTypes.h" +#include "SimTracker/TrackTriggerAssociation/interface/StubAssociation.h" +#include "L1Trigger/TrackTrigger/interface/Setup.h" + +#include +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace edm; + +namespace tt { + + /*! \class tt::StubAssociator + * \brief Class to associate reconstrucable TrackingParticles with TTStubs and vice versa + * It may associate multiple TPs with a TTStub and can therefore be used to associate + * TTTracks with TrackingParticles. This EDProducer creates two StubAssociation EDProducts, + * one using only TP that are "reconstructable" (produce stubs in a min. number of layers) + * and one using TP that are also "use for the tracking efficiency measurement". + * \author Thomas Schuh + * \date 2020, Apr + */ + class StubAssociator : public stream::EDProducer<> { + public: + explicit StubAssociator(const ParameterSet&); + ~StubAssociator() override {} + + private: + void beginRun(const Run&, const EventSetup&) override; + void produce(Event&, const EventSetup&) override; + void endJob() {} + + // helper classe to store configurations + const Setup* setup_; + // ED input token of TTStubs + EDGetTokenT getTokenTTStubDetSetVec_; + // ED input token of TTClusterAssociation + EDGetTokenT getTokenTTClusterAssMap_; + // ED output token for recosntructable stub association + EDPutTokenT putTokenReconstructable_; + // ED output token for selected stub association + EDPutTokenT putTokenSelection_; + // Setup token + ESGetToken esGetTokenSetup_; + }; + + StubAssociator::StubAssociator(const ParameterSet& iConfig) { + // book in- and output ed products + getTokenTTStubDetSetVec_ = consumes(iConfig.getParameter("InputTagTTStubDetSetVec")); + getTokenTTClusterAssMap_ = consumes(iConfig.getParameter("InputTagTTClusterAssMap")); + putTokenReconstructable_ = produces(iConfig.getParameter("BranchReconstructable")); + putTokenSelection_ = produces(iConfig.getParameter("BranchSelection")); + // book ES product + esGetTokenSetup_ = esConsumes(); + } + + void StubAssociator::beginRun(const Run& iRun, const EventSetup& iSetup) { + setup_ = &iSetup.getData(esGetTokenSetup_); + } + + void StubAssociator::produce(Event& iEvent, const EventSetup& iSetup) { + // associate TTStubs with TrackingParticles + Handle handleTTStubDetSetVec; + iEvent.getByToken(getTokenTTStubDetSetVec_, handleTTStubDetSetVec); + Handle handleTTClusterAssMap; + Handle handleTTStubAssMap; + iEvent.getByToken(getTokenTTClusterAssMap_, handleTTClusterAssMap); + map> mapTPPtrsTTStubRefs; + auto isNonnull = [](const TPPtr& tpPtr) { return tpPtr.isNonnull(); }; + for (TTStubDetSetVec::const_iterator ttModule = handleTTStubDetSetVec->begin(); + ttModule != handleTTStubDetSetVec->end(); + ttModule++) { + for (TTStubDetSet::const_iterator ttStub = ttModule->begin(); ttStub != ttModule->end(); ttStub++) { + const TTStubRef ttStubRef = makeRefTo(handleTTStubDetSetVec, ttStub); + set tpPtrs; + for (unsigned int iClus = 0; iClus < 2; iClus++) { + const vector& assocPtrs = + handleTTClusterAssMap->findTrackingParticlePtrs(ttStubRef->clusterRef(iClus)); + copy_if(assocPtrs.begin(), assocPtrs.end(), inserter(tpPtrs, tpPtrs.begin()), isNonnull); + } + for (const TPPtr& tpPtr : tpPtrs) + mapTPPtrsTTStubRefs[tpPtr].push_back(ttStubRef); + } + } + // associate reconstructable TrackingParticles with TTStubs + StubAssociation reconstructable(setup_); + StubAssociation selection(setup_); + for (const pair>& p : mapTPPtrsTTStubRefs) { + if (!setup_->useForReconstructable(*p.first) || !setup_->reconstructable(p.second)) + continue; + reconstructable.insert(p.first, p.second); + if (setup_->useForAlgEff(*p.first)) + selection.insert(p.first, p.second); + } + iEvent.emplace(putTokenReconstructable_, move(reconstructable)); + iEvent.emplace(putTokenSelection_, move(selection)); + } + +} // namespace tt + +DEFINE_FWK_MODULE(tt::StubAssociator); \ No newline at end of file diff --git a/SimTracker/TrackTriggerAssociation/python/StubAssociator_cff.py b/SimTracker/TrackTriggerAssociation/python/StubAssociator_cff.py new file mode 100644 index 0000000000000..f5ac90c9667f3 --- /dev/null +++ b/SimTracker/TrackTriggerAssociation/python/StubAssociator_cff.py @@ -0,0 +1,13 @@ +#--------------------------------------------------------------------------------------------------------- +# This definess StubAssociator which produces StubAssociation which will be used by L1Tigger/trackerDTC and +# trackerTFP Analyzer to associate Stubs with MC truth either by using TTStubAssociationMap or +# TTClusterAssociationMap, where the latter is more useful to debug l1 tracking, the former has been +# implemented to enable use of same association as in standart workflow analyzer if wanted. +#--------------------------------------------------------------------------------------------------------- + +import FWCore.ParameterSet.Config as cms + +from L1Trigger.TrackTrigger.ProducerSetup_cff import TrackTriggerSetup +from SimTracker.TrackTriggerAssociation.StubAssociator_cfi import StubAssociator_params + +StubAssociator = cms.EDProducer('tt::StubAssociator', StubAssociator_params) \ No newline at end of file diff --git a/SimTracker/TrackTriggerAssociation/python/StubAssociator_cfi.py b/SimTracker/TrackTriggerAssociation/python/StubAssociator_cfi.py new file mode 100644 index 0000000000000..f5d782fe957a5 --- /dev/null +++ b/SimTracker/TrackTriggerAssociation/python/StubAssociator_cfi.py @@ -0,0 +1,9 @@ +import FWCore.ParameterSet.Config as cms + +StubAssociator_params = cms.PSet ( + InputTagTTStubDetSetVec = cms.InputTag( "TTStubsFromPhase2TrackerDigis", "StubAccepted" ), # + InputTagTTClusterAssMap = cms.InputTag( "TTClusterAssociatorFromPixelDigis", "ClusterAccepted" ), # + InputTagTTStubAssMap = cms.InputTag( "TTStubAssociatorFromPixelDigis", "StubAccepted" ), # + BranchReconstructable = cms.string ( "Reconstructable" ), # name of StubAssociation collection made with reconstractable TPs + BranchSelection = cms.string ( "UseForAlgEff" ) # name of StubAssociation collection used for tracking efficiency +) \ No newline at end of file diff --git a/SimTracker/TrackTriggerAssociation/src/StubAssociation.cc b/SimTracker/TrackTriggerAssociation/src/StubAssociation.cc new file mode 100644 index 0000000000000..637ee58ec6cb7 --- /dev/null +++ b/SimTracker/TrackTriggerAssociation/src/StubAssociation.cc @@ -0,0 +1,80 @@ +#include "SimTracker/TrackTriggerAssociation/interface/StubAssociation.h" + +#include +#include +#include +#include + +using namespace std; + +namespace tt { + + // insert a TPPtr and its associated collection of TTstubRefs into the underlayering maps + void StubAssociation::insert(const TPPtr& tpPtr, const vector& ttSTubRefs) { + mapTPPtrsTTStubRefs_.insert({tpPtr, ttSTubRefs}); + for (const TTStubRef& ttSTubRef : ttSTubRefs) + mapTTStubRefsTPPtrs_[ttSTubRef].push_back(tpPtr); + } + + // returns collection of TPPtrs associated to given TTstubRef + vector StubAssociation::findTrackingParticlePtrs(const TTStubRef& ttStubRef) const { + const auto it = mapTTStubRefsTPPtrs_.find(ttStubRef); + const vector res = it != mapTTStubRefsTPPtrs_.end() ? it->second : emptyTPPtrs_; + return res; + } + + // returns collection of TTStubRefs associated to given TPPtr + vector StubAssociation::findTTStubRefs(const TPPtr& tpPtr) const { + const auto it = mapTPPtrsTTStubRefs_.find(tpPtr); + return it != mapTPPtrsTTStubRefs_.end() ? it->second : emptyTTStubRefs_; + } + + // Get all TPs that are matched to these stubs in at least 'tpMinLayers' layers and 'tpMinLayersPS' ps layers + vector StubAssociation::associate(const vector& ttStubRefs) const { + // count associated layer for each TP + map> m; + map> mPS; + for (const TTStubRef& ttStubRef : ttStubRefs) { + for (const TPPtr& tpPtr : findTrackingParticlePtrs(ttStubRef)) { + const int layerId = setup_->layerId(ttStubRef); + m[tpPtr].insert(layerId); + if (setup_->psModule(ttStubRef)) + mPS[tpPtr].insert(layerId); + } + } + // count matched TPs + auto sum = [this](int& sum, const pair>& p) { + return sum += ((int)p.second.size() < setup_->tpMinLayers() ? 0 : 1); + }; + const int nTPs = accumulate(m.begin(), m.end(), 0, sum); + vector tpPtrs; + tpPtrs.reserve(nTPs); + // fill and return matched TPs + for (const auto& p : m) + if ((int)p.second.size() >= setup_->tpMinLayers() && (int)mPS[p.first].size() >= setup_->tpMinLayersPS()) + tpPtrs.push_back(p.first); + return tpPtrs; + } + + // Get all TPs that are matched to these stubs in at least 'tpMinLayers' layers and 'tpMinLayersPS' ps layers with not more then 'tpMaxBadStubs2S' not associated 2S stubs and not more then 'tpMaxBadStubsPS' associated PS stubs + std::vector StubAssociation::associateFinal(const std::vector& ttStubRefs) const { + // Get all TPs that are matched to these stubs in at least 'tpMinLayers' layers and 'tpMinLayersPS' ps layers + vector tpPtrs = associate(ttStubRefs); + // remove TPs with more then 'tpMaxBadStubs2S' not associated 2S stubs and more then 'tpMaxBadStubsPS' not associated PS stubs + auto check = [this, &ttStubRefs](const TPPtr& tpPtr) { + int bad2S(0); + int badPS(0); + for (const TTStubRef& ttStubRef : ttStubRefs) { + const vector& tpPtrs = findTrackingParticlePtrs(ttStubRef); + if (find(tpPtrs.begin(), tpPtrs.end(), tpPtr) == tpPtrs.end()) + setup_->psModule(ttStubRef) ? badPS++ : bad2S++; + } + if (badPS > setup_->tpMaxBadStubsPS() || bad2S > setup_->tpMaxBadStubs2S()) + return true; + return false; + }; + tpPtrs.erase(remove_if(tpPtrs.begin(), tpPtrs.end(), check), tpPtrs.end()); + return tpPtrs; + } + +} // namespace tt diff --git a/SimTracker/TrackTriggerAssociation/src/classes.h b/SimTracker/TrackTriggerAssociation/src/classes.h index 792e0926e2de3..e02f7f5987cad 100644 --- a/SimTracker/TrackTriggerAssociation/src/classes.h +++ b/SimTracker/TrackTriggerAssociation/src/classes.h @@ -7,8 +7,5 @@ */ #include "DataFormats/Common/interface/Wrapper.h" -#include "DataFormats/Common/interface/DetSetVectorNew.h" -#include "DataFormats/L1TrackTrigger/interface/TTTypes.h" -#include "SimTracker/TrackTriggerAssociation/interface/TTClusterAssociationMap.h" -#include "SimTracker/TrackTriggerAssociation/interface/TTStubAssociationMap.h" -#include "SimTracker/TrackTriggerAssociation/interface/TTTrackAssociationMap.h" +#include "SimTracker/TrackTriggerAssociation/interface/TTTypes.h" +#include "SimTracker/TrackTriggerAssociation/interface/StubAssociation.h" diff --git a/SimTracker/TrackTriggerAssociation/src/classes_def.xml b/SimTracker/TrackTriggerAssociation/src/classes_def.xml index 75775c56edfa6..3a79a92a05340 100644 --- a/SimTracker/TrackTriggerAssociation/src/classes_def.xml +++ b/SimTracker/TrackTriggerAssociation/src/classes_def.xml @@ -48,4 +48,15 @@ + + + + + + + + + + +