diff --git a/DataFormats/GEMDigi/interface/ME0TriggerDigiCollection.h b/DataFormats/GEMDigi/interface/ME0TriggerDigiCollection.h index de2f10186e05e..9bb32d91ecaa4 100644 --- a/DataFormats/GEMDigi/interface/ME0TriggerDigiCollection.h +++ b/DataFormats/GEMDigi/interface/ME0TriggerDigiCollection.h @@ -8,9 +8,11 @@ */ #include "DataFormats/MuonDetId/interface/ME0DetId.h" +#include "DataFormats/MuonDetId/interface/GEMDetId.h" #include "DataFormats/GEMDigi/interface/ME0TriggerDigi.h" #include "DataFormats/MuonData/interface/MuonDigiCollection.h" typedef MuonDigiCollection ME0TriggerDigiCollection; +typedef MuonDigiCollection GE0TriggerDigiCollection; #endif diff --git a/DataFormats/GEMDigi/src/classes_def.xml b/DataFormats/GEMDigi/src/classes_def.xml index 933da64f447f3..0f0d0bf06a077 100644 --- a/DataFormats/GEMDigi/src/classes_def.xml +++ b/DataFormats/GEMDigi/src/classes_def.xml @@ -137,4 +137,9 @@ + + + + + diff --git a/DataFormats/L1TMuonPhase2/BuildFile.xml b/DataFormats/L1TMuonPhase2/BuildFile.xml index 30d1101e0e69d..ad2fbc6d9100e 100644 --- a/DataFormats/L1TMuonPhase2/BuildFile.xml +++ b/DataFormats/L1TMuonPhase2/BuildFile.xml @@ -1,9 +1,10 @@ - + - + + diff --git a/DataFormats/L1TMuonPhase2/interface/EMTFHit.h b/DataFormats/L1TMuonPhase2/interface/EMTFHit.h new file mode 100644 index 0000000000000..3d7703ed9be5d --- /dev/null +++ b/DataFormats/L1TMuonPhase2/interface/EMTFHit.h @@ -0,0 +1,205 @@ +#ifndef DataFormats_L1TMuonPhase2_EMTFHit_h +#define DataFormats_L1TMuonPhase2_EMTFHit_h + +#include +#include + +#include "DataFormats/L1TMuon/interface/L1TMuonSubsystems.h" + +namespace l1t::phase2 { + + class EMTFHit { + public: + EMTFHit(); + ~EMTFHit() = default; + + // Setters + void setId(uint16_t aId) { id_ = aId; } + + void setRawDetId(uint32_t aRawDetId) { raw_det_id_ = aRawDetId; } + void setSubsystem(int16_t aSubsystem) { subsystem_ = aSubsystem; } + void setEndcap(int16_t aEndcap) { endcap_ = aEndcap; } + void setSector(int16_t aSector) { sector_ = aSector; } + void setSubsector(int16_t aSubsector) { subsector_ = aSubsector; } + void setStation(int16_t aStation) { station_ = aStation; } + void setRing(int16_t aRing) { ring_ = aRing; } + void setRoll(int16_t aRoll) { roll_ = aRoll; } + void setLayer(int16_t aLayer) { layer_ = aLayer; } + void setChamber(int16_t aChamber) { chamber_ = aChamber; } + + void setCscId(int16_t aCscid) { csc_id_ = aCscid; } + void setCscFR(int16_t aCscfr) { csc_fr_ = aCscfr; } + + void setStrip(int16_t aStrip) { strip_ = aStrip; } + void setStripLo(int16_t aStripLo) { strip_lo_ = aStripLo; } + void setStripHi(int16_t aStripHi) { strip_hi_ = aStripHi; } + void setStripQuart(int16_t aStripQuart) { strip_quart_ = aStripQuart; } // Run 3 + void setStripEighth(int16_t aStripEighth) { strip_eighth_ = aStripEighth; } // Run 3 + void setStripQuartBit(int16_t aStripQuartBit) { strip_quart_bit_ = aStripQuartBit; } // Run 3 + void setStripEighthBit(int16_t aStripEighthBit) { strip_eighth_bit_ = aStripEighthBit; } // Run 3 + + void setWire1(int16_t aWire1) { wire1_ = aWire1; } + void setWire2(int16_t aWire2) { wire2_ = aWire2; } + + void setBend(int16_t aBend) { bend_ = aBend; } + void setSlope(int16_t aSlope) { slope_ = aSlope; } + + void setBx(int16_t aBx) { bx_ = aBx; } + void setSubbx(int16_t aSubbx) { subbx_ = aSubbx; } + + void setQuality(int16_t aQuality) { quality_ = aQuality; } + void setPattern(int16_t aPattern) { pattern_ = aPattern; } + + void setGlobPhi(float aGlobPhi) { glob_phi_ = aGlobPhi; } + void setGlobTheta(float aGlobTheta) { glob_theta_ = aGlobTheta; } + void setGlobPerp(float aGlobPerp) { glob_perp_ = aGlobPerp; } + void setGlobZ(float aGlobZ) { glob_z_ = aGlobZ; } + void setGlobTime(float aGlobTime) { glob_time_ = aGlobTime; } + + void setEmtfChamber(int16_t aEmtfChamber) { emtf_chamber_ = aEmtfChamber; } + void setEmtfSegment(int16_t aEmtfSegment) { emtf_segment_ = aEmtfSegment; } + void setEmtfPhi(int16_t aEmtfPhi) { emtf_phi_ = aEmtfPhi; } + void setEmtfBend(int16_t aEmtfBend) { emtf_bend_ = aEmtfBend; } + void setEmtfTheta1(int16_t aEmtfTheta1) { emtf_theta1_ = aEmtfTheta1; } + void setEmtfTheta2(int16_t aEmtfTheta2) { emtf_theta2_ = aEmtfTheta2; } + void setEmtfQual1(int16_t aEmtfQual1) { emtf_qual1_ = aEmtfQual1; } + void setEmtfQual2(int16_t aEmtfQual2) { emtf_qual2_ = aEmtfQual2; } + void setEmtfTime(int16_t aEmtfTime) { emtf_time_ = aEmtfTime; } + void setEmtfSite(int16_t aEmtfSite) { emtf_site_ = aEmtfSite; } + void setEmtfHost(int16_t aEmtfHost) { emtf_host_ = aEmtfHost; } + void setEmtfZones(int16_t aEmtfZones) { emtf_zones_ = aEmtfZones; } + void setEmtfTimezones(int16_t aEmtfTimezones) { emtf_timezones_ = aEmtfTimezones; } + + void setFlagNeighbor(bool aNeighbor) { flag_neighbor_ = aNeighbor; } + void setFlagSubstitute(bool aSubstitute) { flag_substitute_ = aSubstitute; } + void setFlagValid(bool aValid) { flag_valid_ = aValid; } + + // Getters + uint16_t id() const { return id_; } + + uint32_t rawDetId() const { return raw_det_id_; } + int16_t subsystem() const { return subsystem_; } + int16_t endcap() const { return endcap_; } + int16_t sector() const { return sector_; } + int16_t subsector() const { return subsector_; } + int16_t station() const { return station_; } + int16_t ring() const { return ring_; } + int16_t roll() const { return roll_; } + int16_t layer() const { return layer_; } + int16_t chamber() const { return chamber_; } + + int16_t cscId() const { return csc_id_; } + int16_t cscFR() const { return csc_fr_; } + + int16_t strip() const { return strip_; } + int16_t stripLo() const { return strip_lo_; } + int16_t stripHi() const { return strip_hi_; } + int16_t stripQuart() const { return strip_quart_; } // Run 3 + int16_t stripEighth() const { return strip_eighth_; } // Run 3 + int16_t stripQuartBit() const { return strip_quart_bit_; } // Run 3 + int16_t stripEighthBit() const { return strip_eighth_bit_; } // Run 3 + + int16_t wire1() const { return wire1_; } + int16_t wire2() const { return wire2_; } + + int16_t bend() const { return bend_; } + int16_t slope() const { return slope_; } + + int16_t bx() const { return bx_; } + int16_t subbx() const { return subbx_; } + + int16_t quality() const { return quality_; } + int16_t pattern() const { return pattern_; } + + float globPhi() const { return glob_phi_; } + float globTheta() const { return glob_theta_; } + float globPerp() const { return glob_perp_; } + float globZ() const { return glob_z_; } + float globTime() const { return glob_time_; } + + int16_t emtfChamber() const { return emtf_chamber_; } + int16_t emtfSegment() const { return emtf_segment_; } + int16_t emtfPhi() const { return emtf_phi_; } + int16_t emtfBend() const { return emtf_bend_; } + int16_t emtfTheta1() const { return emtf_theta1_; } + int16_t emtfTheta2() const { return emtf_theta2_; } + int16_t emtfQual1() const { return emtf_qual1_; } + int16_t emtfQual2() const { return emtf_qual2_; } + int16_t emtfTime() const { return emtf_time_; } + int16_t emtfSite() const { return emtf_site_; } + int16_t emtfHost() const { return emtf_host_; } + int16_t emtfZones() const { return emtf_zones_; } + int16_t emtfTimezones() const { return emtf_timezones_; } + + bool flagNeighbor() const { return flag_neighbor_; } + bool flagSubstitute() const { return flag_substitute_; } + bool flagValid() const { return flag_valid_; } + + private: + uint16_t id_; + + uint32_t raw_det_id_; + int16_t subsystem_; + int16_t endcap_; + int16_t sector_; + int16_t subsector_; + int16_t station_; + int16_t ring_; + int16_t roll_; + int16_t layer_; + int16_t chamber_; + + int16_t csc_id_; + int16_t csc_fr_; // front/rear + + int16_t strip_; + int16_t strip_lo_; + int16_t strip_hi_; + int16_t strip_quart_; + int16_t strip_eighth_; + int16_t strip_quart_bit_; + int16_t strip_eighth_bit_; + + int16_t wire1_; + int16_t wire2_; + + int16_t bend_; + int16_t slope_; + + int16_t bx_; + int16_t subbx_; + + int16_t quality_; + int16_t pattern_; + + float glob_phi_; + float glob_theta_; + float glob_perp_; + float glob_z_; + float glob_time_; + + int16_t emtf_chamber_; + int16_t emtf_segment_; + int16_t emtf_phi_; + int16_t emtf_bend_; + int16_t emtf_slope_; + int16_t emtf_theta1_; + int16_t emtf_theta2_; + int16_t emtf_qual1_; + int16_t emtf_qual2_; + int16_t emtf_time_; + int16_t emtf_site_; + int16_t emtf_host_; + int16_t emtf_zones_; + int16_t emtf_timezones_; + + bool flag_neighbor_; + bool flag_substitute_; + bool flag_valid_; + }; + + typedef std::vector EMTFHitCollection; + +} // namespace l1t::phase2 + +#endif // DataFormats_L1TMuonPhase2_EMTFHit_h not defined diff --git a/DataFormats/L1TMuonPhase2/interface/EMTFInput.h b/DataFormats/L1TMuonPhase2/interface/EMTFInput.h new file mode 100644 index 0000000000000..f6f972c78949e --- /dev/null +++ b/DataFormats/L1TMuonPhase2/interface/EMTFInput.h @@ -0,0 +1,45 @@ +#ifndef DataFormats_L1TMuonPhase2_EMTFInput_h +#define DataFormats_L1TMuonPhase2_EMTFInput_h + +#include +#include + +#include "DataFormats/L1TMuon/interface/L1TMuonSubsystems.h" + +namespace l1t::phase2 { + + class EMTFInput { + public: + typedef std::vector hits_t; + typedef std::vector segs_t; + + EMTFInput() : endcap_(0), sector_(0), bx_(0), hits_{}, segs_{} {} + ~EMTFInput() = default; + + // Setters + void setEndcap(int16_t aEndcap) { endcap_ = aEndcap; } + void setSector(int16_t aSector) { sector_ = aSector; } + void setBx(int16_t aBx) { bx_ = aBx; } + void setHits(const hits_t& aHits) { hits_ = aHits; } + void setSegs(const segs_t& aSegs) { segs_ = aSegs; } + + // Getters + int16_t endcap() const { return endcap_; } + int16_t sector() const { return sector_; } + int16_t bx() const { return bx_; } + const hits_t& hits() const { return hits_; } + const segs_t& segs() const { return segs_; } + + private: + int16_t endcap_; + int16_t sector_; + int16_t bx_; + hits_t hits_; + segs_t segs_; + }; + + typedef std::vector EMTFInputCollection; + +} // namespace l1t::phase2 + +#endif // DataFormats_L1TMuonPhase2_EMTFInput_h not defined diff --git a/DataFormats/L1TMuonPhase2/interface/EMTFTrack.h b/DataFormats/L1TMuonPhase2/interface/EMTFTrack.h new file mode 100644 index 0000000000000..76ee00fc82324 --- /dev/null +++ b/DataFormats/L1TMuonPhase2/interface/EMTFTrack.h @@ -0,0 +1,115 @@ +#ifndef DataFormats_L1TMuonPhase2_EMTFTrack_h +#define DataFormats_L1TMuonPhase2_EMTFTrack_h + +#include +#include +#include + +namespace l1t::phase2 { + + class EMTFTrack { + public: + typedef std::vector features_t; + typedef std::vector site_hits_t; + typedef std::vector site_segs_t; + typedef std::vector site_mask_t; + + EMTFTrack(); + ~EMTFTrack() = default; + + // Setters + void setEndcap(int16_t aEndcap) { endcap_ = aEndcap; } + void setSector(int16_t aSector) { sector_ = aSector; } + void setBx(int16_t aBx) { bx_ = aBx; } + void setUnconstrained(bool aUnconstrained) { unconstrained_ = aUnconstrained; } + void setValid(bool aValid) { valid_ = aValid; } + + void setModelPtAddress(int16_t aAddress) { model_pt_address_ = aAddress; } + void setModelRelsAddress(int16_t aAddress) { model_rels_address_ = aAddress; } + void setModelDxyAddress(int16_t aAddress) { model_dxy_address_ = aAddress; } + void setModelPattern(int16_t aModelPattern) { model_pattern_ = aModelPattern; } + void setModelQual(int16_t aModelQual) { model_qual_ = aModelQual; } + void setModelPhi(int32_t aModelPhi) { model_phi_ = aModelPhi; } + void setModelEta(int32_t aModelEta) { model_eta_ = aModelEta; } + void setModelFeatures(const features_t& aModelFeatures) { model_features_ = aModelFeatures; } + + void setEmtfQ(int16_t aEmtfQ) { emtf_q_ = aEmtfQ; } + void setEmtfPt(int32_t aEmtfPt) { emtf_pt_ = aEmtfPt; } + void setEmtfRels(int32_t aEmtfRels) { emtf_rels_ = aEmtfRels; } + void setEmtfD0(int32_t aEmtfD0) { emtf_d0_ = aEmtfD0; } + void setEmtfZ0(int32_t aEmtfZ0) { emtf_z0_ = aEmtfZ0; } + void setEmtfBeta(int32_t aEmtfBeta) { emtf_beta_ = aEmtfBeta; } + void setEmtfModeV1(int16_t aEmtfModeV1) { emtf_mode_v1_ = aEmtfModeV1; } + void setEmtfModeV2(int16_t aEmtfModeV2) { emtf_mode_v2_ = aEmtfModeV2; } + + void setSiteHits(const site_hits_t& aSiteHits) { site_hits_ = aSiteHits; } + void setSiteSegs(const site_segs_t& aSiteSegs) { site_segs_ = aSiteSegs; } + void setSiteMask(const site_mask_t& aSiteMask) { site_mask_ = aSiteMask; } + void setSiteRMMask(const site_mask_t& aSiteMask) { site_rm_mask_ = aSiteMask; } + + // Getters + int16_t endcap() const { return endcap_; } + int16_t sector() const { return sector_; } + int16_t bx() const { return bx_; } + bool unconstrained() const { return unconstrained_; } + bool valid() const { return valid_; } + + int16_t modelPtAddress() const { return model_pt_address_; } + int16_t modelRelsAddress() const { return model_rels_address_; } + int16_t modelDxyAddress() const { return model_dxy_address_; } + int16_t modelPattern() const { return model_pattern_; } + int16_t modelQual() const { return model_qual_; } + int32_t modelPhi() const { return model_phi_; } + int32_t modelEta() const { return model_eta_; } + const features_t& modelFeatures() const { return model_features_; } + + int16_t emtfQ() const { return emtf_q_; } + int32_t emtfPt() const { return emtf_pt_; } + int32_t emtfRels() const { return emtf_rels_; } + int32_t emtfD0() const { return emtf_d0_; } + int32_t emtfZ0() const { return emtf_z0_; } + int32_t emtfBeta() const { return emtf_beta_; } + int16_t emtfModeV1() const { return emtf_mode_v1_; } + int16_t emtfModeV2() const { return emtf_mode_v2_; } + + const site_hits_t& siteHits() const { return site_hits_; } + const site_segs_t& siteSegs() const { return site_segs_; } + const site_mask_t& siteMask() const { return site_mask_; } + const site_mask_t& siteRMMask() const { return site_rm_mask_; } + + private: + int16_t endcap_; + int16_t sector_; + int16_t bx_; + bool unconstrained_; + bool valid_; + + int16_t model_pt_address_; + int16_t model_rels_address_; + int16_t model_dxy_address_; + int16_t model_pattern_; + int16_t model_qual_; + int32_t model_phi_; + int32_t model_eta_; + features_t model_features_; + + int16_t emtf_q_; + int32_t emtf_pt_; + int32_t emtf_rels_; + int32_t emtf_d0_; + int32_t emtf_z0_; + int32_t emtf_beta_; + int16_t emtf_mode_v1_; + int16_t emtf_mode_v2_; + + site_hits_t site_hits_; + site_segs_t site_segs_; + site_mask_t site_mask_; + site_mask_t site_rm_mask_; + }; + + typedef std::vector EMTFTrackCollection; + +} // namespace l1t::phase2 + +#endif // DataFormats_L1TMuonPhase2_EMTFTrack_h not defined diff --git a/DataFormats/L1TMuonPhase2/src/EMTFHit.cc b/DataFormats/L1TMuonPhase2/src/EMTFHit.cc new file mode 100644 index 0000000000000..966de1640a64d --- /dev/null +++ b/DataFormats/L1TMuonPhase2/src/EMTFHit.cc @@ -0,0 +1,64 @@ +#include "DataFormats/L1TMuonPhase2/interface/EMTFHit.h" + +using namespace l1t::phase2; + +EMTFHit::EMTFHit() + : id_(0), + + raw_det_id_(0), + subsystem_(0), + endcap_(0), + sector_(0), + subsector_(0), + station_(0), + ring_(0), + roll_(0), + layer_(0), + chamber_(0), + + csc_id_(0), + csc_fr_(0), + + strip_(0), + strip_lo_(0), + strip_hi_(0), + strip_quart_(0), // Run 3 + strip_eighth_(0), // Run 3 + strip_quart_bit_(0), // Run 3 + strip_eighth_bit_(0), // Run 3 + + wire1_(0), + wire2_(0), + + bx_(0), + subbx_(0), + + quality_(0), + pattern_(0), + + glob_phi_(0), + glob_theta_(0), + glob_perp_(0), + glob_z_(0), + glob_time_(0), + + emtf_chamber_(0), + emtf_segment_(0), + emtf_phi_(0), + emtf_bend_(0), + emtf_slope_(0), + emtf_theta1_(0), + emtf_theta2_(0), + emtf_qual1_(0), + emtf_qual2_(0), + emtf_time_(0), + emtf_site_(0), + emtf_host_(0), + emtf_zones_(0), + emtf_timezones_(0), + + flag_neighbor_(false), + flag_substitute_(false), + flag_valid_(false) { + // Do Nothing +} diff --git a/DataFormats/L1TMuonPhase2/src/EMTFInput.cc b/DataFormats/L1TMuonPhase2/src/EMTFInput.cc new file mode 100644 index 0000000000000..7ed9b912cb0fc --- /dev/null +++ b/DataFormats/L1TMuonPhase2/src/EMTFInput.cc @@ -0,0 +1,3 @@ +#include "DataFormats/L1TMuonPhase2/interface/EMTFInput.h" + +using namespace l1t::phase2; diff --git a/DataFormats/L1TMuonPhase2/src/EMTFTrack.cc b/DataFormats/L1TMuonPhase2/src/EMTFTrack.cc new file mode 100644 index 0000000000000..6cb65ec0207b0 --- /dev/null +++ b/DataFormats/L1TMuonPhase2/src/EMTFTrack.cc @@ -0,0 +1,30 @@ +#include "DataFormats/L1TMuonPhase2/interface/EMTFTrack.h" + +using namespace l1t::phase2; + +EMTFTrack::EMTFTrack() + : endcap_(0), + sector_(0), + bx_(0), + unconstrained_(false), + valid_(false), + model_pt_address_(0), + model_dxy_address_(0), + model_pattern_(0), + model_qual_(0), + model_phi_(0), + model_eta_(0), + model_features_{}, + emtf_q_(0), + emtf_pt_(0), + emtf_d0_(0), + emtf_z0_(0), + emtf_beta_(0), + emtf_mode_v1_(0), + emtf_mode_v2_(0), + site_hits_{}, + site_segs_{}, + site_mask_{}, + site_rm_mask_{} { + // Do Nothing +} diff --git a/DataFormats/L1TMuonPhase2/src/TrackerMuon.cc b/DataFormats/L1TMuonPhase2/src/TrackerMuon.cc index 7beba2607bba5..916eb797b8e8e 100644 --- a/DataFormats/L1TMuonPhase2/src/TrackerMuon.cc +++ b/DataFormats/L1TMuonPhase2/src/TrackerMuon.cc @@ -1,4 +1,3 @@ - #include "DataFormats/L1TMuonPhase2/interface/TrackerMuon.h" using namespace l1t; diff --git a/DataFormats/L1TMuonPhase2/src/classes.h b/DataFormats/L1TMuonPhase2/src/classes.h index c970357cc3958..2c0dd2a390149 100644 --- a/DataFormats/L1TMuonPhase2/src/classes.h +++ b/DataFormats/L1TMuonPhase2/src/classes.h @@ -1,6 +1,12 @@ #include "DataFormats/Common/interface/Wrapper.h" #include "DataFormats/Common/interface/RefToBase.h" + #include "DataFormats/L1TMuonPhase2/interface/MuonStub.h" #include "DataFormats/L1TMuonPhase2/interface/TrackerMuon.h" #include "DataFormats/L1TMuonPhase2/interface/SAMuon.h" + +#include "DataFormats/L1TMuonPhase2/interface/EMTFHit.h" +#include "DataFormats/L1TMuonPhase2/interface/EMTFTrack.h" +#include "DataFormats/L1TMuonPhase2/interface/EMTFInput.h" + #include diff --git a/DataFormats/L1TMuonPhase2/src/classes_def.xml b/DataFormats/L1TMuonPhase2/src/classes_def.xml index b3cbf00fcf430..23c286c1d736c 100644 --- a/DataFormats/L1TMuonPhase2/src/classes_def.xml +++ b/DataFormats/L1TMuonPhase2/src/classes_def.xml @@ -1,27 +1,42 @@ - + + + + + + + - - - - - - + + + + + + + + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + diff --git a/L1Trigger/L1TGEM/interface/GE0TriggerPseudoBuilder.h b/L1Trigger/L1TGEM/interface/GE0TriggerPseudoBuilder.h new file mode 100644 index 0000000000000..7ad1b985982c4 --- /dev/null +++ b/L1Trigger/L1TGEM/interface/GE0TriggerPseudoBuilder.h @@ -0,0 +1,63 @@ +#ifndef L1Trigger_L1TGEM_GE0TriggerPseudoBuilder_h +#define L1Trigger_L1TGEM_GE0TriggerPseudoBuilder_h + +/** \class GE0TriggerPseudoBuilder + * + * Builds GE0 trigger objects from GE0 segment + * + * \author Original ME0 code by Tao Huang (TAMU). Converted and updated to GE0 by Ian J. Watson (USeoul) + * + */ + +#include "DataFormats/GEMDigi/interface/ME0TriggerDigiCollection.h" +#include "DataFormats/GEMRecHit/interface/GEMSegmentCollection.h" +#include "DataFormats/GEMRecHit/interface/GEMSegment.h" +#include "DataFormats/GEMRecHit/interface/GEMRecHit.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" + +class GEMGeometry; + +class GE0TriggerPseudoBuilder { +public: + /** Configure the algorithm via constructor. + * Receives ParameterSet percolated down from + * EDProducer which owns this Builder. + */ + explicit GE0TriggerPseudoBuilder(const edm::ParameterSet&); + + ~GE0TriggerPseudoBuilder(); + + /** Build Triggers from ME0 segment in each chamber and fill them into output collections. */ + void build(const GEMSegmentCollection& me0segments, GE0TriggerDigiCollection& oc_trig); + + /** set geometry for the matching needs */ + void setME0Geometry(const GEMGeometry* g) { me0_g = g; } + + /* print all ME0 segments in the event */ + void dumpAllME0Segments(const GEMSegmentCollection& segments) const; + + /** Max values of trigger labels for all ME0s; + * used to construct TMB processors. + */ + enum class trig_me0s { MAX_ENDCAPS = 2, MAX_CHAMBERS = 18 }; + +private: + static const int min_endcap; + static const int max_endcap; + static const int min_chamber; + static const int max_chamber; + static const unsigned int ME0KeyLayer; + static const int ME0TriggerCentralBX; + + const GEMGeometry* me0_g; + + int info_; + + double dphiresolution_; //unit: trigger pad + + ME0TriggerDigi segmentConversion(const GEMSegment segment); + + edm::ParameterSet config_; +}; + +#endif diff --git a/L1Trigger/L1TGEM/plugins/GE0TriggerPseudoProducer.cc b/L1Trigger/L1TGEM/plugins/GE0TriggerPseudoProducer.cc new file mode 100644 index 0000000000000..56e47e4283eac --- /dev/null +++ b/L1Trigger/L1TGEM/plugins/GE0TriggerPseudoProducer.cc @@ -0,0 +1,74 @@ +/** \class GE0TriggerPseudoProducer + * + * Takes offline GE0 segment as input + * Produces GE0 trigger objects + * + * \author Original ME0 code by Tao Huang (TAMU). Converted and updated to GE0 by Ian J. Watson (USeoul) + * + */ + +#include "FWCore/Framework/interface/MakerMacros.h" +#include "FWCore/Framework/interface/ConsumesCollector.h" +#include "FWCore/Framework/interface/Frameworkfwd.h" +#include "FWCore/Framework/interface/global/EDProducer.h" +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/Utilities/interface/InputTag.h" +#include "FWCore/Utilities/interface/ESGetToken.h" +#include "FWCore/Framework/interface/ESHandle.h" +#include "FWCore/MessageLogger/interface/MessageLogger.h" +#include "L1Trigger/L1TGEM/interface/GE0TriggerPseudoBuilder.h" +#include "DataFormats/Common/interface/Handle.h" +#include "DataFormats/GEMDigi/interface/ME0TriggerDigiCollection.h" +#include "DataFormats/GEMRecHit/interface/GEMSegmentCollection.h" +#include "Geometry/Records/interface/MuonGeometryRecord.h" +#include "Geometry/GEMGeometry/interface/GEMGeometry.h" + +class GE0TriggerPseudoBuilder; + +class GE0TriggerPseudoProducer : public edm::global::EDProducer<> { +public: + explicit GE0TriggerPseudoProducer(const edm::ParameterSet&); + ~GE0TriggerPseudoProducer() override = default; + + void produce(edm::StreamID, edm::Event&, const edm::EventSetup&) const override; + +private: + edm::InputTag me0segmentProducer_; + edm::EDGetTokenT me0segment_token_; + edm::ESGetToken me0_geom_token_; + edm::ParameterSet config_; +}; + +GE0TriggerPseudoProducer::GE0TriggerPseudoProducer(const edm::ParameterSet& conf) + : me0segmentProducer_(conf.getParameter("ME0SegmentProducer")), + me0segment_token_(consumes(me0segmentProducer_)), + me0_geom_token_(esConsumes()), + config_(conf) { + // register what this produces + produces(); +} + +void GE0TriggerPseudoProducer::produce(edm::StreamID, edm::Event& ev, const edm::EventSetup& setup) const { + edm::ESHandle h_me0 = setup.getHandle(me0_geom_token_); + + edm::Handle me0Segmentcoll; + ev.getByToken(me0segment_token_, me0Segmentcoll); + const GEMSegmentCollection* me0segments = me0Segmentcoll.product(); + + // Create empty collection + auto oc_trig = std::make_unique(); + + auto trigBuilder = std::make_unique(config_); + trigBuilder->setME0Geometry(&*h_me0); + + // Fill output collections if valid input collection is available. + if (me0Segmentcoll.isValid()) { + trigBuilder->build(*me0segments, *oc_trig); + } + + // Put collections in event. + ev.put(std::move(oc_trig)); +} + +DEFINE_FWK_MODULE(GE0TriggerPseudoProducer); diff --git a/L1Trigger/L1TGEM/python/me0TriggerConvertedPseudoDigis_cfi.py b/L1Trigger/L1TGEM/python/me0TriggerConvertedPseudoDigis_cfi.py index 48113e3fe5121..74a941c879f2d 100644 --- a/L1Trigger/L1TGEM/python/me0TriggerConvertedPseudoDigis_cfi.py +++ b/L1Trigger/L1TGEM/python/me0TriggerConvertedPseudoDigis_cfi.py @@ -5,3 +5,9 @@ info = cms.untracked.int32(0), DeltaPhiResolution = cms.untracked.double(0.25)# in term of trigger pad ) + +ge0TriggerConvertedPseudoDigis = cms.EDProducer("GE0TriggerPseudoProducer", + ME0SegmentProducer = cms.InputTag("gemSegments"), + info = cms.untracked.int32(0), + DeltaPhiResolution = cms.untracked.double(0.25)# in term of trigger pad +) diff --git a/L1Trigger/L1TGEM/python/me0TriggerDigis_cff.py b/L1Trigger/L1TGEM/python/me0TriggerDigis_cff.py index 053cae23ea24c..57c7be6aefc64 100644 --- a/L1Trigger/L1TGEM/python/me0TriggerDigis_cff.py +++ b/L1Trigger/L1TGEM/python/me0TriggerDigis_cff.py @@ -7,6 +7,7 @@ me0TriggerRealDigiTask = cms.Task(simMuonME0PadDigis, me0TriggerDigis) me0TriggerAllDigiTask = cms.Task(me0TriggerRealDigiTask, me0TriggerPseudoDigiTask) +ge0TriggerAllDigiTask = cms.Task(ge0TriggerPseudoDigiTask) -## in scenarios with GE0, remove the pseudo digis -phase2_GE0.toReplaceWith(me0TriggerAllDigiTask, me0TriggerAllDigiTask.copyAndExclude([me0TriggerPseudoDigiTask])) +# in scenarios with GE0, remove the ME0 pseudo digis +phase2_GE0.toReplaceWith(me0TriggerAllDigiTask, ge0TriggerAllDigiTask) diff --git a/L1Trigger/L1TGEM/python/me0TriggerPseudoDigis_cff.py b/L1Trigger/L1TGEM/python/me0TriggerPseudoDigis_cff.py index ea60ea4d19600..6ed3a7b3a79fa 100644 --- a/L1Trigger/L1TGEM/python/me0TriggerPseudoDigis_cff.py +++ b/L1Trigger/L1TGEM/python/me0TriggerPseudoDigis_cff.py @@ -37,3 +37,16 @@ me0Segments, me0TriggerConvertedPseudoDigis ) + +from RecoLocalMuon.GEMRecHit.gemRecHits_cfi import * +from RecoLocalMuon.GEMSegment.gemSegments_cfi import * + +from Configuration.Eras.Modifier_phase2_GE0_cff import phase2_GE0 +phase2_GE0.toModify(gemRecHits, gemDigiLabel=cms.InputTag("simMuonGEMDigis")) + +ge0TriggerPseudoDigiTask = cms.Task( + ## need to run the standard GE0 RECO sequence for converted triggers + gemRecHits, + gemSegments, + ge0TriggerConvertedPseudoDigis +) diff --git a/L1Trigger/L1TGEM/src/GE0TriggerPseudoBuilder.cc b/L1Trigger/L1TGEM/src/GE0TriggerPseudoBuilder.cc new file mode 100644 index 0000000000000..2ffe8b658ebfd --- /dev/null +++ b/L1Trigger/L1TGEM/src/GE0TriggerPseudoBuilder.cc @@ -0,0 +1,166 @@ +#include "L1Trigger/L1TGEM/interface/GE0TriggerPseudoBuilder.h" +#include "FWCore/MessageLogger/interface/MessageLogger.h" +#include "Geometry/Records/interface/MuonGeometryRecord.h" +#include "Geometry/GEMGeometry/interface/GEMGeometry.h" + +#include +#include + +const unsigned int GE0TriggerPseudoBuilder::ME0KeyLayer = 3; +const int GE0TriggerPseudoBuilder::ME0TriggerCentralBX = 8; + +GE0TriggerPseudoBuilder::GE0TriggerPseudoBuilder(const edm::ParameterSet& conf) { + config_ = conf; + info_ = config_.getUntrackedParameter("info", 0); + dphiresolution_ = config_.getUntrackedParameter("DeltaPhiResolution", 0.25); +} + +GE0TriggerPseudoBuilder::~GE0TriggerPseudoBuilder() {} + +void GE0TriggerPseudoBuilder::build(const GEMSegmentCollection& me0Segments, GE0TriggerDigiCollection& oc_trig) { + if (info_ > 2) + dumpAllME0Segments(me0Segments); + + for (unsigned int endc = 0; endc < static_cast(trig_me0s::MAX_ENDCAPS); endc++) { + for (unsigned int cham = 0; cham < static_cast(trig_me0s::MAX_CHAMBERS); cham++) { + // 0th layer means whole chamber. + // chamber counts from 1 to 18 in ME0ID + const int region(endc == 0 ? -1 : 1); + // constexpr GEMDetId(int region, int ring, int station, int layer, int chamber, int ieta) + GEMDetId detid(region, 1, 0, 0, cham + 1, 0); + + const auto& drange = me0Segments.get(detid); + std::vector trigV; + for (auto digiIt = drange.first; digiIt != drange.second; digiIt++) { + if (info_ > 1) + LogTrace("L1ME0Trigger") << "GE0TriggerPseudoBuilder id " << detid << " ME0 segment " << *digiIt + << " to be converted into trigger digi\n"; + ME0TriggerDigi trig = segmentConversion(*digiIt); + if (trig.isValid()) + trigV.push_back(trig); + if (info_ > 1 and trig.isValid()) + LogTrace("L1ME0Trigger") << " ME0trigger " << trig << "\n"; + else if (info_ > 1) + LogTrace("L1ME0Trigger") << " ME0trigger is not valid. Conversion failed \n"; + } + + if (!trigV.empty()) { + LogTrace("L1ME0Trigger") << "GE0TriggerPseudoBuilder got results in " << detid << std::endl + << "Put " << trigV.size() << " Trigger digi" << ((trigV.size() > 1) ? "s " : " ") + << "in collection\n"; + oc_trig.put(std::make_pair(trigV.begin(), trigV.end()), detid); + } + } + } +} + +ME0TriggerDigi GE0TriggerPseudoBuilder::segmentConversion(const GEMSegment segment) { + auto detid = segment.gemDetId(); + const GEMSuperChamber* chamber = me0_g->superChamber(detid); + const GEMChamber* keylayer = chamber->chamber(GE0TriggerPseudoBuilder::ME0KeyLayer); + int chamberid = detid.superChamberId() % 2; + int totRolls = keylayer->nEtaPartitions(); + float dphi = chamber->computeDeltaPhi(segment.localPosition(), segment.localDirection()); + + int nrechits = segment.nRecHits(); + std::vector rolls; + for (const auto& rechit : segment.specificRecHits()) { + if (std::find(rolls.begin(), rolls.end(), rechit.gemId().roll()) == rolls.end()) + rolls.push_back(rechit.gemId().roll()); + } + if (rolls.size() > 2 or rolls.empty()) + LogTrace("L1ME0Trigger") << " ME0 segment is crossing " << rolls.size() << " roll !!! \n"; + //assert(rolls.size() <= 2); // we did found very few ME0 segments crossing 3 rolls!!! this cut is applied offline + if (rolls.empty()) + return ME0TriggerDigi(); + if (rolls[0] < 1) { + LogTrace("L1ME0Trigger") << " ME0 segment has wrong roll number " << rolls[0] << " which should be >= 1 \n !!!"; + throw edm::Exception(edm::errors::LogicError, "ME0 should have at least one roll"); + } + int partition = (rolls[0] - 1) << 1; //roll from detid counts from 1 + if (rolls.size() == 2 and rolls[0] > rolls[1]) + partition = partition - 1; + else if (rolls.size() == 2 and rolls[0] < rolls[1]) + partition = partition + 1; + + if (partition < 0 or partition >= 2 * totRolls) { + LogTrace("L1ME0Trigger") << " ME0 segment rolls size of all hits " << rolls.size() << " rolls[0] " << rolls[0] + << " rolls.back() " << rolls.back() << " and ME0 trigger roll is " << partition + << " max expected " << 2 * totRolls - 1 << "\n"; + return ME0TriggerDigi(); + } + + //globalpoint from ME0 segment + GlobalPoint gp = me0_g->idToDet(segment.gemDetId())->surface().toGlobal(segment.localPosition()); + const GEMEtaPartition* etapart = keylayer->etaPartition(rolls[0]); + LocalPoint segment_lp = etapart->surface().toLocal(gp); // convert segment gp into lp in etapartition coordinate + float strippitch = etapart->localPitch(segment_lp); + float strip = etapart->strip(segment_lp); + int totstrip = etapart->nstrips(); + int istrip = static_cast(strip); + int phiposition = istrip; + if (phiposition > totstrip) + LogTrace("L1ME0Trigger") << " ME0 segment strip number is " << phiposition << " larger than nstrip " << totstrip + << " !!! \n"; + constexpr float phi_resolution = 0.5; //halfstrip + int phiposition2 = (static_cast((strip - phiposition) / phi_resolution) & 1); // half-strip resolution + phiposition = (phiposition << 1) | phiposition2; + + //gloablpoint from ME0 trigger digi + float centreOfStrip = istrip + 0.25 + phiposition2 * 0.5; + GlobalPoint gp_digi = etapart->toGlobal(etapart->centreOfStrip(centreOfStrip)); + + float strippitch_rad = strippitch / gp.perp(); //unit in rad + + int idphi = static_cast(fabs(dphi) / (strippitch_rad * dphiresolution_)); + const int max_idphi = 512; + if (idphi >= max_idphi) { + LogTrace("L1ME0Trigger") << " ME0 segment dphi " << dphi << " and int type: " << idphi + << " larger than max allowed: " << max_idphi << " !!! \n"; + idphi = max_idphi - 1; + } + int quality = nrechits; // attention: not the same as discussed in meeting + // !!!!TODO!!!! int BX = (static_cast(fabs(time) / 25.0)) * sign_time + GE0TriggerPseudoBuilder::ME0TriggerCentralBX; + int BX = GE0TriggerPseudoBuilder::ME0TriggerCentralBX; + int bend = (dphi > 0.0) ? 0 : 1; + if (info_ > 2) + LogTrace("L1ME0Trigger") << " ME0trigger in conversion function:\n" + << "\t chamber(1-18) " << detid.chamber() << " chamber id " << chamberid << " \n" + << "\t rolls size of all hits " << rolls.size() << " rolls[0] " << rolls[0] + << " rolls.back() " << rolls.back() << " roll " << partition << " \n" + << "\t nRechits " << nrechits << " quality " << quality << " \n" + << "\t strip(float) " << strip << " (int) " << istrip << " phiposition " << phiposition + << " resolution (in term of strip) " << phi_resolution << " \n" + << "\t deltaphi(float) " << dphi << " (int) " << idphi << " resolution " + << strippitch_rad * dphiresolution_ << " bend " << bend << " \n" + << "\t global point eta " << gp.eta() << " phi " << gp.phi() << " trigger digi eta " + << gp_digi.eta() << " phi " << gp_digi.phi() << " \n" + // << "\t time (ns, float) " << time << " BX " << BX << " \n" + ; + + ME0TriggerDigi result = ME0TriggerDigi(chamberid, quality, phiposition, partition, idphi, bend, BX); + result.setStrip(istrip); + return result; + + return ME0TriggerDigi(); +} + +void GE0TriggerPseudoBuilder::dumpAllME0Segments(const GEMSegmentCollection& segments) const { + LogTrace("L1GE0Trigger") << "dumpt all ME0 Segments" << std::endl; + for (auto iC = segments.id_begin(); iC != segments.id_end(); ++iC) { + auto ch_segs = segments.get(*iC); + for (auto iS = ch_segs.first; iS != ch_segs.second; ++iS) { + if (iS->gemDetId().station() != 0) // only dump GE0 segments + continue; + GlobalPoint gp = me0_g->idToDet(iS->gemDetId())->surface().toGlobal(iS->localPosition()); + LogTrace("L1ME0Trigger") << "ME0Detid " << iS->gemDetId() << " segment " << *iS << " eta " << gp.eta() << " phi " + << gp.phi() << std::endl; + auto recHits(iS->recHits()); + LogTrace("L1GE0Trigger") << "\t has " << recHits.size() << " me0 rechits" << std::endl; + for (auto& rh : recHits) { + const GEMRecHit* me0rh(dynamic_cast(rh)); + LogTrace("L1GEMTrigger") << "\t detid " << me0rh->gemId() << " rechit " << *me0rh << std::endl; + } + } + } +} diff --git a/L1Trigger/L1TMuon/interface/MuonTriggerPrimitive.h b/L1Trigger/L1TMuon/interface/MuonTriggerPrimitive.h index 811d3010c99ac..026e00ef65349 100644 --- a/L1Trigger/L1TMuon/interface/MuonTriggerPrimitive.h +++ b/L1Trigger/L1TMuon/interface/MuonTriggerPrimitive.h @@ -222,6 +222,8 @@ namespace L1TMuon { // Constructor from ME0 data TriggerPrimitive(const ME0DetId& detid, const ME0TriggerDigi& digi); + // Constructor from GE0 data + TriggerPrimitive(const GEMDetId& detid, const ME0TriggerDigi& digi); // Copy constructor TriggerPrimitive(const TriggerPrimitive& tp); diff --git a/L1Trigger/L1TMuon/python/simDigis_cff.py b/L1Trigger/L1TMuon/python/simDigis_cff.py index 521660d4717fd..8d06f96353b58 100644 --- a/L1Trigger/L1TMuon/python/simDigis_cff.py +++ b/L1Trigger/L1TMuon/python/simDigis_cff.py @@ -123,10 +123,6 @@ _phase2_SimL1TMuonTask = SimL1TMuonTask.copy() _phase2_SimL1TMuonTask.add(me0TriggerAllDigiTask) _phase2_SimL1TMuonTask.add(simCscTriggerPrimitiveDigisPhase2) -_phase2_GE0_SimL1TMuonTask = SimL1TMuonTask.copyAndExclude([me0TriggerAllDigiTask]) from Configuration.Eras.Modifier_phase2_muon_cff import phase2_muon (stage2L1Trigger & phase2_muon).toReplaceWith( SimL1TMuonTask, _phase2_SimL1TMuonTask ) - -from Configuration.Eras.Modifier_phase2_GE0_cff import phase2_GE0 -(stage2L1Trigger & phase2_GE0).toReplaceWith( SimL1TMuonTask, _phase2_GE0_SimL1TMuonTask ) diff --git a/L1Trigger/L1TMuon/src/GeometryTranslator.cc b/L1Trigger/L1TMuon/src/GeometryTranslator.cc index bdab164708cbe..ed4408d194749 100644 --- a/L1Trigger/L1TMuon/src/GeometryTranslator.cc +++ b/L1Trigger/L1TMuon/src/GeometryTranslator.cc @@ -151,21 +151,49 @@ void GeometryTranslator::checkAndUpdateGeometry(const edm::EventSetup& es) { // _____________________________________________________________________________ // ME0 GlobalPoint GeometryTranslator::getME0SpecificPoint(const TriggerPrimitive& tp) const { - const ME0DetId id(tp.detId()); - const ME0Chamber* chamber = _geome0->chamber(id); - const ME0Layer* keylayer = chamber->layer(3); // ME0 key layer is layer 3 - int partition = tp.getME0Data().partition; // 'partition' is in half-roll unit - int iroll = (partition >> 1) + 1; - const ME0EtaPartition* roll = keylayer->etaPartition(iroll); - assert(roll != nullptr); // failed to get ME0 roll - // See L1Trigger/ME0Trigger/src/ME0TriggerPseudoBuilder.cc - int phiposition = tp.getME0Data().phiposition; // 'phiposition' is in half-strip unit - int istrip = (phiposition >> 1); - int phiposition2 = (phiposition & 0x1); - float centreOfStrip = istrip + 0.25 + phiposition2 * 0.5; - const LocalPoint& lp = roll->centreOfStrip(centreOfStrip); - const GlobalPoint& gp = roll->surface().toGlobal(lp); - return gp; + if (tp.detId().subdetId() == MuonSubdetId::GEM) { // GE0 + const GEMDetId id(tp.detId()); + const GEMSuperChamber* chamber = _geogem->superChamber(id); + const GEMChamber* keylayer = chamber->chamber(3); // GEM key layer is layer 3 + int partition = tp.getME0Data().partition; // 'partition' is in half-roll unit + int iroll = (partition >> 1) + 1; + const GEMEtaPartition* roll = keylayer->etaPartition(iroll); + + // failed to get ME0 roll + if (roll == nullptr) { + throw cms::Exception("Invalid GE0 Roll") << "Failed to get GEM roll for GE0" << std::endl; + } + + // See L1Trigger/ME0Trigger/src/ME0TriggerPseudoBuilder.cc + int phiposition = tp.getME0Data().phiposition; // 'phiposition' is in half-strip unit + int istrip = (phiposition >> 1); + int phiposition2 = (phiposition & 0x1); + float centreOfStrip = istrip + 0.25 + phiposition2 * 0.5; + const LocalPoint& lp = roll->centreOfStrip(centreOfStrip); + const GlobalPoint& gp = roll->surface().toGlobal(lp); + return gp; + } else { // ME0 + const ME0DetId id(tp.detId()); + const ME0Chamber* chamber = _geome0->chamber(id); + const ME0Layer* keylayer = chamber->layer(3); // ME0 key layer is layer 3 + int partition = tp.getME0Data().partition; // 'partition' is in half-roll unit + int iroll = (partition >> 1) + 1; + const ME0EtaPartition* roll = keylayer->etaPartition(iroll); + + // failed to get ME0 roll + if (roll == nullptr) { + throw cms::Exception("Invalid ME0 Roll") << "Failed to get ME0 roll" << std::endl; + } + + // See L1Trigger/ME0Trigger/src/ME0TriggerPseudoBuilder.cc + int phiposition = tp.getME0Data().phiposition; // 'phiposition' is in half-strip unit + int istrip = (phiposition >> 1); + int phiposition2 = (phiposition & 0x1); + float centreOfStrip = istrip + 0.25 + phiposition2 * 0.5; + const LocalPoint& lp = roll->centreOfStrip(centreOfStrip); + const GlobalPoint& gp = roll->surface().toGlobal(lp); + return gp; + } } double GeometryTranslator::calcME0SpecificEta(const TriggerPrimitive& tp) const { diff --git a/L1Trigger/L1TMuon/src/MuonTriggerPrimitive.cc b/L1Trigger/L1TMuon/src/MuonTriggerPrimitive.cc index 74eeee069ab7a..a1b4af2a9560b 100644 --- a/L1Trigger/L1TMuon/src/MuonTriggerPrimitive.cc +++ b/L1Trigger/L1TMuon/src/MuonTriggerPrimitive.cc @@ -251,6 +251,23 @@ TriggerPrimitive::TriggerPrimitive(const ME0DetId& detid, const ME0TriggerDigi& _me0.bx = digi.getBX(); } +// Constructor from GE0 data +TriggerPrimitive::TriggerPrimitive(const GEMDetId& detid, const ME0TriggerDigi& digi) + : _id(detid), _subsystem(L1TMuon::kME0) { + calculateGlobalSector(detid, _globalsector, _subsector); + _eta = 0.; + _phi = 0.; + _rho = 0.; + _theta = 0.; + _me0.chamberid = digi.getChamberid(); + _me0.quality = digi.getQuality(); + _me0.phiposition = digi.getPhiposition(); + _me0.partition = digi.getPartition(); + _me0.deltaphi = digi.getDeltaphi(); + _me0.bend = digi.getBend(); + _me0.bx = digi.getBX(); +} + // _____________________________________________________________________________ // Copy constructor TriggerPrimitive::TriggerPrimitive(const TriggerPrimitive& tp) @@ -478,7 +495,12 @@ void TriggerPrimitive::print(std::ostream& out) const { out << "Pad high : " << _gem.pad_hi << std::endl; break; case kME0: - out << detId() << std::endl; + if (detId().subdetId() == MuonSubdetId::ME0) { + out << detId() << std::endl; + } else { + out << detId() << std::endl; + } + out << "Local BX : " << _me0.bx << std::endl; out << "Chamber id : " << _me0.chamberid << std::endl; out << "Quality : " << _me0.quality << std::endl; diff --git a/L1Trigger/L1TMuonEndCapPhase2/BuildFile.xml b/L1Trigger/L1TMuonEndCapPhase2/BuildFile.xml new file mode 100644 index 0000000000000..8d0f1f91b4eab --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/BuildFile.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/L1Trigger/L1TMuonEndCapPhase2/interface/Algo/DuplicateRemovalLayer.h b/L1Trigger/L1TMuonEndCapPhase2/interface/Algo/DuplicateRemovalLayer.h new file mode 100644 index 0000000000000..fe2da30b5d02d --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/interface/Algo/DuplicateRemovalLayer.h @@ -0,0 +1,27 @@ +#ifndef L1Trigger_L1TMuonEndCapPhase2_DuplicateRemovalLayer_h +#define L1Trigger_L1TMuonEndCapPhase2_DuplicateRemovalLayer_h + +#include +#include + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFfwd.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFTypes.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFConstants.h" + +namespace emtf::phase2::algo { + + class DuplicateRemovalLayer { + public: + DuplicateRemovalLayer(const EMTFContext&); + + ~DuplicateRemovalLayer() = default; + + void apply(std::vector&) const; + + private: + const EMTFContext& context_; + }; + +} // namespace emtf::phase2::algo + +#endif // L1Trigger_L1TMuonEndCapPhase2_DuplicateRemovalLayer_h not defined diff --git a/L1Trigger/L1TMuonEndCapPhase2/interface/Algo/HitmapLayer.h b/L1Trigger/L1TMuonEndCapPhase2/interface/Algo/HitmapLayer.h new file mode 100644 index 0000000000000..d28c96d2ba556 --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/interface/Algo/HitmapLayer.h @@ -0,0 +1,23 @@ +#ifndef L1Trigger_L1TMuonEndCapPhase2_HitmapLayer_h +#define L1Trigger_L1TMuonEndCapPhase2_HitmapLayer_h + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFfwd.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFTypes.h" + +namespace emtf::phase2::algo { + + class HitmapLayer { + public: + HitmapLayer(const EMTFContext&); + + ~HitmapLayer() = default; + + void apply(const segment_collection_t&, std::vector&) const; + + private: + const EMTFContext& context_; + }; + +} // namespace emtf::phase2::algo + +#endif // L1Trigger_L1TMuonEndCapPhase2_HitmapLayer_h not defined diff --git a/L1Trigger/L1TMuonEndCapPhase2/interface/Algo/OutputLayer.h b/L1Trigger/L1TMuonEndCapPhase2/interface/Algo/OutputLayer.h new file mode 100644 index 0000000000000..41a025eac31eb --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/interface/Algo/OutputLayer.h @@ -0,0 +1,41 @@ +#ifndef L1Trigger_L1TMuonEndCapPhase2_OutputLayer_h +#define L1Trigger_L1TMuonEndCapPhase2_OutputLayer_h + +#include +#include + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFfwd.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFTypes.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFConstants.h" + +namespace emtf::phase2::algo { + + class OutputLayer { + public: + OutputLayer(const EMTFContext&); + + ~OutputLayer() = default; + + void apply(const int&, + const int&, + const int&, + const std::map&, + const std::vector&, + const bool&, + EMTFTrackCollection&) const; + + private: + const EMTFContext& context_; + + std::array prompt_pt_calibration_lut_; + std::array disp_pt_calibration_lut_; + std::array disp_dxy_calibration_lut_; + + int findEMTFModeV1(const track_t::site_mask_t&) const; + + int findEMTFModeV2(const track_t::site_mask_t&) const; + }; + +} // namespace emtf::phase2::algo + +#endif // L1Trigger_L1TMuonEndCapPhase2_OutputLayer_h not defined diff --git a/L1Trigger/L1TMuonEndCapPhase2/interface/Algo/ParameterAssignmentLayer.h b/L1Trigger/L1TMuonEndCapPhase2/interface/Algo/ParameterAssignmentLayer.h new file mode 100644 index 0000000000000..d603484098073 --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/interface/Algo/ParameterAssignmentLayer.h @@ -0,0 +1,27 @@ +#ifndef L1Trigger_L1TMuonEndCapPhase2_ParameterAssignment_h +#define L1Trigger_L1TMuonEndCapPhase2_ParameterAssignment_h + +#include +#include + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFfwd.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFTypes.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFConstants.h" + +namespace emtf::phase2::algo { + + class ParameterAssignmentLayer { + public: + ParameterAssignmentLayer(const EMTFContext&); + + ~ParameterAssignmentLayer() = default; + + void apply(const bool&, std::vector&) const; + + private: + const EMTFContext& context_; + }; + +} // namespace emtf::phase2::algo + +#endif // L1Trigger_L1TMuonEndCapPhase2_ParameterAssignment_h not defined diff --git a/L1Trigger/L1TMuonEndCapPhase2/interface/Algo/PatternMatchingLayer.h b/L1Trigger/L1TMuonEndCapPhase2/interface/Algo/PatternMatchingLayer.h new file mode 100644 index 0000000000000..cfcd5f0516419 --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/interface/Algo/PatternMatchingLayer.h @@ -0,0 +1,27 @@ +#ifndef L1Trigger_L1TMuonEndCapPhase2_PatternMatchingLayer_h +#define L1Trigger_L1TMuonEndCapPhase2_PatternMatchingLayer_h + +#include +#include + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFfwd.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFTypes.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFConstants.h" + +namespace emtf::phase2::algo { + + class PatternMatchingLayer { + public: + PatternMatchingLayer(const EMTFContext&); + + ~PatternMatchingLayer() = default; + + void apply(const std::vector&, const bool&, std::vector&) const; + + private: + const EMTFContext& context_; + }; + +} // namespace emtf::phase2::algo + +#endif // L1Trigger_L1TMuonEndCapPhase2_PatternMatchingLayer_h not defined diff --git a/L1Trigger/L1TMuonEndCapPhase2/interface/Algo/RoadSortingLayer.h b/L1Trigger/L1TMuonEndCapPhase2/interface/Algo/RoadSortingLayer.h new file mode 100644 index 0000000000000..6c90677b02828 --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/interface/Algo/RoadSortingLayer.h @@ -0,0 +1,27 @@ +#ifndef L1Trigger_L1TMuonEndCapPhase2_RoadSortingLayer_h +#define L1Trigger_L1TMuonEndCapPhase2_RoadSortingLayer_h + +#include +#include + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFfwd.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFTypes.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFConstants.h" + +namespace emtf::phase2::algo { + + class RoadSortingLayer { + public: + RoadSortingLayer(const EMTFContext&); + + ~RoadSortingLayer() = default; + + void apply(const unsigned int&, const std::vector&, std::vector&) const; + + private: + const EMTFContext& context_; + }; + +} // namespace emtf::phase2::algo + +#endif // L1Trigger_L1TMuonEndCapPhase2_RoadSortingLayer_h not defined diff --git a/L1Trigger/L1TMuonEndCapPhase2/interface/Algo/TrackBuildingLayer.h b/L1Trigger/L1TMuonEndCapPhase2/interface/Algo/TrackBuildingLayer.h new file mode 100644 index 0000000000000..9b7a510ccf389 --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/interface/Algo/TrackBuildingLayer.h @@ -0,0 +1,34 @@ +#ifndef L1Trigger_L1TMuonEndCapPhase2_TrackBuildingLayer_h +#define L1Trigger_L1TMuonEndCapPhase2_TrackBuildingLayer_h + +#include +#include + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFfwd.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFTypes.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFConstants.h" + +namespace emtf::phase2::algo { + + class TrackBuildingLayer { + // Static + private: + static seg_theta_t calc_theta_median(std::vector); + + // Members + public: + TrackBuildingLayer(const EMTFContext&); + + ~TrackBuildingLayer() = default; + + void apply(const segment_collection_t&, const std::vector&, const bool&, std::vector&) const; + + private: + const EMTFContext& context_; + + void attachSegments(const segment_collection_t&, const road_t&, const bool&, track_t&) const; + }; + +} // namespace emtf::phase2::algo + +#endif // L1Trigger_L1TMuonEndCapPhase2_TrackBuildingLayer_h not defined diff --git a/L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/CSCTPCollector.h b/L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/CSCTPCollector.h new file mode 100644 index 0000000000000..3b13b5f3b700c --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/CSCTPCollector.h @@ -0,0 +1,26 @@ +#ifndef L1Trigger_L1TMuonEndCapPhase2_CSCTPCollector_h +#define L1Trigger_L1TMuonEndCapPhase2_CSCTPCollector_h + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFfwd.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFTypes.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/TPCollectors.h" + +namespace emtf::phase2 { + + class CSCTPCollector : public TPCollector { + public: + explicit CSCTPCollector(const EMTFContext&, edm::ConsumesCollector&); + + ~CSCTPCollector() override = default; + + void collect(const edm::Event&, BXTPCMap&) const final; + + private: + const EMTFContext& context_; + + const edm::EDGetToken input_token_; + }; + +} // namespace emtf::phase2 + +#endif // L1Trigger_L1TMuonEndCapPhase2_CSCTPCollector_h diff --git a/L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/CSCTPConverter.h b/L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/CSCTPConverter.h new file mode 100644 index 0000000000000..d13448984a58a --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/CSCTPConverter.h @@ -0,0 +1,28 @@ +#ifndef L1Trigger_L1TMuonEndCapPhase2_CSCTPConverter_h +#define L1Trigger_L1TMuonEndCapPhase2_CSCTPConverter_h + +#include "DataFormats/MuonDetId/interface/CSCDetId.h" +#include "Geometry/CSCGeometry/interface/CSCGeometry.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFfwd.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFTypes.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/TPrimitives.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/TPConverters.h" + +namespace emtf::phase2 { + + class CSCTPConverter : public TPConverter { + public: + explicit CSCTPConverter(const EMTFContext&, const int&, const int&); + + ~CSCTPConverter() override = default; + + void convert(const TriggerPrimitive&, const TPInfo&, EMTFHit&) const final; + + private: + const EMTFContext& context_; + + int endcap_, sector_; + }; // namespace emtf::phase2 +} // namespace emtf::phase2 + +#endif // L1Trigger_L1TMuonEndCapPhase2_CSCTPConverter_h diff --git a/L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/CSCTPSelector.h b/L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/CSCTPSelector.h new file mode 100644 index 0000000000000..3f9121129bfff --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/CSCTPSelector.h @@ -0,0 +1,31 @@ +#ifndef L1Trigger_L1TMuonEndCapPhase2_CSCTPSelector_h +#define L1Trigger_L1TMuonEndCapPhase2_CSCTPSelector_h + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFfwd.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFTypes.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/TPrimitives.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/TPSelectors.h" + +namespace emtf::phase2 { + + class CSCTPSelector : public TPSelector { + public: + explicit CSCTPSelector(const EMTFContext&, const int&, const int&); + + ~CSCTPSelector() override = default; + + void select(const TriggerPrimitive&, TPInfo, ILinkTPCMap&) const final; + + private: + const EMTFContext& context_; + + int endcap_, sector_; + + int getInputLink(const TriggerPrimitive&, TPInfo&) const; + + int calcInputLink(const int&, const int&, const int&, const int&, const TPSelection&) const; + }; + +} // namespace emtf::phase2 + +#endif // L1Trigger_L1TMuonEndCapPhase2_CSCTPSelector_h diff --git a/L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/GE0TPCollector.h b/L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/GE0TPCollector.h new file mode 100644 index 0000000000000..2fddbcaa88b35 --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/GE0TPCollector.h @@ -0,0 +1,26 @@ +#ifndef L1Trigger_L1TMuonEndCapPhase2_GE0TPCollector_h +#define L1Trigger_L1TMuonEndCapPhase2_GE0TPCollector_h + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFfwd.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFTypes.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/TPCollectors.h" + +namespace emtf::phase2 { + + class GE0TPCollector : public TPCollector { + public: + explicit GE0TPCollector(const EMTFContext&, edm::ConsumesCollector&); + + ~GE0TPCollector() override = default; + + void collect(const edm::Event&, BXTPCMap&) const final; + + private: + const EMTFContext& context_; + + const edm::EDGetToken input_token_; + }; + +} // namespace emtf::phase2 + +#endif // L1Trigger_L1TMuonEndCapPhase2_GE0TPCollector_h diff --git a/L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/GE0TPConverter.h b/L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/GE0TPConverter.h new file mode 100644 index 0000000000000..843cd3687f007 --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/GE0TPConverter.h @@ -0,0 +1,27 @@ +#ifndef L1Trigger_L1TMuonEndCapPhase2_GE0TPConverter_h +#define L1Trigger_L1TMuonEndCapPhase2_GE0TPConverter_h + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFfwd.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFTypes.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/TPrimitives.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/TPConverters.h" + +namespace emtf::phase2 { + + class GE0TPConverter : public TPConverter { + public: + explicit GE0TPConverter(const EMTFContext&, const int&, const int&); + + ~GE0TPConverter() override = default; + + void convert(const TriggerPrimitive&, const TPInfo&, EMTFHit&) const final; + + private: + const EMTFContext& context_; + + int endcap_, sector_; + }; + +} // namespace emtf::phase2 + +#endif // L1Trigger_L1TMuonEndCapPhase2_GE0TPConverter_h diff --git a/L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/GE0TPSelector.h b/L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/GE0TPSelector.h new file mode 100644 index 0000000000000..48f2ea8963f3a --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/GE0TPSelector.h @@ -0,0 +1,31 @@ +#ifndef L1Trigger_L1TMuonEndCapPhase2_GE0TPSelector_h +#define L1Trigger_L1TMuonEndCapPhase2_GE0TPSelector_h + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFfwd.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFTypes.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/TPrimitives.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/TPSelectors.h" + +namespace emtf::phase2 { + + class GE0TPSelector : public TPSelector { + public: + explicit GE0TPSelector(const EMTFContext&, const int&, const int&); + + ~GE0TPSelector() override = default; + + void select(const TriggerPrimitive&, TPInfo, ILinkTPCMap&) const final; + + private: + const EMTFContext& context_; + + int endcap_, sector_; + + int getInputLink(const TriggerPrimitive&, TPInfo&) const; + + int calcInputLink(const int&, const int&, const TPSelection&) const; + }; + +} // namespace emtf::phase2 + +#endif // L1Trigger_L1TMuonEndCapPhase2_GE0TPSelector_h diff --git a/L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/GEMTPCollector.h b/L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/GEMTPCollector.h new file mode 100644 index 0000000000000..8715dec88a923 --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/GEMTPCollector.h @@ -0,0 +1,26 @@ +#ifndef L1Trigger_L1TMuonEndCapPhase2_GEMTPCollector_h +#define L1Trigger_L1TMuonEndCapPhase2_GEMTPCollector_h + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFfwd.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFTypes.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/TPCollectors.h" + +namespace emtf::phase2 { + + class GEMTPCollector : public TPCollector { + public: + explicit GEMTPCollector(const EMTFContext&, edm::ConsumesCollector&); + + ~GEMTPCollector() override = default; + + void collect(const edm::Event&, BXTPCMap&) const final; + + private: + const EMTFContext& context_; + + const edm::EDGetToken input_token_; + }; + +} // namespace emtf::phase2 + +#endif // L1Trigger_L1TMuonEndCapPhase2_GEMTPCollector_h diff --git a/L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/GEMTPConverter.h b/L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/GEMTPConverter.h new file mode 100644 index 0000000000000..4d2d82fce61b5 --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/GEMTPConverter.h @@ -0,0 +1,27 @@ +#ifndef L1Trigger_L1TMuonEndCapPhase2_GEMTPConverter_h +#define L1Trigger_L1TMuonEndCapPhase2_GEMTPConverter_h + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFfwd.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFTypes.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/TPrimitives.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/TPConverters.h" + +namespace emtf::phase2 { + + class GEMTPConverter : public TPConverter { + public: + explicit GEMTPConverter(const EMTFContext&, const int&, const int&); + + ~GEMTPConverter() override = default; + + void convert(const TriggerPrimitive&, const TPInfo&, EMTFHit&) const final; + + private: + const EMTFContext& context_; + + int endcap_, sector_; + }; + +} // namespace emtf::phase2 + +#endif // L1Trigger_L1TMuonEndCapPhase2_GEMTPConverter_h diff --git a/L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/GEMTPSelector.h b/L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/GEMTPSelector.h new file mode 100644 index 0000000000000..a054e6eb4705c --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/GEMTPSelector.h @@ -0,0 +1,31 @@ +#ifndef L1Trigger_L1TMuonEndCapPhase2_GEMTPSelector_h +#define L1Trigger_L1TMuonEndCapPhase2_GEMTPSelector_h + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFfwd.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFTypes.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/TPrimitives.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/TPSelectors.h" + +namespace emtf::phase2 { + + class GEMTPSelector : public TPSelector { + public: + explicit GEMTPSelector(const EMTFContext&, const int&, const int&); + + ~GEMTPSelector() override = default; + + void select(const TriggerPrimitive&, TPInfo, ILinkTPCMap&) const final; + + private: + const EMTFContext& context_; + + int endcap_, sector_; + + int getInputLink(const TriggerPrimitive&, TPInfo&) const; + + int calcInputLink(const int&, const int&, const int&, const int&, const TPSelection&) const; + }; + +} // namespace emtf::phase2 + +#endif // L1Trigger_L1TMuonEndCapPhase2_GEMTPSelector_h diff --git a/L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/ME0TPCollector.h b/L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/ME0TPCollector.h new file mode 100644 index 0000000000000..40f1e444949c8 --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/ME0TPCollector.h @@ -0,0 +1,26 @@ +#ifndef L1Trigger_L1TMuonEndCapPhase2_ME0TPCollector_h +#define L1Trigger_L1TMuonEndCapPhase2_ME0TPCollector_h + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFfwd.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFTypes.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/TPCollectors.h" + +namespace emtf::phase2 { + + class ME0TPCollector : public TPCollector { + public: + explicit ME0TPCollector(const EMTFContext&, edm::ConsumesCollector&); + + ~ME0TPCollector() override = default; + + void collect(const edm::Event&, BXTPCMap&) const final; + + private: + const EMTFContext& context_; + + const edm::EDGetToken input_token_; + }; + +} // namespace emtf::phase2 + +#endif // L1Trigger_L1TMuonEndCapPhase2_ME0TPCollector_h diff --git a/L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/ME0TPConverter.h b/L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/ME0TPConverter.h new file mode 100644 index 0000000000000..a45639b6b7740 --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/ME0TPConverter.h @@ -0,0 +1,27 @@ +#ifndef L1Trigger_L1TMuonEndCapPhase2_ME0TPConverter_h +#define L1Trigger_L1TMuonEndCapPhase2_ME0TPConverter_h + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFfwd.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFTypes.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/TPrimitives.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/TPConverters.h" + +namespace emtf::phase2 { + + class ME0TPConverter : public TPConverter { + public: + explicit ME0TPConverter(const EMTFContext&, const int&, const int&); + + ~ME0TPConverter() override = default; + + void convert(const TriggerPrimitive&, const TPInfo&, EMTFHit&) const final; + + private: + const EMTFContext& context_; + + int endcap_, sector_; + }; + +} // namespace emtf::phase2 + +#endif // L1Trigger_L1TMuonEndCapPhase2_ME0TPConverter_h diff --git a/L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/ME0TPSelector.h b/L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/ME0TPSelector.h new file mode 100644 index 0000000000000..bd61a132c836d --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/ME0TPSelector.h @@ -0,0 +1,31 @@ +#ifndef L1Trigger_L1TMuonEndCapPhase2_ME0TPSelector_h +#define L1Trigger_L1TMuonEndCapPhase2_ME0TPSelector_h + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFfwd.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFTypes.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/TPrimitives.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/TPSelectors.h" + +namespace emtf::phase2 { + + class ME0TPSelector : public TPSelector { + public: + explicit ME0TPSelector(const EMTFContext&, const int&, const int&); + + ~ME0TPSelector() override = default; + + void select(const TriggerPrimitive&, TPInfo, ILinkTPCMap&) const final; + + private: + const EMTFContext& context_; + + int endcap_, sector_; + + int getInputLink(const TriggerPrimitive&, TPInfo&) const; + + int calcInputLink(const int&, const int&, const TPSelection&) const; + }; + +} // namespace emtf::phase2 + +#endif // L1Trigger_L1TMuonEndCapPhase2_ME0TPSelector_h diff --git a/L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/RPCTPCollector.h b/L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/RPCTPCollector.h new file mode 100644 index 0000000000000..29c0ecea79dc8 --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/RPCTPCollector.h @@ -0,0 +1,26 @@ +#ifndef L1Trigger_L1TMuonEndCapPhase2_RPCTPCollector_h +#define L1Trigger_L1TMuonEndCapPhase2_RPCTPCollector_h + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFfwd.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFTypes.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/TPCollectors.h" + +namespace emtf::phase2 { + + class RPCTPCollector : public TPCollector { + public: + explicit RPCTPCollector(const EMTFContext&, edm::ConsumesCollector&); + + ~RPCTPCollector() override = default; + + void collect(const edm::Event&, BXTPCMap&) const final; + + private: + const EMTFContext& context_; + + const edm::EDGetToken input_token_; + }; + +} // namespace emtf::phase2 + +#endif // L1Trigger_L1TMuonEndCapPhase2_RPCTPCollector_h diff --git a/L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/RPCTPConverter.h b/L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/RPCTPConverter.h new file mode 100644 index 0000000000000..8416b249e06ea --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/RPCTPConverter.h @@ -0,0 +1,27 @@ +#ifndef L1Trigger_L1TMuonEndCapPhase2_RPCTPConverter_h +#define L1Trigger_L1TMuonEndCapPhase2_RPCTPConverter_h + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFfwd.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFTypes.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/TPrimitives.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/TPConverters.h" + +namespace emtf::phase2 { + + class RPCTPConverter : public TPConverter { + public: + explicit RPCTPConverter(const EMTFContext&, const int&, const int&); + + ~RPCTPConverter() override = default; + + void convert(const TriggerPrimitive&, const TPInfo&, EMTFHit&) const final; + + private: + const EMTFContext& context_; + + int endcap_, sector_; + }; + +} // namespace emtf::phase2 + +#endif // L1Trigger_L1TMuonEndCapPhase2_RPCTPConverter_h diff --git a/L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/RPCTPSelector.h b/L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/RPCTPSelector.h new file mode 100644 index 0000000000000..e72f3c771fe18 --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/RPCTPSelector.h @@ -0,0 +1,32 @@ +#ifndef L1Trigger_L1TMuonEndCapPhase2_RPCTPSelector_h +#define L1Trigger_L1TMuonEndCapPhase2_RPCTPSelector_h + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFfwd.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFTypes.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/TPrimitives.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/TPSelectors.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Utils/RPCUtils.h" + +namespace emtf::phase2 { + + class RPCTPSelector : public TPSelector { + public: + explicit RPCTPSelector(const EMTFContext&, const int&, const int&); + + ~RPCTPSelector() override = default; + + void select(const TriggerPrimitive&, TPInfo, ILinkTPCMap&) const final; + + private: + const EMTFContext& context_; + + int endcap_, sector_; + + int getInputLink(const TriggerPrimitive&, TPInfo&) const; + + int calcInputLink(const int&, const int&, const int&, const int&, const TPSelection&) const; + }; + +} // namespace emtf::phase2 + +#endif // L1Trigger_L1TMuonEndCapPhase2_RPCTPSelector_h diff --git a/L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/SubsystemTags.h b/L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/SubsystemTags.h new file mode 100644 index 0000000000000..691dd9c0f100c --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/SubsystemTags.h @@ -0,0 +1,97 @@ +#ifndef L1Trigger_L1TMuonEndCapPhase2_SubsystemTags_h +#define L1Trigger_L1TMuonEndCapPhase2_SubsystemTags_h + +#include "DataFormats/MuonDetId/interface/CSCDetId.h" +#include "DataFormats/MuonDetId/interface/RPCDetId.h" +#include "DataFormats/MuonDetId/interface/GEMDetId.h" +#include "DataFormats/MuonDetId/interface/ME0DetId.h" + +#include "DataFormats/L1DTTrackFinder/interface/L1MuDTChambPhDigi.h" +#include "DataFormats/L1DTTrackFinder/interface/L1MuDTChambPhContainer.h" +#include "DataFormats/L1DTTrackFinder/interface/L1MuDTChambThDigi.h" +#include "DataFormats/L1DTTrackFinder/interface/L1MuDTChambThContainer.h" +#include "DataFormats/CSCDigi/interface/CSCCorrelatedLCTDigi.h" +#include "DataFormats/CSCDigi/interface/CSCCorrelatedLCTDigiCollection.h" +#include "DataFormats/CSCDigi/interface/CSCComparatorDigi.h" +#include "DataFormats/CSCDigi/interface/CSCComparatorDigiCollection.h" +#include "DataFormats/RPCDigi/interface/RPCDigi.h" +#include "DataFormats/RPCDigi/interface/RPCDigiCollection.h" +#include "DataFormats/RPCRecHit/interface/RPCRecHit.h" +#include "DataFormats/RPCRecHit/interface/RPCRecHitCollection.h" +#include "DataFormats/L1TMuon/interface/CPPFDigi.h" +#include "DataFormats/GEMDigi/interface/GEMPadDigiCluster.h" +#include "DataFormats/GEMDigi/interface/GEMPadDigiClusterCollection.h" +#include "DataFormats/GEMDigi/interface/ME0TriggerDigi.h" +#include "DataFormats/GEMDigi/interface/ME0TriggerDigiCollection.h" + +// Forward declarations +class CSCGeometry; +class RPCGeometry; +class GEMGeometry; +class ME0Geometry; + +namespace emtf::phase2 { + + struct DTTag { + typedef L1MuDTChambPhDigi digi_type; + typedef L1MuDTChambPhContainer collection_type; + typedef L1MuDTChambThDigi theta_digi_type; + typedef L1MuDTChambThContainer theta_collection_type; + }; + + struct CSCTag { + typedef CSCDetId detid_type; + typedef CSCCorrelatedLCTDigi digi_type; + typedef CSCCorrelatedLCTDigiCollection collection_type; + typedef CSCComparatorDigi comparator_digi_type; + typedef CSCComparatorDigiCollection comparator_collection_type; + typedef CSCGeometry detgeom_type; + }; + + struct RPCTag { + typedef RPCDetId detid_type; + typedef RPCDigi digi_type; + typedef RPCDigiCollection collection_type; + typedef RPCRecHit rechit_type; + typedef RPCRecHitCollection rechit_collection_type; + typedef RPCGeometry detgeom_type; + }; + + struct IRPCTag { + typedef RPCDetId detid_type; + typedef RPCDigi digi_type; + typedef RPCDigiCollection collection_type; + typedef RPCRecHit rechit_type; + typedef RPCRecHitCollection rechit_collection_type; + typedef RPCGeometry detgeom_type; + }; + + struct CPPFTag { + typedef l1t::CPPFDigi digi_type; + typedef l1t::CPPFDigiCollection collection_type; + }; + + struct GEMTag { + typedef GEMDetId detid_type; + typedef GEMPadDigiCluster digi_type; + typedef GEMPadDigiClusterCollection collection_type; + typedef GEMGeometry detgeom_type; + }; + + struct ME0Tag { + typedef ME0DetId detid_type; + typedef ME0TriggerDigi digi_type; + typedef ME0TriggerDigiCollection collection_type; + typedef ME0Geometry detgeom_type; + }; + + struct GE0Tag { + typedef GEMDetId detid_type; + typedef ME0TriggerDigi digi_type; + typedef GE0TriggerDigiCollection collection_type; + typedef GEMGeometry detgeom_type; + }; + +} // namespace emtf::phase2 + +#endif // L1Trigger_L1TMuonEndCapPhase2_SubsystemTags_h diff --git a/L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/TPCollectors.h b/L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/TPCollectors.h new file mode 100644 index 0000000000000..e10e60df79a76 --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/TPCollectors.h @@ -0,0 +1,21 @@ +#ifndef L1Trigger_L1TMuonEndCapPhase2_TPCollectors_h +#define L1Trigger_L1TMuonEndCapPhase2_TPCollectors_h + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFfwd.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFTypes.h" + +namespace emtf::phase2 { + + class TPCollector { + public: + TPCollector() = default; + + virtual ~TPCollector() = default; + + // Collects all the trigger primitives in the event + virtual void collect(const edm::Event&, BXTPCMap&) const = 0; + }; + +} // namespace emtf::phase2 + +#endif // L1Trigger_L1TMuonEndCapPhase2_TPCollectors_h diff --git a/L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/TPConverters.h b/L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/TPConverters.h new file mode 100644 index 0000000000000..d5a67d7b8c97d --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/TPConverters.h @@ -0,0 +1,21 @@ +#ifndef L1Trigger_L1TMuonEndCapPhase2_TPConverters_h +#define L1Trigger_L1TMuonEndCapPhase2_TPConverters_h + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFfwd.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFTypes.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/TPrimitives.h" + +namespace emtf::phase2 { + + class TPConverter { + public: + TPConverter() = default; + + virtual ~TPConverter() = default; + + virtual void convert(const TriggerPrimitive&, const TPInfo&, EMTFHit&) const = 0; + }; + +} // namespace emtf::phase2 + +#endif // L1Trigger_L1TMuonEndCapPhase2_TPConverters_h diff --git a/L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/TPSelectors.h b/L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/TPSelectors.h new file mode 100644 index 0000000000000..488738af6231e --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/TPSelectors.h @@ -0,0 +1,20 @@ +#ifndef L1Trigger_L1TMuonEndCapPhase2_TPSelectors_h +#define L1Trigger_L1TMuonEndCapPhase2_TPSelectors_h + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFfwd.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFTypes.h" + +namespace emtf::phase2 { + + class TPSelector { + public: + TPSelector() = default; + + virtual ~TPSelector() = default; + + virtual void select(const TriggerPrimitive& tp, TPInfo tp_info, ILinkTPCMap&) const = 0; + }; + +} // namespace emtf::phase2 + +#endif // L1Trigger_L1TMuonEndCapPhase2_TPSelectors_h diff --git a/L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/TPrimitives.h b/L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/TPrimitives.h new file mode 100644 index 0000000000000..e7c0d2ff20534 --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/TPrimitives.h @@ -0,0 +1,66 @@ +#ifndef L1Trigger_L1TMuonEndCapPhase2_TPrimitives_h +#define L1Trigger_L1TMuonEndCapPhase2_TPrimitives_h + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFfwd.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFTypes.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Utils/CSCUtils.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Utils/RPCUtils.h" + +namespace emtf::phase2 { + + enum TPSelection { kNative, kNeighbor, kNone }; + + struct TPInfo { + // Id + int hit_id = -1; + int segment_id = -1; + + // Selection + int bx = -999; + int ilink = -1; + TPSelection selection = kNone; + + // Flags + bool flag_substitute = false; + + // Detector + int endcap = 0; + int endcap_pm = 0; + int sector = 0; + int subsector = 0; + int station = 0; + int ring = 0; + int roll = 0; + int layer = 0; + int chamber = 0; + + // CSC + int csc_id = -1; + csc::Facing csc_facing = csc::Facing::kNone; + int csc_first_wire = -1; + int csc_second_wire = -1; + + // RPC + rpc::Type rpc_type = rpc::kNone; + }; + + class TPEntry { + public: + TPEntry(const TPEntry&); + TPEntry(const TriggerPrimitive&); + TPEntry(const TriggerPrimitive&, const TPInfo&); + TPEntry(const CSCDetId&, const CSCCorrelatedLCTDigi&); + TPEntry(const RPCDetId&, const RPCRecHit&); + TPEntry(const GEMDetId&, const GEMPadDigiCluster&); + TPEntry(const ME0DetId&, const ME0TriggerDigi&); + TPEntry(const GEMDetId&, const ME0TriggerDigi&); + + ~TPEntry(); + + TriggerPrimitive tp_; + TPInfo info_; + }; + +} // namespace emtf::phase2 + +#endif // L1Trigger_L1TMuonEndCapPhase2_TPrimitives_h not defined diff --git a/L1Trigger/L1TMuonEndCapPhase2/interface/Data/ActivationLut.h b/L1Trigger/L1TMuonEndCapPhase2/interface/Data/ActivationLut.h new file mode 100644 index 0000000000000..8c4dfc44846b3 --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/interface/Data/ActivationLut.h @@ -0,0 +1,36 @@ +#ifndef L1Trigger_L1TMuonEndCapPhase2_ActivationLut_h +#define L1Trigger_L1TMuonEndCapPhase2_ActivationLut_h + +#include + +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/EventSetup.h" + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFfwd.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFTypes.h" + +namespace emtf::phase2::data { + + class ActivationLut { + public: + ActivationLut(); + + ~ActivationLut(); + + void update(const edm::Event&, const edm::EventSetup&); + + const trk_pt_t& lookupPromptPt(const trk_nn_address_t&) const; + const trk_pt_t& lookupDispPt(const trk_nn_address_t&) const; + const trk_rels_t& lookupRels(const trk_nn_address_t&) const; + const trk_dxy_t& lookupDxy(const trk_nn_address_t&) const; + + private: + std::vector prompt_pt_lut_; + std::vector disp_pt_lut_; + std::vector rels_lut_; + std::vector dxy_lut_; + }; + +} // namespace emtf::phase2::data + +#endif // L1Trigger_L1TMuonEndCapPhase2_ActivationLut_h diff --git a/L1Trigger/L1TMuonEndCapPhase2/interface/Data/HostLut.h b/L1Trigger/L1TMuonEndCapPhase2/interface/Data/HostLut.h new file mode 100644 index 0000000000000..43fd857970782 --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/interface/Data/HostLut.h @@ -0,0 +1,35 @@ +#ifndef L1Trigger_L1TMuonEndCapPhase2_HostLut_h +#define L1Trigger_L1TMuonEndCapPhase2_HostLut_h + +#include +#include + +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/EventSetup.h" + +namespace emtf::phase2::data { + + class HostLut { + // Static + public: + static const int kInvalid; + + // Member + public: + HostLut(); + + ~HostLut(); + + void update(const edm::Event&, const edm::EventSetup&); + + const int& lookup(const std::tuple&) const; + + private: + // Key: Subsystem, Station, Ring + // Value: Host + std::map, int> lut_; + }; + +} // namespace emtf::phase2::data + +#endif // L1Trigger_L1TMuonEndCapPhase2_HostLut_h diff --git a/L1Trigger/L1TMuonEndCapPhase2/interface/Data/SiteLut.h b/L1Trigger/L1TMuonEndCapPhase2/interface/Data/SiteLut.h new file mode 100644 index 0000000000000..5d5962d72254f --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/interface/Data/SiteLut.h @@ -0,0 +1,36 @@ + +#ifndef L1Trigger_L1TMuonEndCapPhase2_SiteLut_h +#define L1Trigger_L1TMuonEndCapPhase2_SiteLut_h + +#include +#include + +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/EventSetup.h" + +namespace emtf::phase2::data { + + class SiteLut { + // Static + public: + static const int kInvalid; + + // Member + public: + SiteLut(); + + ~SiteLut(); + + void update(const edm::Event&, const edm::EventSetup&); + + const int& lookup(const std::tuple&) const; + + private: + // Key: Subsystem, Station, Ring + // Value: Site + std::map, int> lut_; + }; + +} // namespace emtf::phase2::data + +#endif // L1Trigger_L1TMuonEndCapPhase2_SiteLut_h diff --git a/L1Trigger/L1TMuonEndCapPhase2/interface/Data/TimeZoneLut.h b/L1Trigger/L1TMuonEndCapPhase2/interface/Data/TimeZoneLut.h new file mode 100644 index 0000000000000..8a309ba053228 --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/interface/Data/TimeZoneLut.h @@ -0,0 +1,35 @@ +#ifndef L1Trigger_L1TMuonEndCapPhase2_TimeZoneLut_h +#define L1Trigger_L1TMuonEndCapPhase2_TimeZoneLut_h + +#include +#include + +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/EventSetup.h" + +namespace emtf::phase2::data { + + class TimeZoneLut { + // Static + public: + bool in_range(const std::pair&, const int&) const; + + // Member + public: + TimeZoneLut(); + + ~TimeZoneLut(); + + void update(const edm::Event&, const edm::EventSetup&); + + int getTimezones(const int&, const int&) const; + + private: + // Key: Host + // Value: BX Range + std::map> lut_; + }; + +} // namespace emtf::phase2::data + +#endif // L1Trigger_L1TMuonEndCapPhase2_TimeZoneLut_h diff --git a/L1Trigger/L1TMuonEndCapPhase2/interface/Data/ZoneLut.h b/L1Trigger/L1TMuonEndCapPhase2/interface/Data/ZoneLut.h new file mode 100644 index 0000000000000..6bbc032b09585 --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/interface/Data/ZoneLut.h @@ -0,0 +1,52 @@ +#ifndef L1Trigger_L1TMuonEndCapPhase2_ZoneLut_h +#define L1Trigger_L1TMuonEndCapPhase2_ZoneLut_h + +#include +#include + +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/EventSetup.h" + +namespace emtf::phase2::data { + + // Forward declarations + class Zone; + + // Classes + class ZoneLut { + public: + ZoneLut(); + + ~ZoneLut(); + + void update(const edm::Event&, const edm::EventSetup&); + + int getZones(const int&, const int&) const; + + int getZones(const int&, const int&, const int&) const; + + private: + std::vector zones_; + }; + + class Zone { + friend ZoneLut; + + public: + Zone() = default; + + ~Zone() = default; + + bool contains(const int&, const int&) const; + + bool contains(const int&, const int&, const int&) const; + + private: + // Key: Host + // Value: Theta Range + std::map> lut_; + }; + +} // namespace emtf::phase2::data + +#endif // L1Trigger_L1TMuonEndCapPhase2_ZoneLut_h diff --git a/L1Trigger/L1TMuonEndCapPhase2/interface/EMTFConfiguration.h b/L1Trigger/L1TMuonEndCapPhase2/interface/EMTFConfiguration.h new file mode 100644 index 0000000000000..70504aed4faa2 --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/interface/EMTFConfiguration.h @@ -0,0 +1,57 @@ +#ifndef L1Trigger_L1TMuonEndCapPhase2_EMTFConfiguration_h +#define L1Trigger_L1TMuonEndCapPhase2_EMTFConfiguration_h + +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFfwd.h" + +namespace emtf::phase2 { + + // Class + class EMTFConfiguration { + public: + EMTFConfiguration(const edm::ParameterSet&); + + ~EMTFConfiguration(); + + // Event configuration + void update(const edm::Event&, const edm::EventSetup&); + + // Config + int verbosity_; + + // Validation + std::string validation_dir_; + + // Neural Network + std::string prompt_graph_path_; + std::string displ_graph_path_; + + // Trigger + int min_bx_; + int max_bx_; + int bx_window_; + + // Subsystems + bool csc_en_; + bool rpc_en_; + bool gem_en_; + bool me0_en_; + bool ge0_en_; + + int csc_bx_shift_; + int rpc_bx_shift_; + int gem_bx_shift_; + int me0_bx_shift_; + + edm::InputTag csc_input_; + edm::InputTag rpc_input_; + edm::InputTag gem_input_; + edm::InputTag me0_input_; + edm::InputTag ge0_input_; + + // Primitive Selectoin + bool include_neighbor_en_; + }; +} // namespace emtf::phase2 + +#endif // L1Trigger_L1TMuonEndCapPhase2_EMTFConfiguration_h not defined diff --git a/L1Trigger/L1TMuonEndCapPhase2/interface/EMTFConstants.h b/L1Trigger/L1TMuonEndCapPhase2/interface/EMTFConstants.h new file mode 100644 index 0000000000000..d77cca5440775 --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/interface/EMTFConstants.h @@ -0,0 +1,62 @@ +#ifndef L1Trigger_L1TMuonEndCapPhase2_EMTFConstants_h +#define L1Trigger_L1TMuonEndCapPhase2_EMTFConstants_h + +namespace emtf::phase2 { + // from DataFormats/MuonDetId/interface/CSCDetId.h + constexpr int kMinEndcap = 1; + constexpr int kMaxEndcap = 2; + constexpr int kMinStation = 1; + constexpr int kMaxStation = 4; + constexpr int kMinRing = 1; + constexpr int kMaxRing = 4; + constexpr int kMinChamber = 1; + constexpr int kMaxChamber = 36; + constexpr int kMinLayer = 1; + constexpr int kMaxLayer = 6; + + // from DataFormats/MuonDetId/interface/CSCTriggerNumbering.h + constexpr int kMinCSCId = 1; + constexpr int kMaxCSCId = 9; + constexpr int kMinTrigSector = 1; + constexpr int kMaxTrigSector = 6; + constexpr int kNumTrigSector = 12; + constexpr int kMinTrigSubsector = 0; + constexpr int kMaxTrigSubsector = 2; + + // Algorithm + namespace v3 { + constexpr int kNumChambers = 115; // per sector + constexpr int kChamberSegments = 2; // per chamber + constexpr int kNumSegments = kNumChambers * kChamberSegments; + constexpr int kNumSegmentVariables = 13; // per segment + + constexpr int kNumZones = 3; // per sector + constexpr int kNumZonePatterns = 7; // per zone + + constexpr int kNumTimeZones = 3; // per sector + + constexpr int kNumTracks = 4; // per sector + constexpr int kNumTrackVariables = 54; // per track + constexpr int kNumTrackFeatures = 40; // per track + constexpr int kNumTrackPredictions = 1; // per track + constexpr int kNumTrackSites = 12; // per track + constexpr int kNumTrackSitesRM = 5; // per track + + constexpr int kChamberHitmapBW = 90; // 24 deg + constexpr int kChamberHitmapJoinedBW = 315; // 84 deg + constexpr int kHitmapNRows = 8; + constexpr int kHitmapNCols = 288; + constexpr int kHitmapNGates = 3; + constexpr int kHitmapColFactor = 16; + constexpr int kHitmapColFactorLog2 = 4; // (1 << 4) = 16 + constexpr int kHitmapCropColStart = kChamberHitmapJoinedBW - kHitmapNCols; // 27 (Inclusive) + constexpr int kHitmapCropColStop = kChamberHitmapJoinedBW; // 315 (Exclusive) + + constexpr int kPatternNCols = 110; + constexpr int kPatternMatchingPadding = 55; + constexpr int kMaxPatternActivation = 63; + constexpr int kMaxPatternActivationLog2 = 6; // (1 << 6) - 1 = 63 + } // namespace v3 +} // namespace emtf::phase2 + +#endif // L1Trigger_L1TMuonEndCapPhase2_EMTFConstants_h diff --git a/L1Trigger/L1TMuonEndCapPhase2/interface/EMTFContext.h b/L1Trigger/L1TMuonEndCapPhase2/interface/EMTFContext.h new file mode 100644 index 0000000000000..c45b2c528b2e7 --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/interface/EMTFContext.h @@ -0,0 +1,69 @@ +#ifndef L1Trigger_L1TMuonEndCapPhase2_EMTFContext_h +#define L1Trigger_L1TMuonEndCapPhase2_EMTFContext_h + +#include "PhysicsTools/TensorFlow/interface/TensorFlow.h" + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFfwd.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFConfiguration.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFModel.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFTypes.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Algo/HitmapLayer.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Algo/PatternMatchingLayer.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Algo/RoadSortingLayer.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Algo/TrackBuildingLayer.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Algo/DuplicateRemovalLayer.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Algo/ParameterAssignmentLayer.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Algo/OutputLayer.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Data/ActivationLut.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Data/HostLut.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Data/SiteLut.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Data/ZoneLut.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Data/TimeZoneLut.h" + +namespace emtf::phase2 { + + // Class + class EMTFContext { + public: + EMTFContext(const edm::ParameterSet&, edm::ConsumesCollector); + + ~EMTFContext(); + + // Event configuration + void update(const edm::Event&, const edm::EventSetup&); + + // Helpers + GeometryTranslator geometry_translator_; + + // EMTF + EMTFConfiguration config_; + EMTFModel model_; + + // Prompt Neural Network + tensorflow::GraphDef* prompt_graph_ptr_; + tensorflow::Session* prompt_session_ptr_; + + // Displaced Neural Network + tensorflow::GraphDef* disp_graph_ptr_; + tensorflow::Session* disp_session_ptr_; + + // Data + data::SiteLut site_lut_; + data::HostLut host_lut_; + data::ZoneLut zone_lut_; + data::TimeZoneLut timezone_lut_; + data::ActivationLut activation_lut_; + + // Algorithm + algo::HitmapLayer hitmap_building_layer_; + algo::PatternMatchingLayer pattern_matching_layer_; + algo::RoadSortingLayer road_sorting_layer_; + algo::TrackBuildingLayer track_building_layer_; + algo::DuplicateRemovalLayer duplicate_removal_layer_; + algo::ParameterAssignmentLayer parameter_assignment_layer_; + algo::OutputLayer output_layer_; + }; + +} // namespace emtf::phase2 + +#endif // L1Trigger_L1TMuonEndCapPhase2_EMTFContext_h not defined diff --git a/L1Trigger/L1TMuonEndCapPhase2/interface/EMTFModel.h b/L1Trigger/L1TMuonEndCapPhase2/interface/EMTFModel.h new file mode 100644 index 0000000000000..cef879daa770a --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/interface/EMTFModel.h @@ -0,0 +1,124 @@ +#ifndef L1Trigger_L1TMuonEndCapPhase2_EMTFModel_h +#define L1Trigger_L1TMuonEndCapPhase2_EMTFModel_h + +#include +#include + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFfwd.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFTypes.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFConstants.h" + +namespace emtf::phase2 { + + // Forward Declarations + namespace model { + namespace zones { + namespace hitmap { + struct chamber_t; + struct site_t; + typedef std::vector row_t; + } // namespace hitmap + + namespace pattern { + struct row_t; + } + + typedef std::vector hitmap_t; + typedef std::vector pattern_t; + typedef std::vector quality_lut_t; + } // namespace zones + + namespace theta_medians { + struct site_t; + typedef std::vector group_t; + } // namespace theta_medians + + namespace reduced_sites { + struct reduced_site_t; + } + + struct zone_t; + struct feature_t; + + typedef std::vector theta_median_t; + typedef std::vector reduced_sites_t; + } // namespace model + + // Definitions + class EMTFModel { + public: + EMTFModel(const EMTFContext&); + + ~EMTFModel(); + + std::vector zones_; + std::vector features_; + std::vector theta_medians_; + model::reduced_sites_t reduced_sites_; + + private: + const EMTFContext& context_; + }; + + namespace model { + // Define Zone Structs + struct zone_t { + zones::hitmap_t hitmap; + + // Prompt + std::vector prompt_patterns; + zones::quality_lut_t prompt_quality_lut; + + // Displaced + std::vector disp_patterns; + zones::quality_lut_t disp_quality_lut; + }; + + namespace zones { + namespace hitmap { + struct site_t { + site_id_t id; + std::vector chambers; + }; + + struct chamber_t { + unsigned int id; + unsigned int begin; + unsigned int end; + }; + } // namespace hitmap + + namespace pattern { + struct row_t { + unsigned int begin; + unsigned int center; + unsigned int end; + }; + } // namespace pattern + } // namespace zones + + // Define Feature Structs + struct feature_t { + feature_id_t id; + std::vector sites; + }; + + // Define Theta Median Structs + namespace theta_medians { + struct site_t { + site_id_t id; + theta_id_t theta_id; + }; + } // namespace theta_medians + + // Define Reduced Site Structs + namespace reduced_sites { + struct reduced_site_t { + reduced_site_id_t id; + std::vector trk_sites; + }; + } // namespace reduced_sites + } // namespace model +} // namespace emtf::phase2 + +#endif // L1Trigger_L1TMuonEndCapPhase2_EMTFModel_h not defined diff --git a/L1Trigger/L1TMuonEndCapPhase2/interface/EMTFTypes.h b/L1Trigger/L1TMuonEndCapPhase2/interface/EMTFTypes.h new file mode 100644 index 0000000000000..5c562146c4f4c --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/interface/EMTFTypes.h @@ -0,0 +1,178 @@ +#ifndef L1Trigger_L1TMuonEndCapPhase2_EMTFTypes_h +#define L1Trigger_L1TMuonEndCapPhase2_EMTFTypes_h + +#include +#include + +#include "ap_int.h" +#include "ap_fixed.h" +#include "DataFormats/L1TMuonPhase2/interface/EMTFHit.h" +#include "DataFormats/L1TMuonPhase2/interface/EMTFTrack.h" +#include "DataFormats/L1TMuonPhase2/interface/EMTFInput.h" +#include "L1Trigger/L1TMuon/interface/GeometryTranslator.h" +#include "L1Trigger/L1TMuon/interface/MuonTriggerPrimitive.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFfwd.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFConstants.h" + +namespace emtf::phase2 { + + // Trigger Primitives + typedef L1TMuon::TriggerPrimitive TriggerPrimitive; + typedef std::vector TPCollection; + typedef std::map BXTPCMap; + typedef std::map ILinkTPCMap; + + // Hits + typedef l1t::phase2::EMTFHit EMTFHit; + typedef l1t::phase2::EMTFHitCollection EMTFHitCollection; + + // Tracks + typedef l1t::phase2::EMTFTrack EMTFTrack; + typedef l1t::phase2::EMTFTrackCollection EMTFTrackCollection; + + // Inputs + typedef l1t::phase2::EMTFInput EMTFInput; + typedef l1t::phase2::EMTFInputCollection EMTFInputCollection; + + // General + typedef ap_uint<1> flag_t; + + // Segments + enum class site_id_t { + kME11 = 0, + kME12 = 1, + kME2 = 2, + kME3 = 3, + kME4 = 4, + kRE1 = 5, + kRE2 = 6, + kRE3 = 7, + kRE4 = 8, + kGE11 = 9, + kGE21 = 10, + kME0 = 11, + size, + begin = 0, + end = size + }; + + enum class feature_id_t { kPhi = 0, kTheta = 1, kBend = 2, kQuality = 3, kTime = 4, size, begin = 0, end = size }; + + enum class theta_id_t { kTheta1 = 0, kTheta2 = 1, size, begin = 0, end = size }; + + enum class reduced_site_id_t { kME1 = 0, kME2 = 1, kME3 = 2, kME4 = 3, kME0 = 4, size, begin = 0, end = size }; + + typedef ap_uint<13> seg_phi_t; + typedef ap_int<10> seg_bend_t; + typedef ap_uint<8> seg_theta_t; + typedef ap_uint<4> seg_qual_t; + typedef ap_int<4> seg_time_t; + typedef ap_uint<3> seg_zones_t; + typedef ap_uint<3> seg_tzones_t; + typedef ap_uint<1> seg_cscfr_t; + typedef ap_uint<1> seg_layer_t; + typedef ap_int<2> seg_bx_t; + typedef ap_uint<1> seg_valid_t; + + struct segment_t { + seg_phi_t phi; + seg_bend_t bend; + seg_theta_t theta1; + seg_theta_t theta2; + seg_qual_t qual1; + seg_qual_t qual2; + seg_time_t time; + seg_zones_t zones; + seg_tzones_t tzones; + seg_cscfr_t cscfr; + seg_layer_t layer; + seg_bx_t bx; + seg_valid_t valid; + }; + + typedef std::array segment_collection_t; + + // Tracks + typedef ap_uint<2> trk_zone_t; + typedef ap_uint<2> trk_tzone_t; + typedef ap_uint<9> trk_col_t; + typedef ap_uint<3> trk_patt_t; + typedef ap_uint<6> trk_qual_t; + typedef ap_uint<2> trk_gate_t; + typedef ap_uint<1> trk_q_t; + typedef ap_uint<13> trk_pt_t; + typedef ap_uint<7> trk_rels_t; + typedef ap_int<7> trk_dxy_t; + typedef ap_int<5> trk_z0_t; + typedef ap_int<13> trk_phi_t; + typedef ap_int<13> trk_eta_t; + typedef ap_uint<4> trk_beta_t; + typedef ap_uint<1> trk_valid_t; + typedef ap_uint<8> trk_site_seg_t; + typedef ap_uint<1> trk_site_bit_t; + typedef ap_int<13> trk_feature_t; + typedef ap_int<10> trk_nn_address_t; + + struct track_t { + typedef std::array site_segs_t; + typedef std::array site_mask_t; + typedef std::array features_t; + + trk_zone_t zone; + trk_col_t col; + trk_patt_t pattern; + trk_qual_t quality; + trk_q_t q; + trk_pt_t pt; + trk_rels_t rels; + trk_dxy_t dxy; + trk_z0_t z0; + seg_phi_t phi; + seg_theta_t theta; + trk_eta_t eta; + trk_beta_t beta; + trk_valid_t valid; + site_segs_t site_segs; + site_mask_t site_mask; + site_mask_t site_rm_mask; + features_t features; + trk_nn_address_t pt_address; + trk_nn_address_t rels_address; + trk_nn_address_t dxy_address; + }; + + // Hitmaps + typedef ap_uint hitmap_row_t; + typedef std::array hitmap_t; + + // Roads + struct road_t { + trk_zone_t zone; + trk_col_t col; + trk_patt_t pattern; + trk_qual_t quality; + }; + + typedef std::array road_collection_t; + + // Reduced Track + struct reduced_track_t { + typedef std::array site_segs_t; + typedef std::array site_mask_t; + + trk_valid_t valid; + site_segs_t site_segs; + site_mask_t site_mask; + }; +} // namespace emtf::phase2 + +typedef L1TMuon::subsystem_type SubsystemType; +typedef L1TMuon::GeometryTranslator GeometryTranslator; + +typedef L1TMuon::TriggerPrimitive::DTData DTData; +typedef L1TMuon::TriggerPrimitive::CSCData CSCData; +typedef L1TMuon::TriggerPrimitive::RPCData RPCData; +typedef L1TMuon::TriggerPrimitive::GEMData GEMData; +typedef L1TMuon::TriggerPrimitive::ME0Data ME0Data; + +#endif // L1Trigger_L1TMuonEndCapPhase2_EMTFTypes_h diff --git a/L1Trigger/L1TMuonEndCapPhase2/interface/EMTFfwd.h b/L1Trigger/L1TMuonEndCapPhase2/interface/EMTFfwd.h new file mode 100644 index 0000000000000..21e0a7b02803f --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/interface/EMTFfwd.h @@ -0,0 +1,30 @@ +#ifndef L1Trigger_L1TMuonEndCapPhase2_EMTFfwd_h +#define L1Trigger_L1TMuonEndCapPhase2_EMTFfwd_h + +#include "FWCore/Framework/interface/Frameworkfwd.h" + +#include "L1Trigger/L1TMuon/interface/MuonTriggerPrimitiveFwd.h" + +namespace emtf::phase2 { + class EMTFContext; + class EMTFConfiguration; + class EMTFModel; + + struct TPInfo; + class TPEntry; + class TrackFinder; + class SectorProcessor; + class TPCollector; + class CSCTPCollector; + class RPCTPCollector; + class GEMTPCollector; + class ME0TPCollector; + class TPSelector; + class CSCTPSelector; + class RPCTPSelector; + class GEMTPSelector; + class ME0TPSelector; + class TPConverter; +} // namespace emtf::phase2 + +#endif // namespace L1Trigger_L1TMuonEndCapPhase2_EMTFfwd_h diff --git a/L1Trigger/L1TMuonEndCapPhase2/interface/SectorProcessor.h b/L1Trigger/L1TMuonEndCapPhase2/interface/SectorProcessor.h new file mode 100644 index 0000000000000..3054620698253 --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/interface/SectorProcessor.h @@ -0,0 +1,50 @@ +#ifndef L1Trigger_L1TMuonEndCapPhase2_SectorProcessor_h +#define L1Trigger_L1TMuonEndCapPhase2_SectorProcessor_h + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFfwd.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFTypes.h" + +namespace emtf::phase2 { + + class SectorProcessor { + public: + SectorProcessor(const EMTFContext&, const int&, const int&); + + ~SectorProcessor(); + + void configureEvent(const edm::Event&); + + void configureBx(const int&); + + void select(const TriggerPrimitive&, const TPInfo&); + + void process(EMTFHitCollection&, EMTFTrackCollection&, EMTFInputCollection&); + + private: + const EMTFContext& context_; + + int endcap_, sector_; + std::map> tp_selectors_; + std::map> tp_converters_; + + // Event + const edm::Event* event_; + const int* bx_; + + // Buffers + std::vector bx_window_hits_; + std::map bx_ilink_tpc_maps_; + + // Helper functions + void copyTP(const ILinkTPCMap& source, ILinkTPCMap& target) const; + + void convertTP(const int&, const ILinkTPCMap&, EMTFHitCollection&); + + void populateSegments(const std::vector&, std::map&, segment_collection_t&); + + void buildTracks(const std::map&, const segment_collection_t&, const bool&, EMTFTrackCollection&); + }; + +} // namespace emtf::phase2 + +#endif // L1Trigger_L1TMuonEndCapPhase2_SectorProcessor_h diff --git a/L1Trigger/L1TMuonEndCapPhase2/interface/TrackFinder.h b/L1Trigger/L1TMuonEndCapPhase2/interface/TrackFinder.h new file mode 100644 index 0000000000000..3a4f03e6210da --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/interface/TrackFinder.h @@ -0,0 +1,37 @@ +#ifndef L1Trigger_L1TMuonEndCapPhase2_TrackFinder_h +#define L1Trigger_L1TMuonEndCapPhase2_TrackFinder_h + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFfwd.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFTypes.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFContext.h" + +namespace emtf::phase2 { + + class TrackFinder { + public: + explicit TrackFinder(const edm::ParameterSet&, edm::ConsumesCollector&&); + + ~TrackFinder(); + + void process( + // Input + const edm::Event&, + const edm::EventSetup&, + // Output + EMTFHitCollection&, + EMTFTrackCollection&, + EMTFInputCollection&); + + void onJobBegin(); + + void onJobEnd(); + + private: + EMTFContext context_; + + std::vector> tp_collectors_; + std::vector> sector_processors_; + }; +} // namespace emtf::phase2 + +#endif diff --git a/L1Trigger/L1TMuonEndCapPhase2/interface/Utils/CSCUtils.h b/L1Trigger/L1TMuonEndCapPhase2/interface/Utils/CSCUtils.h new file mode 100644 index 0000000000000..698c508ce9e33 --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/interface/Utils/CSCUtils.h @@ -0,0 +1,40 @@ +#ifndef L1Trigger_L1TMuonEndCapPhase2_CSCUtils_h +#define L1Trigger_L1TMuonEndCapPhase2_CSCUtils_h + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFfwd.h" + +namespace emtf::phase2::csc { + + // Enums + enum Facing { kFront, kRear, kNone }; + + // Chambers + int getNext10DegChamber(int chamber); + + int getPrev10DegChamber(int chamber); + + int getNext20DegChamber(int chamber); + + int getPrev20DegChamber(int chamber); + + // Functions + bool isTPInSector(int match_endcap, int match_sector, int tp_endcap, int tp_sector); + + bool isTPInNeighborSector( + int match_endcap, int match_sector, int tp_endcap, int tp_sector, int tp_subsector, int tp_station, int tp_id); + + int getId(int ring, int station, int chamber); + + int getTriggerSector(int ring, int station, int chamber); + + int getTriggerSubsector(int station, int chamber); + + Facing getFaceDirection(int station, int ring, int chamber); + + std::pair getMaxStripAndWire(int station, int ring); + + std::pair getMaxPatternAndQuality(int station, int ring); + +} // namespace emtf::phase2::csc + +#endif // namespace L1Trigger_L1TMuonEndCapPhase2_CSCUtils_h diff --git a/L1Trigger/L1TMuonEndCapPhase2/interface/Utils/DataUtils.h b/L1Trigger/L1TMuonEndCapPhase2/interface/Utils/DataUtils.h new file mode 100644 index 0000000000000..dec8841acf8bd --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/interface/Utils/DataUtils.h @@ -0,0 +1,155 @@ +#ifndef L1Trigger_L1TMuonEndCapPhase2_DataUtils_h +#define L1Trigger_L1TMuonEndCapPhase2_DataUtils_h + +#include +#include +#include + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFfwd.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFTypes.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFConstants.h" + +namespace emtf::phase2::data { + + // Merge-Sort + template + void swapWires(T arr[], const unsigned int& wire_1, const unsigned int& wire_2, const C& comparator) { + int result = comparator(arr[wire_1], arr[wire_2]); + + if (result == 1) { + auto temp = arr[wire_1]; + arr[wire_1] = arr[wire_2]; + arr[wire_2] = temp; + } + } + + template + void mergesortBlock(T arr[], + const unsigned int& offset, + const unsigned int& step, + const unsigned int& block_begin, + const unsigned int& block_end, + const unsigned int& first_n, + const C& comparator) { + auto wire_offset = offset + block_begin; + auto wire_cutoff = first_n + block_begin; + auto wire_1 = wire_offset; + auto wire_2 = wire_1 + step; + + // Loop pairs + while (wire_2 < block_end) { + // Trim results + if (first_n > 0 && wire_cutoff < block_end) { + bool wire_needed = (wire_offset <= wire_1) && (wire_1 <= wire_cutoff); + + if (!wire_needed) { + break; + } + } + + // Swap Wires + swapWires(arr, wire_1, wire_2, comparator); + + // Calculate next wire_1 + if (step == 1) { + wire_1 = wire_2 + 1; + } else { + wire_1 = wire_1 + 1; + } + + // Calculate next wire_2 + wire_2 = wire_1 + step; + } + } + + template + void mergesort(T arr[], const unsigned int& arr_size, const unsigned int& first_n, const C& comparator) { + // Sort + auto n_pairs = static_cast(arr_size / 2); + + for (unsigned int i = 0; i < n_pairs; ++i) { + swapWires(arr, 2 * i, 2 * i + 1, comparator); + } + + // Merge + auto offset = 0u; + auto step = 2u; + auto block_size = step * 2; + + // Loop block sizes + while (true) { + // Loop step sizes + // If the offset is greater than the amount of wires to keep + // there's no need to continue, since (offset)-wires are known + // to not contribute to the end result + while (true) { + // Loop blocks + auto block_begin = 0u; + auto block_end = block_size; + + while (block_begin < arr_size) { + // Constrain block_end + if (block_end > arr_size) + block_end = arr_size; + + // Merge block + mergesortBlock(arr, offset, step, block_begin, block_end, first_n, comparator); + + // Move to next block + block_begin = block_end; + block_end = block_end + block_size; + } + + // Decrease step + if (step > 2) { + // For each pass we are certain of the local min and max + // so skip 2 wires and reduce the step + offset = offset + 2; + step = step - 2; + } else if (step == 2) { + // For final pass we are certain of the global min and max + // so skip 1 wire and compare wires 1 to 1, the last value + // will be left without a partner; naturally since + // it's the global min + offset = 1; + step = 1; + } else { + // Short-Circuit: Done + break; + } + } + + // Short-Circuit: No more wires + if (block_size >= arr_size) + break; + + // Double the block size + offset = 0; + step = block_size; + block_size = step * 2; + } + } + + template + void mergesort(T arr[], const unsigned int& arr_size, const C& comparator) { + mergesort(arr, arr_size, 0, comparator); + } + + // Median Calculation + template + T getMedianOfSorted(T arr[], const unsigned int& arr_size) { + T mid; + + if ((arr_size % 2) == 0) { + const auto& top = arr[arr_size / 2]; + const auto& bot = arr[arr_size / 2 - 1]; + mid = (top + bot) >> 1; // Mid = (Top + Bot) / 2 + } else { + mid = arr[(arr_size - 1) / 2]; + } + + return mid; + } +} // namespace emtf::phase2::data + +#endif // L1Trigger_L1TMuonEndCapPhase2_DataUtils_h not defined diff --git a/L1Trigger/L1TMuonEndCapPhase2/interface/Utils/DebugUtils.h b/L1Trigger/L1TMuonEndCapPhase2/interface/Utils/DebugUtils.h new file mode 100644 index 0000000000000..f824837c70585 --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/interface/Utils/DebugUtils.h @@ -0,0 +1,18 @@ +#ifndef L1Trigger_L1TMuonEndCapPhase2_DebugUtils_h +#define L1Trigger_L1TMuonEndCapPhase2_DebugUtils_h + +#include +#include + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFTypes.h" + +// Uncomment the following line to use assert +// #define EMTF_ALLOW_ASSERT + +#ifdef EMTF_ALLOW_ASSERT +#define emtf_assert(expr) (assert(expr)) +#else +#define emtf_assert(expr) ((void)(expr)) +#endif + +#endif // namespace L1Trigger_L1TMuonEndCapPhase2_DebugUtils_h diff --git a/L1Trigger/L1TMuonEndCapPhase2/interface/Utils/RPCUtils.h b/L1Trigger/L1TMuonEndCapPhase2/interface/Utils/RPCUtils.h new file mode 100644 index 0000000000000..de6903299b4d9 --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/interface/Utils/RPCUtils.h @@ -0,0 +1,13 @@ +#ifndef L1Trigger_L1TMuonEndCapPhase2_RPCUtils_h +#define L1Trigger_L1TMuonEndCapPhase2_RPCUtils_h + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFfwd.h" + +namespace emtf::phase2::rpc { + + // Enums + enum Type { kRPC, kiRPC, kNone }; + +} // namespace emtf::phase2::rpc + +#endif // namespace L1Trigger_L1TMuonEndCapPhase2_RPCUtils_h diff --git a/L1Trigger/L1TMuonEndCapPhase2/interface/Utils/TPUtils.h b/L1Trigger/L1TMuonEndCapPhase2/interface/Utils/TPUtils.h new file mode 100644 index 0000000000000..a748f200bc41e --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/interface/Utils/TPUtils.h @@ -0,0 +1,46 @@ +#ifndef L1Trigger_L1TMuonEndCapPhase2_TPUtils_h +#define L1Trigger_L1TMuonEndCapPhase2_TPUtils_h + +namespace emtf::phase2::tp { + + // _______________________________________________________________________ + // radians <-> degrees + float degToRad(float deg); + + float radToDeg(float rad); + + // _______________________________________________________________________ + // phi range: [-180..180] or [-pi..pi] + float wrapPhiDeg(float); + + float wrapPhiRad(float); + + // _______________________________________________________________________ + // theta + float calcThetaRadFromEta(float); + + float calcThetaDegFromEta(float); + + float calcThetaRadFromInt(int); + + float calcThetaDegFromInt(int); + + int calcThetaInt(int, float); + + // _______________________________________________________________________ + // phi + float calcPhiGlobDegFromLoc(int, float); + + float calcPhiGlobRadFromLoc(int, float); + + float calcPhiLocDegFromInt(int); + + float calcPhiLocRadFromInt(int); + + float calcPhiLocDegFromGlob(int, float); + + int calcPhiInt(int, float); + +} // namespace emtf::phase2::tp + +#endif // namespace L1Trigger_L1TMuonEndCapPhase2_TPUtils_h diff --git a/L1Trigger/L1TMuonEndCapPhase2/plugins/BuildFile.xml b/L1Trigger/L1TMuonEndCapPhase2/plugins/BuildFile.xml new file mode 100644 index 0000000000000..bc5a448d4f1f3 --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/plugins/BuildFile.xml @@ -0,0 +1,4 @@ + + + + diff --git a/L1Trigger/L1TMuonEndCapPhase2/plugins/L1TMuonEndCapPhase2TrackProducer.cc b/L1Trigger/L1TMuonEndCapPhase2/plugins/L1TMuonEndCapPhase2TrackProducer.cc new file mode 100644 index 0000000000000..f332a9a6977f8 --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/plugins/L1TMuonEndCapPhase2TrackProducer.cc @@ -0,0 +1,79 @@ +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/EventSetup.h" +#include "FWCore/Framework/interface/ConsumesCollector.h" +#include "FWCore/Framework/interface/MakerMacros.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" + +#include "DataFormats/L1TMuon/interface/RegionalMuonCand.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/TrackFinder.h" + +#include "L1TMuonEndCapPhase2TrackProducer.h" + +L1TMuonEndCapPhase2TrackProducer::L1TMuonEndCapPhase2TrackProducer(const edm::ParameterSet& pset) + : track_finder_(std::make_unique(pset, consumesCollector())), + hit_token_(produces()), + trk_token_(produces()), + in_token_(produces()) {} + +void L1TMuonEndCapPhase2TrackProducer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { + edm::ParameterSetDescription desc; + + // Neural Network Models + desc.add("PromptGraphPath", "L1Trigger/L1TMuonEndCapPhase2/data/prompt_model.pb"); + desc.add("DisplacedGraphPath", "L1Trigger/L1TMuonEndCapPhase2/data/displaced_model.pb"); + + // Input Collections + desc.add("CSCInput", edm::InputTag("simCscTriggerPrimitiveDigisForEMTF")); + desc.add("RPCInput", edm::InputTag("rpcRecHitsForEMTF")); + desc.add("GEMInput", edm::InputTag("simMuonGEMPadDigiClusters")); + desc.add("ME0Input", edm::InputTag("me0TriggerConvertedPseudoDigis")); + desc.add("GE0Input", edm::InputTag("ge0TriggerConvertedPseudoDigis")); + + // Enable Subdetectors + desc.add("CSCEnabled", true); + desc.add("RPCEnabled", true); + desc.add("GEMEnabled", true); + desc.add("ME0Enabled", true); + desc.add("GE0Enabled", false); + + // Bunch-Crossing Settings + desc.add("MinBX", -2); + desc.add("MaxBX", 2); + desc.add("BXWindow", 1); + + desc.add("CSCInputBXShift", -8); + desc.add("RPCInputBXShift", 0); + desc.add("GEMInputBXShift", 0); + desc.add("ME0InputBXShift", -8); + + // Primitive Settings + desc.add("IncludeNeighborEnabled", true); + + // Debug Utils + desc.addUntracked("Verbosity", 3); + desc.add("ValidationDirectory", "L1Trigger/L1TMuonEndCapPhase2/data/validation"); + + // Register + descriptions.add("L1TMuonEndCapPhase2TrackProducer", desc); +} + +void L1TMuonEndCapPhase2TrackProducer::produce(edm::Event& event, const edm::EventSetup& event_setup) { + emtf::phase2::EMTFHitCollection out_hits; + emtf::phase2::EMTFTrackCollection out_tracks; + emtf::phase2::EMTFInputCollection out_inputs; + + // Forward event to track finder + track_finder_->process(event, event_setup, out_hits, out_tracks, out_inputs); + + // Output + event.emplace(hit_token_, std::move(out_hits)); + event.emplace(trk_token_, std::move(out_tracks)); + event.emplace(in_token_, std::move(out_inputs)); +} + +void L1TMuonEndCapPhase2TrackProducer::beginStream(edm::StreamID stream_id) { track_finder_->onJobBegin(); } + +void L1TMuonEndCapPhase2TrackProducer::endStream() { track_finder_->onJobEnd(); } + +//define this as a plug-in +DEFINE_FWK_MODULE(L1TMuonEndCapPhase2TrackProducer); diff --git a/L1Trigger/L1TMuonEndCapPhase2/plugins/L1TMuonEndCapPhase2TrackProducer.h b/L1Trigger/L1TMuonEndCapPhase2/plugins/L1TMuonEndCapPhase2TrackProducer.h new file mode 100644 index 0000000000000..9655be15f8614 --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/plugins/L1TMuonEndCapPhase2TrackProducer.h @@ -0,0 +1,38 @@ +#ifndef L1Trigger_L1TMuonEndCapPhase2_L1TMuonEndCapPhase2TrackProducer_h +#define L1Trigger_L1TMuonEndCapPhase2_L1TMuonEndCapPhase2TrackProducer_h + +#include + +#include "FWCore/Framework/interface/stream/EDProducer.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/StreamID.h" + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFfwd.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFTypes.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFContext.h" + +class L1TMuonEndCapPhase2TrackProducer : public edm::stream::EDProducer<> { +public: + explicit L1TMuonEndCapPhase2TrackProducer(const edm::ParameterSet&); + + ~L1TMuonEndCapPhase2TrackProducer() override = default; + + static void fillDescriptions(edm::ConfigurationDescriptions&); + +private: + std::unique_ptr track_finder_; + + edm::EDPutTokenT hit_token_; + edm::EDPutTokenT trk_token_; + edm::EDPutTokenT in_token_; + + // Producer Functions + void produce(edm::Event&, const edm::EventSetup&) override; + void beginStream(edm::StreamID) override; + void endStream() override; +}; + +#endif diff --git a/L1Trigger/L1TMuonEndCapPhase2/python/config.py b/L1Trigger/L1TMuonEndCapPhase2/python/config.py new file mode 100644 index 0000000000000..54453334d4b61 --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/python/config.py @@ -0,0 +1,59 @@ +import FWCore.ParameterSet.Config as cms + +def customise_debug(process): + # EMTF Phase2 Emulator + process.load('L1Trigger.L1TMuonEndCapPhase2.simCscTriggerPrimitiveDigisForEMTF_cfi') + process.load('L1Trigger.L1TMuonEndCapPhase2.rpcRecHitsForEMTF_cfi') + process.load('L1Trigger.L1TMuonEndCapPhase2.simEmtfDigisPhase2_cfi') + + process.gemRecHits.gemDigiLabel = 'simMuonGEMDigis' + process.simEmtfDigisPhase2.Verbosity = cms.untracked.int32(5) + + process.L1TMuonEndCapPhase2Task = cms.Task( + process.simCscTriggerPrimitiveDigisForEMTF, + process.rpcRecHitsForEMTF, + process.simEmtfDigisPhase2 + ) + + process.L1TMuonEndCapPhase2Sequence = cms.Sequence( + process.L1TMuonEndCapPhase2Task + ) + + # Path + process.L1TMuonEndCapPhase2_step = cms.Path(process.L1TMuonEndCapPhase2Sequence) + + process.schedule.extend([process.L1TMuonEndCapPhase2_step]) + + # Remove cms.EndPath instances from schedule + paths_in_schedule = [path for path in process.schedule if not isinstance(path, cms.EndPath)] + process.schedule = cms.Schedule(*paths_in_schedule) + return process + +def customise_mc(process): + # EMTF Phase2 Emulator + process.load('L1Trigger.L1TMuonEndCapPhase2.simCscTriggerPrimitiveDigisForEMTF_cfi') + process.load('L1Trigger.L1TMuonEndCapPhase2.rpcRecHitsForEMTF_cfi') + process.load('L1Trigger.L1TMuonEndCapPhase2.simEmtfDigisPhase2_cfi') + + process.gemRecHits.gemDigiLabel = 'simMuonGEMDigis' + process.simEmtfDigisPhase2.Verbosity = cms.untracked.int32(1) + + process.L1TMuonEndCapPhase2Task = cms.Task( + process.simCscTriggerPrimitiveDigisForEMTF, + process.rpcRecHitsForEMTF, + process.simEmtfDigisPhase2 + ) + + process.L1TMuonEndCapPhase2Sequence = cms.Sequence( + process.L1TMuonEndCapPhase2Task + ) + + # Path + process.L1TMuonEndCapPhase2_step = cms.Path(process.L1TMuonEndCapPhase2Sequence) + + process.schedule.extend([process.L1TMuonEndCapPhase2_step]) + + # Remove cms.EndPath instances from schedule + paths_in_schedule = [path for path in process.schedule if not isinstance(path, cms.EndPath)] + process.schedule = cms.Schedule(*paths_in_schedule) + return process diff --git a/L1Trigger/L1TMuonEndCapPhase2/python/rpcRecHitsForEMTF_cfi.py b/L1Trigger/L1TMuonEndCapPhase2/python/rpcRecHitsForEMTF_cfi.py new file mode 100644 index 0000000000000..55bfdfead591e --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/python/rpcRecHitsForEMTF_cfi.py @@ -0,0 +1,5 @@ +import FWCore.ParameterSet.Config as cms + +from RecoLocalMuon.RPCRecHit.rpcRecHits_cfi import rpcRecHits +rpcRecHitsForEMTF = rpcRecHits.clone(rpcDigiLabel = 'simMuonRPCDigis') + diff --git a/L1Trigger/L1TMuonEndCapPhase2/python/simCscTriggerPrimitiveDigisForEMTF_cfi.py b/L1Trigger/L1TMuonEndCapPhase2/python/simCscTriggerPrimitiveDigisForEMTF_cfi.py new file mode 100644 index 0000000000000..7e57ccdaa0fdc --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/python/simCscTriggerPrimitiveDigisForEMTF_cfi.py @@ -0,0 +1,30 @@ +import FWCore.ParameterSet.Config as cms + +from L1Trigger.CSCTriggerPrimitives.cscTriggerPrimitiveDigis_cfi import cscTriggerPrimitiveDigis + +# Taken from L1Trigger.L1TMuon.simDigis_cff +simCscTriggerPrimitiveDigisForEMTF = cscTriggerPrimitiveDigis.clone( + CSCComparatorDigiProducer = 'simMuonCSCDigis:MuonCSCComparatorDigi', + CSCWireDigiProducer = 'simMuonCSCDigis:MuonCSCWireDigi' +) + +# Taken from L1Trigger.CSCTriggerPrimitives.cscTriggerPrimitiveDigis_cfi +from Configuration.Eras.Modifier_run3_GEM_cff import run3_GEM +run3_GEM.toModify(simCscTriggerPrimitiveDigisForEMTF, + commonParam = dict(runPhase2 = cms.bool(True), + runME11Up = cms.bool(True), + runME11ILT = cms.bool(False), # was: True + GEMPadDigiClusterProducer = cms.InputTag(""), + enableAlctPhase2 = cms.bool(False))) # was: True + +from Configuration.Eras.Modifier_phase2_muon_cff import phase2_muon +phase2_muon.toModify(simCscTriggerPrimitiveDigisForEMTF, + commonParam = dict(runME21Up = cms.bool(True), + runME21ILT = cms.bool(False), # was: True + runME31Up = cms.bool(True), + runME41Up = cms.bool(True), + enableAlctPhase2 = cms.bool(False))) # was: True + +# Allow CSCs to have hits in multiple bxs - (Needs to be fixed on their end eventually) +phase2_muon.toModify(simCscTriggerPrimitiveDigisForEMTF.tmbPhase1, tmbReadoutEarliest2 = False) +phase2_muon.toModify(simCscTriggerPrimitiveDigisForEMTF.tmbPhase2, tmbReadoutEarliest2 = False) diff --git a/L1Trigger/L1TMuonEndCapPhase2/python/simEmtfDigisPhase2_cfi.py b/L1Trigger/L1TMuonEndCapPhase2/python/simEmtfDigisPhase2_cfi.py new file mode 100644 index 0000000000000..e6a9e3f97a9e7 --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/python/simEmtfDigisPhase2_cfi.py @@ -0,0 +1,57 @@ +import FWCore.ParameterSet.Config as cms +from Configuration.Eras.Modifier_phase2_GE0_cff import phase2_GE0 + +# EMTF Phase2 emulator configuration +simEmtfDigisMCPhase2 = cms.EDProducer( + "L1TMuonEndCapPhase2TrackProducer", + + # Verbosity level + Verbosity = cms.untracked.int32(3), + + # Validation + ValidationDirectory = cms.string("L1Trigger/L1TMuonEndCapPhase2/data/validation"), + + # Neural Network Models + PromptGraphPath = cms.string("L1Trigger/L1TMuonEndCapPhase2/data/prompt_model.pb"), + DisplacedGraphPath = cms.string("L1Trigger/L1TMuonEndCapPhase2/data/displaced_model.pb"), + + # Input collections + # Three options for CSCInput + # * 'simCscTriggerPrimitiveDigis','MPCSORTED' : simulated trigger primitives (LCTs) from re-emulating CSC digis + # * 'csctfDigis' : real trigger primitives as received by CSCTF (legacy trigger), available only in 2016 data + # * 'emtfStage2Digis' : real trigger primitives as received by EMTF, unpacked in EventFilter/L1TRawToDigi/ + CSCInput = cms.InputTag('simCscTriggerPrimitiveDigisForEMTF','MPCSORTED'), + RPCInput = cms.InputTag('rpcRecHitsForEMTF'), + GEMInput = cms.InputTag('simMuonGEMPadDigiClusters'), + ME0Input = cms.InputTag('me0TriggerConvertedPseudoDigis'), + GE0Input = cms.InputTag('ge0TriggerConvertedPseudoDigis'), + + # Run with CSC, RPC, GEM + CSCEnabled = cms.bool(True), # Use CSC LCTs from the MPCs in track-building + RPCEnabled = cms.bool(True), # Use clustered RPC hits from CPPF in track-building + GEMEnabled = cms.bool(True), # Use hits from GEMs in track-building + ME0Enabled = cms.bool(True), + GE0Enabled = cms.bool(False), + + # BX + MinBX = cms.int32(-2), # Minimum BX considered + MaxBX = cms.int32(2), # Maximum BX considered + BXWindow = cms.int32(1), # Number of BX whose primitives can be included in the same track + + CSCInputBXShift = cms.int32(-8), # Shift applied to input CSC LCT primitives, to center at BX = 0 + RPCInputBXShift = cms.int32(0), + GEMInputBXShift = cms.int32(0), + ME0InputBXShift = cms.int32(-8), + + IncludeNeighborEnabled = cms.bool(True), # Include primitives from neighbor chambers in track-building +) + +phase2_GE0.toModify(simEmtfDigisMCPhase2, ME0Enabled=False, GE0Enabled=True) + +simEmtfDigisDataPhase2 = simEmtfDigisMCPhase2.clone( + # Inputs + CSCInput = cms.InputTag('emtfStage2Digis'), + RPCInput = cms.InputTag('muonRPCDigis'), +) + +simEmtfDigisPhase2 = simEmtfDigisMCPhase2.clone() diff --git a/L1Trigger/L1TMuonEndCapPhase2/src/Algo/DuplicateRemovalLayer.cc b/L1Trigger/L1TMuonEndCapPhase2/src/Algo/DuplicateRemovalLayer.cc new file mode 100644 index 0000000000000..70f5354307131 --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/src/Algo/DuplicateRemovalLayer.cc @@ -0,0 +1,124 @@ +#include "FWCore/MessageLogger/interface/MessageLogger.h" + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFContext.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Utils/DataUtils.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Utils/DebugUtils.h" + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Algo/DuplicateRemovalLayer.h" + +using namespace emtf::phase2; +using namespace emtf::phase2::algo; + +DuplicateRemovalLayer::DuplicateRemovalLayer(const EMTFContext& context) : context_(context) {} + +void DuplicateRemovalLayer::apply(std::vector& tracks) const { + // =========================================================================== + // Unpack model + // --------------------------------------------------------------------------- + const auto& model = context_.model_; + const auto& model_reduced_sites = model.reduced_sites_; + + // =========================================================================== + // Build reduced tracks + // --------------------------------------------------------------------------- + std::vector reduced_tracks; + + for (const auto& track : tracks) { // Begin loop tracks + // Fetch reduced track + auto& rtrk = reduced_tracks.emplace_back(); + auto& rtrk_valid = rtrk.valid; + + // Initialize valid state + rtrk_valid = track.valid; + + // Fill reduced track with segments + for (const auto& model_rsite : model_reduced_sites) { // Begin loop reduced model sites + + // Get reduced site + int model_rsite_id = static_cast(model_rsite.id); + + auto& rsite_seg = rtrk.site_segs[model_rsite_id]; + auto& rsite_bit = rtrk.site_mask[model_rsite_id]; + + // Init reduced site + rsite_seg = 0; + rsite_bit = 0; + + // Select the first segment available for the reduced site + for (const auto& model_rs_ts : model_rsite.trk_sites) { // Begin loop reduced site track sites + int trk_site_id = static_cast(model_rs_ts); + + const auto& trk_site_seg = track.site_segs[trk_site_id]; + const auto& trk_site_bit = track.site_mask[trk_site_id]; + + if (trk_site_bit == 0) { + continue; + } + + // Attach segment + // If even one segment is attached + // the reduced track is considered valid + rtrk_valid = 1; + rsite_seg = trk_site_seg; + rsite_bit = 1; + + break; + } // End loop reduced site track sites + } // End loop reduced model sites + } // End loop tracks + + // =========================================================================== + // Find and invalidate duplicate tracks + // --------------------------------------------------------------------------- + for (unsigned int i_rtrk = 0; i_rtrk < reduced_tracks.size(); ++i_rtrk) { // Begin loop reduced tracks i + + auto& trk_i = tracks[i_rtrk]; + const auto& rtrk_i = reduced_tracks[i_rtrk]; + + if (rtrk_i.valid == 1) { + for (unsigned int j_rtrk = (i_rtrk + 1); j_rtrk < reduced_tracks.size(); + ++j_rtrk) { // Begin loop reduced tracks j + + auto& rtrk_j = reduced_tracks[j_rtrk]; + + // If the reduced track is already invalid, move on + if (rtrk_j.valid == 0) + continue; + + // Compare reduced track sites + for (unsigned int k_rsite = 0; k_rsite < v3::kNumTrackSitesRM; ++k_rsite) { // Begin loop reduced sites k + const auto& rtrk_site_mask_ik = rtrk_i.site_mask[k_rsite]; + const auto& rtrk_site_mask_jk = rtrk_j.site_mask[k_rsite]; + + // If one or both of the sites are missing, move on + if (!(rtrk_site_mask_ik & rtrk_site_mask_jk)) + continue; + + // Compare segment_ids + const auto& rtrk_seg_id_ik = rtrk_i.site_segs[k_rsite]; + const auto& rtrk_seg_id_jk = rtrk_j.site_segs[k_rsite]; + + // If segment ids are differente, move on + if (rtrk_seg_id_ik != rtrk_seg_id_jk) + continue; + + // If there's even one collision, invalidate the track + rtrk_j.valid = 0; + } // End loop reduced sites k + } // End loop reduced tracks j + } + + // Propagate invalidation + trk_i.valid = rtrk_i.valid; + + // DEBUG + if (this->context_.config_.verbosity_ > 1) { + if (trk_i.valid) { + edm::LogInfo("L1TEMTFpp") << "Unique Track" + << " zone " << trk_i.zone << " col " << trk_i.col << " pat " << trk_i.pattern + << " qual " << trk_i.quality << " phi " << trk_i.phi << " theta " << trk_i.theta + << " valid " << trk_i.valid << std::endl; + } + } + } // End loop reduced tracks i +} diff --git a/L1Trigger/L1TMuonEndCapPhase2/src/Algo/HitmapLayer.cc b/L1Trigger/L1TMuonEndCapPhase2/src/Algo/HitmapLayer.cc new file mode 100644 index 0000000000000..bca1748d2b2e2 --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/src/Algo/HitmapLayer.cc @@ -0,0 +1,168 @@ +#include "FWCore/MessageLogger/interface/MessageLogger.h" + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFContext.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Utils/DebugUtils.h" + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Algo/HitmapLayer.h" + +using namespace emtf::phase2::algo; + +HitmapLayer::HitmapLayer(const EMTFContext& context) : context_(context) {} + +void HitmapLayer::apply(const segment_collection_t& segments, std::vector& zone_hitmaps) const { + const hitmap_row_t padded_one = 1; + + auto& model = context_.model_; + + // Create Images + auto n_zones = model.zones_.size(); + + for (unsigned int zone_id = 0; zone_id < n_zones; ++zone_id) { // Begin zones + unsigned int zone_mask = (1u << zone_id); + unsigned int tzone_mask = (1u << 0); // Only looking at BX=0 for now + + const auto& model_hm = model.zones_[zone_id].hitmap; + auto& hitmap = zone_hitmaps.emplace_back(); + bool hitmap_is_blank = true; + + auto n_rows = model_hm.size(); + + for (unsigned int row_id = 0; row_id < n_rows; ++row_id) { // Begin loop rows + + const auto& model_hm_row = model_hm[row_id]; + auto& row = hitmap[row_id]; + row = 0; // Clear Row Image + + for (const auto& model_hm_site : model_hm_row) { // Begin loop sites in row + + for (const auto& model_hm_chamber : model_hm_site.chambers) { // Begin loop chambers in site + + for (unsigned int i_ch_seg = 0; i_ch_seg < v3::kChamberSegments; ++i_ch_seg) { // Begin loop segments + + const int seg_id = model_hm_chamber.id * v3::kChamberSegments + i_ch_seg; + const auto& seg = segments[seg_id]; + + // Short-Circuit: Must be valid + if (seg.valid != 1) { + continue; + } + + // Short-Circuit: Must be same zone + if ((seg.zones & zone_mask) != zone_mask) { + // Debug Info + if (this->context_.config_.verbosity_ > 4) { + edm::LogInfo("L1TEMTFpp") + << "Hitmap Segment not in zone: " + << " zone " << zone_id << " row " << row_id << " seg_id " << seg_id << " seg_phi " << seg.phi + << " seg_zones " << seg.zones << " seg_tzones " << seg.tzones << std::endl; + } + + continue; + } + + // Short-Circuit: Must be same timezone + if ((seg.tzones & tzone_mask) != tzone_mask) { + // Debug Info + if (this->context_.config_.verbosity_ > 4) { + edm::LogInfo("L1TEMTFpp") + << "Hitmap Segment not in timezone: " + << " zone " << zone_id << " row " << row_id << " seg_id " << seg_id << " seg_phi " << seg.phi + << " seg_zones " << seg.zones << " seg_tzones " << seg.tzones << std::endl; + } + + continue; + } + + // Convert emtf_phi to col: truncate the last 4 bits, hence dividing by 16 + auto col_id = static_cast(seg.phi >> v3::kHitmapColFactorLog2); + + // Debug Info + // Seg col should be in the range specified by the model chamber + if (this->context_.config_.verbosity_ > 4) { + edm::LogInfo("L1TEMTFpp") << "Hitmap Segment Before Assert" + << " zone " << zone_id << " row " << row_id << " col " << col_id << " seg_id " + << seg_id << " seg_phi " << seg.phi << " seg_zones " << seg.zones + << " seg_tzones " << seg.tzones << " ch_col_begin " << model_hm_chamber.begin + << " ch_col_end " << model_hm_chamber.end << std::endl; + } + + emtf_assert(model_hm_chamber.begin <= col_id && col_id < model_hm_chamber.end); + + // Short-Circuit: Joined chamber hitmap has more columns than the final image, + // so we skip the columns outside of the final hitmaps's range + // i.e. cropping the originl image + if (!(v3::kHitmapCropColStart <= col_id && col_id < v3::kHitmapCropColStop)) { + // Debug Info + if (this->context_.config_.verbosity_ > 4) { + edm::LogInfo("L1TEMTFpp") << "Hitmap Segment out of bounds: " + << " zone " << zone_id << " row " << row_id << " col " << col_id << " seg_id " + << seg_id << " seg_phi " << seg.phi << " seg_zones " << seg.zones + << " seg_tzones " << seg.tzones << std::endl; + } + + continue; + } + + // Adjust col_id so kHitmapCropColStart is col 0 in the image + col_id -= v3::kHitmapCropColStart; + + // Calculate the 0-padded int for that column and or-it into the image + hitmap_row_t col_mask = padded_one << col_id; + row |= col_mask; + + // Debug Info + if (this->context_.config_.verbosity_ > 1) { + edm::LogInfo("L1TEMTFpp") << "Hitmap Segment" + << " zone " << zone_id << " row " << row_id << " col " << col_id << " seg_id " + << seg_id << " seg_phi " << seg.phi << " seg_zones " << seg.zones + << " seg_tzones " << seg.tzones << std::endl; + } + } // End loop segments + + } // End loop chambers in site + + } // End loop sites in row + + // Check if hitmap is blank + if (hitmap_is_blank && row != 0) { + hitmap_is_blank = false; + } + } // End loop rows + + // Debug Info + if (this->context_.config_.verbosity_ > 3) { + // Short-Circuit: the image is blank + if (hitmap_is_blank) { + continue; + } + + // Pretty print + edm::LogInfo("L1TEMTFpp") << std::endl; + edm::LogInfo("L1TEMTFpp") << "Zone " << zone_id << " Image" << std::endl; + + // Print rows in reverse order + for (int row_id = (model_hm.size() - 1); 0 <= row_id; --row_id) { + const auto& row = hitmap[row_id]; + + edm::LogInfo("L1TEMTFpp") << row_id << " "; + + for (unsigned int col_id = 0; col_id < v3::kHitmapNCols; ++col_id) { + hitmap_row_t pixel_mask = 1; + pixel_mask = pixel_mask << col_id; + + bool is_present = (row & pixel_mask) == pixel_mask; + + if (is_present) { + edm::LogInfo("L1TEMTFpp") << "X"; + } else { + edm::LogInfo("L1TEMTFpp") << "-"; + } + } + + edm::LogInfo("L1TEMTFpp") << std::endl; + } + + edm::LogInfo("L1TEMTFpp") << std::endl; + } + } // End loop zones +} diff --git a/L1Trigger/L1TMuonEndCapPhase2/src/Algo/OutputLayer.cc b/L1Trigger/L1TMuonEndCapPhase2/src/Algo/OutputLayer.cc new file mode 100644 index 0000000000000..552ab14f9e3ec --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/src/Algo/OutputLayer.cc @@ -0,0 +1,223 @@ +#include "PhysicsTools/TensorFlow/interface/TensorFlow.h" + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFContext.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Utils/DataUtils.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Utils/DebugUtils.h" + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Algo/OutputLayer.h" + +using namespace emtf::phase2; +using namespace emtf::phase2::algo; + +OutputLayer::OutputLayer(const EMTFContext& context) : context_(context) {} + +void OutputLayer::apply(const int& endcap, + const int& sector, + const int& bx, + const std::map& seg_to_hit, + const std::vector& tracks, + const bool& displaced_en, + EMTFTrackCollection& out_tracks) const { + const int endcap_pm = (endcap == 2) ? -1 : endcap; // 1: +endcap, -1: -endcap + + for (auto& track : tracks) { // Begin loop tracks + // Fill Site/Hit Vectors + int hit_count = 0; + + EMTFTrack::site_hits_t site_hits; + EMTFTrack::site_segs_t site_segs; + EMTFTrack::site_mask_t site_mask; + EMTFTrack::site_mask_t site_rm_mask; + + for (unsigned int i = 0; i < v3::kNumTrackSites; i++) { + // Get attached segments + const auto& site_seg_id = track.site_segs[i]; + const auto& site_bit = track.site_mask[i]; + const auto& site_rm_bit = track.site_rm_mask[i]; + + // Increase hit count + if (site_bit == 1) { + hit_count += 1; + } + + // Convert segment to hit + int hit_id = 0; + + if ((site_bit == 1) || (site_rm_bit == 1)) { + hit_id = seg_to_hit.at(site_seg_id); + } + + // Save Info + site_hits.push_back(hit_id); + site_segs.push_back(site_seg_id); + site_mask.push_back(site_bit); + site_rm_mask.push_back(site_rm_bit); + } + + // Short-Circuit: Only keep tracks with hits + if (!track.valid && hit_count == 0) { + continue; + } + + // Fill Feature Vector + EMTFTrack::features_t model_features; + + for (unsigned int i = 0; i < v3::kNumTrackFeatures; i++) { + model_features.push_back(track.features[i]); + } + + // Find EMTF/GMT variables + const int emtf_mode_v1 = findEMTFModeV1(track.site_mask); + const int emtf_mode_v2 = findEMTFModeV2(track.site_mask); + + // Init Parameters + auto& out_trk = out_tracks.emplace_back(); + + out_trk.setEndcap(endcap_pm); + out_trk.setSector(sector); + out_trk.setBx(bx); + out_trk.setUnconstrained(displaced_en ? true : false); + out_trk.setValid(track.valid); + + out_trk.setModelPtAddress(track.pt_address); + out_trk.setModelRelsAddress(track.rels_address); + out_trk.setModelDxyAddress(track.dxy_address); + out_trk.setModelPattern(track.pattern); + out_trk.setModelQual(track.quality); + out_trk.setModelPhi(track.phi); + out_trk.setModelEta(track.theta); + out_trk.setModelFeatures(model_features); + + out_trk.setEmtfQ(track.q); + out_trk.setEmtfPt(track.pt); + out_trk.setEmtfRels(track.rels); + out_trk.setEmtfD0(std::abs(track.dxy)); + out_trk.setEmtfZ0(0); // not yet implemented + out_trk.setEmtfBeta(0); // not yet implemented + out_trk.setEmtfModeV1(emtf_mode_v1); + out_trk.setEmtfModeV2(emtf_mode_v2); + + out_trk.setSiteHits(site_hits); + out_trk.setSiteSegs(site_segs); + out_trk.setSiteMask(site_mask); + out_trk.setSiteRMMask(site_rm_mask); + } // End loop tracks +} + +int OutputLayer::findEMTFModeV1(const track_t::site_mask_t& x) const { + int mode = 0; + + if (x[0] or x[9] or x[1] or x[5] or x[11]) { // ME1/1, GE1/1, ME1/2, RE1/2, ME0 + mode |= (1 << 3); + } + + if (x[2] or x[10] or x[6]) { // ME2, GE2/1, RE2/2 + mode |= (1 << 2); + } + + if (x[3] or x[7]) { // ME3, RE3 + mode |= (1 << 1); + } + + if (x[4] or x[8]) { // ME4, RE4 + mode |= (1 << 0); + } + + return mode; +} + +// SingleMu (12) +// - at least one station-1 segment (ME1/1, GE1/1, ME1/2, RE1/2, ME0) +// with one of the following requirements on stations 2,3,4 +// a. if there is ME1/2 or RE1/2, +// i. if there is ME1/2, require 1 more CSC station +// ii. else, require 1 more CSC station + 1 more station +// b. if there is ME1/1 or GE1/1, +// i. if there is ME1/1, require 1 more CSC station + 1 more station +// ii. else, require 2 more CSC stations +// c. if there is ME0, +// i. if there is ME1/1, require 1 more station in stations 3,4 +// ii. else, require 1 more CSC station + 1 more station +// +// DoubleMu (8) +// - at least one station-1 segment (ME1/1, GE1/1, ME1/2, RE1/2, ME0) +// with one of the following requirements on stations 2,3,4 +// a. if there is ME1/1 or ME1/2, require 1 more station +// b. if there is GE1/1 or RE1/2, require 1 more CSC station +// c. if there is ME0, +// i. if there is ME1/1, require 1 more station +// ii. else, require 1 more CSC station +// +// TripleMu (4) +// - at least two stations +// a. if there is ME1/1 or ME1/2, require 1 more station +// b. if there is GE1/1 or RE1/2, require 1 more CSC station +// c. if there is ME0, +// i. if there is ME1/1, require 1 more station +// ii. else, require 1 more CSC station +// d. else, require 2 more CSC stations +// +// SingleHit (0) +// - at least one station +// +// Note that SingleMu, DoubleMu, TripleMu, SingleHit are mutually-exclusive categories. +int OutputLayer::findEMTFModeV2(const track_t::site_mask_t& x) const { + int mode = 0; + int cnt_ye11 = x[0] + x[9]; // ME1/1, GE1/1 + int cnt_ye12 = x[1] + x[5]; // ME1/2, RE1/2 + int cnt_ye22 = x[2] + x[10] + x[6]; // ME2, GE2/1, RE2/2 + int cnt_ye23 = x[3] + x[7]; // ME3, RE3 + int cnt_ye24 = x[4] + x[8]; // ME4, RE4 + int cnt_ye2a = (cnt_ye22 != 0) + (cnt_ye23 != 0) + (cnt_ye24 != 0); // + int cnt_ye2b = (cnt_ye23 != 0) + (cnt_ye24 != 0); // + int cnt_me11 = x[0]; // ME1/1 only + int cnt_me12 = x[1]; // ME1/2 only + int cnt_me14 = x[11]; // ME0 only + int cnt_me2a = (x[2] != 0) + (x[3] != 0) + (x[4] != 0); // + + // SingleMu (12) + { + bool rule_a_i = (cnt_me12 != 0) and (cnt_me2a >= 1); + bool rule_a_ii = (cnt_ye12 != 0) and (cnt_me2a >= 1) and (cnt_ye2a >= 2); + bool rule_b_i = (cnt_me11 != 0) and (cnt_me2a >= 1) and (cnt_ye2a >= 2); + bool rule_b_ii = (cnt_ye11 != 0) and (cnt_me2a >= 2); + bool rule_c_i = (cnt_me14 != 0) and (cnt_me11 != 0) and (cnt_ye2b >= 1); + bool rule_c_ii = (cnt_me14 != 0) and (cnt_me2a >= 1) and (cnt_ye2a >= 2); + + if (rule_a_i or rule_a_ii or rule_b_i or rule_b_ii or rule_c_i or rule_c_ii) { + mode |= (1 << 3); + mode |= (1 << 2); + } + } + + // DoubleMu (8) + if (mode < (1 << 3)) { + bool rule_a_i = (cnt_me12 != 0) and (cnt_ye2a >= 1); + bool rule_a_ii = (cnt_me11 != 0) and (cnt_ye2a >= 1); + bool rule_b_i = (cnt_ye12 != 0) and (cnt_me2a >= 1); + bool rule_b_ii = (cnt_ye11 != 0) and (cnt_me2a >= 1); + bool rule_c_i = (cnt_me14 != 0) and (cnt_me11 != 0) and (cnt_ye2a >= 1); + bool rule_c_ii = (cnt_me14 != 0) and (cnt_me2a >= 1); + + if (rule_a_i or rule_a_ii or rule_b_i or rule_b_ii or rule_c_i or rule_c_ii) { + mode |= (1 << 3); + } + } + + // TripleMu (4) + if (mode < (1 << 2)) { + bool rule_a_i = (cnt_me12 != 0) and (cnt_ye2a >= 1); + bool rule_a_ii = (cnt_me11 != 0) and (cnt_ye2a >= 1); + bool rule_b_i = (cnt_ye12 != 0) and (cnt_me2a >= 1); + bool rule_b_ii = (cnt_ye11 != 0) and (cnt_me2a >= 1); + bool rule_c_i = (cnt_me14 != 0) and (cnt_me11 != 0) and (cnt_ye2a >= 1); + bool rule_c_ii = (cnt_me14 != 0) and (cnt_me2a >= 1); + bool rule_d = (cnt_me2a >= 2); + + if (rule_a_i or rule_a_ii or rule_b_i or rule_b_ii or rule_c_i or rule_c_ii or rule_d) { + mode |= (1 << 2); + } + } + + return mode; +} diff --git a/L1Trigger/L1TMuonEndCapPhase2/src/Algo/ParameterAssignmentLayer.cc b/L1Trigger/L1TMuonEndCapPhase2/src/Algo/ParameterAssignmentLayer.cc new file mode 100644 index 0000000000000..cc25f9740d7ee --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/src/Algo/ParameterAssignmentLayer.cc @@ -0,0 +1,151 @@ +#include + +#include "FWCore/MessageLogger/interface/MessageLogger.h" +#include "PhysicsTools/TensorFlow/interface/TensorFlow.h" + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFContext.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Utils/DataUtils.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Utils/DebugUtils.h" + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Algo/ParameterAssignmentLayer.h" + +using namespace emtf::phase2; +using namespace emtf::phase2::algo; + +ParameterAssignmentLayer::ParameterAssignmentLayer(const EMTFContext& context) : context_(context) {} + +void ParameterAssignmentLayer::apply(const bool& displaced_en, std::vector& tracks) const { + std::vector feature_sites = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 0, 1, 2, 3, 4, 11, 0, 1, 2, 3, 4, 11, -1, -1, -1, -1}; + + for (auto& track : tracks) { // Begin loop tracks + // Init Parameters + track.pt = 0; + track.rels = 0; + track.dxy = 0; + track.z0 = 0; + track.beta = 0; + + track.pt_address = 0; + track.rels_address = 0; + track.dxy_address = 0; + + // Short-Circuit: Skip invalid tracks + if (track.valid == 0) { + continue; + } + + // Get Features + const auto& site_mask = track.site_mask; + const auto& features = track.features; + + // Single batch of NTrackFeatures values + tensorflow::Tensor input(tensorflow::DT_FLOAT, {1, v3::kNumTrackFeatures}); + + if (this->context_.config_.verbosity_ > 1) { + edm::LogInfo("L1TEMTFpp") << "Parameter Assignment In" + << " disp " << displaced_en << " zone " << track.zone << " col " << track.col << " pat " + << track.pattern << " qual " << track.quality << " phi " << track.phi << " theta " + << track.theta << " features " << std::endl; + } + + // Prepare input tensor + float* input_data = input.flat().data(); + + for (unsigned int i_feature = 0; i_feature < v3::kNumTrackFeatures; ++i_feature) { + const auto& feature = features[i_feature]; + const auto& feature_site = feature_sites[i_feature]; + + bool mask_value = false; + + // Debug Info + if (this->context_.config_.verbosity_ > 1 && i_feature > 0) { + edm::LogInfo("L1TEMTFpp") << " "; + } + + // Mask invalid sites + if (feature_site > -1) { + mask_value = (site_mask[feature_site] == 0); + } + + if (mask_value) { + (*input_data) = 0.; + + // Debug Info + if (this->context_.config_.verbosity_ > 1) { + edm::LogInfo("L1TEMTFpp") << "0"; + } + } else { + (*input_data) = feature.to_float(); + + // Debug Info + if (this->context_.config_.verbosity_ > 1) { + edm::LogInfo("L1TEMTFpp") << feature.to_float(); + } + } + + input_data++; + } + + // Debug Info + if (this->context_.config_.verbosity_ > 1) { + edm::LogInfo("L1TEMTFpp") << std::endl; + } + + // Select TF Session + auto* session_ptr = context_.prompt_session_ptr_; + + if (displaced_en) { + session_ptr = context_.disp_session_ptr_; + } + + // Evaluate Prompt + std::vector outputs; + + tensorflow::run(session_ptr, + {{"inputs", input}}, // Input layer name + {"Identity"}, // Output layer name + &outputs); + + // Assign parameters + if (displaced_en) { + // Read displaced pb outputs + auto pt_address = outputs[0].matrix()(0, 0); + auto rels_address = outputs[0].matrix()(0, 1); + auto dxy_address = outputs[0].matrix()(0, 2); + + track.pt_address = std::clamp(pt_address, -512, 511); + track.rels_address = std::clamp(rels_address, -512, 511); + track.dxy_address = std::clamp(dxy_address, -512, 511); + + track.q = (track.pt_address < 0); + track.pt = context_.activation_lut_.lookupDispPt(track.pt_address); + track.rels = context_.activation_lut_.lookupRels(track.rels_address); + track.dxy = context_.activation_lut_.lookupDxy(track.dxy_address); + } else { + // Read prompt pb outputs + auto pt_address = outputs[0].matrix()(0, 0); + auto rels_address = outputs[0].matrix()(0, 1); + + track.pt_address = std::clamp(pt_address, -512, 511); + track.rels_address = std::clamp(rels_address, -512, 511); + track.dxy_address = 0; + + track.q = (track.pt_address < 0); + track.pt = context_.activation_lut_.lookupPromptPt(track.pt_address); + track.rels = context_.activation_lut_.lookupRels(track.rels_address); + track.dxy = 0; + } + + // DEBUG + if (this->context_.config_.verbosity_ > 1) { + edm::LogInfo("L1TEMTFpp") << "Parameter Assignment Out" + << " disp " << displaced_en << " zone " << track.zone << " col " << track.col << " pat " + << track.pattern << " qual " << track.quality << " q " << track.q << " pt " << track.pt + << " rels " << track.rels << " dxy " << track.dxy << " z0 " << track.z0 << " phi " + << track.phi << " theta " << track.theta << " beta " << track.beta << " pt_address " + << track.pt_address << " rels_address " << track.rels_address << " dxy_address " + << track.dxy_address << " valid " << track.valid << std::endl; + } + } // End loop tracks +} diff --git a/L1Trigger/L1TMuonEndCapPhase2/src/Algo/PatternMatchingLayer.cc b/L1Trigger/L1TMuonEndCapPhase2/src/Algo/PatternMatchingLayer.cc new file mode 100644 index 0000000000000..47743345ac9c5 --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/src/Algo/PatternMatchingLayer.cc @@ -0,0 +1,123 @@ +#include "FWCore/MessageLogger/interface/MessageLogger.h" + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFContext.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Utils/DebugUtils.h" + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Algo/PatternMatchingLayer.h" + +using namespace emtf::phase2::algo; + +PatternMatchingLayer::PatternMatchingLayer(const EMTFContext& context) : context_(context) {} + +void PatternMatchingLayer::apply(const std::vector& zone_hitmaps, + const bool& displaced_en, + std::vector& zone_roads) const { + typedef ap_uint padded_row_t; + typedef ap_uint pattern_activation_t; + typedef std::array pattern_activation_collection_t; + + const padded_row_t padded_one = 1; + + auto& model = context_.model_; + + for (unsigned int i_zone = 0; i_zone < zone_hitmaps.size(); ++i_zone) { // Loop Zones + auto& hitmap = zone_hitmaps[i_zone]; + auto* model_pc = &(model.zones_[i_zone].prompt_patterns); + auto* model_ql = &(model.zones_[i_zone].prompt_quality_lut); + + if (displaced_en) { + model_pc = &(model.zones_[i_zone].disp_patterns); + model_ql = &(model.zones_[i_zone].disp_quality_lut); + } + + // Initialize roads + auto& roads = zone_roads.emplace_back(); + + for (unsigned int i_col = 0; i_col < v3::kHitmapNCols; ++i_col) { + roads[i_col].pattern = 0; + roads[i_col].quality = 0; + } + + // Apply patterns + for (unsigned int i_pattern = 0; i_pattern < model_pc->size(); ++i_pattern) { // Loop Patterns + auto& model_pat = (*model_pc)[i_pattern]; + + // Initialize activations + pattern_activation_collection_t pac; + + for (unsigned int i_col = 0; i_col < v3::kHitmapNCols; ++i_col) { + pac[i_col] = 0; + } + + // Build activations + for (unsigned int i_row = 0; i_row < v3::kHitmapNRows; ++i_row) { // Loop Rows + // Pad the row with zeros to cover cases where + // pattern range is out of range + const auto& hitmap_row = hitmap[i_row]; + auto& model_pat_row = model_pat[i_row]; + + // Pad the hitmap row on both sides using kMaxPadding + // We binary shift it to the left by kMaxPadding + // effectively padding it to the right, and since + // the bitwidth already includes both paddings + // the left is also padded + padded_row_t padded_hm_row = hitmap_row; + padded_hm_row = padded_hm_row << v3::kPatternMatchingPadding; + + // Convert the model pattern row to a padded row + padded_row_t padded_pat_row = 0; + + unsigned int offset = model_pat_row.begin; + + unsigned int bw = model_pat_row.end - model_pat_row.begin + 1; // Add 1 since it's an inclusive range + + for (unsigned int i_bit = 0; i_bit < bw; ++i_bit) + padded_pat_row |= (padded_one << (offset + i_bit)); + + // Slide the pattern row across the hitmap and check for 'activations' + for (unsigned int i_col = 0; i_col < v3::kHitmapNCols; ++i_col) { + // "AND" both rows together if the result is greater than 0 + // there is an activation + padded_row_t result = padded_pat_row & padded_hm_row; + + if (result > 0) + pac[i_col] = pac[i_col] | (1 << i_row); + + // Shift the pattern row to the left, i.e. slide it across + padded_pat_row = padded_pat_row << 1; + } + } // End Loop Rows + + // Compare Activations + // Update the road if the column's road has a smaller + // quality than the new activation's quality. + // Note: Since this is in a loop going from smallest pattern number + // to the largest, cases where the quality is the same, + // but the pattern number is larger the smaller one will be preferred + for (unsigned int i_col = 0; i_col < v3::kHitmapNCols; ++i_col) { + auto& activation = pac[i_col]; + auto quality = (*model_ql)[activation]; + + auto& current_road = roads[i_col]; + + if (current_road.quality < quality) { + current_road.pattern = i_pattern; + current_road.quality = quality; + } + } + } // End Loop Patterns in Zones + + // Debug Info + if (this->context_.config_.verbosity_ > 1) { + for (unsigned int i_col = 0; i_col < v3::kHitmapNCols; ++i_col) { + if (roads[i_col].quality == 0) { + continue; + } + + edm::LogInfo("L1TEMTFpp") << "Road" + << " zone " << i_zone << " col " << i_col << " pat " << roads[i_col].pattern + << " qual " << roads[i_col].quality << std::endl; + } + } + } // End Loop Zones +} diff --git a/L1Trigger/L1TMuonEndCapPhase2/src/Algo/RoadSortingLayer.cc b/L1Trigger/L1TMuonEndCapPhase2/src/Algo/RoadSortingLayer.cc new file mode 100644 index 0000000000000..d085e9a25d2d8 --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/src/Algo/RoadSortingLayer.cc @@ -0,0 +1,157 @@ +#include "FWCore/MessageLogger/interface/MessageLogger.h" + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFContext.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Utils/DataUtils.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Utils/DebugUtils.h" + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Algo/RoadSortingLayer.h" + +using namespace emtf::phase2::algo; + +RoadSortingLayer::RoadSortingLayer(const EMTFContext& context) : context_(context) {} + +void RoadSortingLayer::apply(const unsigned int& first_n, + const std::vector& zone_roads, + std::vector& best_roads) const { + // Find the best roads from each zone + std::vector top_roads; + + for (unsigned int i_zone = 0; i_zone < zone_roads.size(); ++i_zone) { // Loop Zones + + auto& roads = zone_roads[i_zone]; + + // Suppress qualities of non local maximum + road_collection_t suppressed_roads; + + { + const int last_col = v3::kHitmapNCols - 1; + + for (unsigned int i_col = 0; i_col < v3::kHitmapNCols; ++i_col) { + bool is_local_max = true; + bool is_last_col = i_col == last_col; + bool is_first_col = i_col == 0; + + // If this is not the last column, compare it with the next column's road + // If this column has better or equal quality than the next, this is still the local max + if (is_local_max && !is_last_col) { + is_local_max &= (roads[i_col].quality >= roads[i_col + 1].quality); + } + + // If this is not the first column, compare it with the previous column's road + // If this column has better quality than the previous, this is still the local max + if (is_local_max && !is_first_col) { + is_local_max &= (roads[i_col].quality > roads[i_col - 1].quality); + } + + // Suppress qualities + if (is_local_max) { + suppressed_roads[i_col].zone = i_zone; + suppressed_roads[i_col].col = i_col; + suppressed_roads[i_col].pattern = roads[i_col].pattern; + suppressed_roads[i_col].quality = roads[i_col].quality; + } else { + // Debug Info + if (this->context_.config_.verbosity_ > 2 && roads[i_col].quality > 0) { + edm::LogInfo("L1TEMTFpp") << "Road Suppressed" + << " zone " << i_zone << " col " << i_col << " pat " << roads[i_col].pattern + << " qual " << roads[i_col].quality << std::endl; + } + + // Suppress + suppressed_roads[i_col].zone = i_zone; + suppressed_roads[i_col].col = i_col; + suppressed_roads[i_col].pattern = roads[i_col].pattern; + suppressed_roads[i_col].quality = 0; + } + } + } + + // Keep best of every pair + const int keep_n_roads = v3::kHitmapNCols / 2; + + road_t roads_kept[keep_n_roads]; + + { + for (unsigned int i_col = 0; i_col < keep_n_roads; ++i_col) { + bool is_single = (i_col * 2 + 1) >= v3::kHitmapNCols; + + if (is_single || suppressed_roads[i_col * 2].quality > 0) { + roads_kept[i_col] = suppressed_roads[i_col * 2]; + } else { + roads_kept[i_col] = suppressed_roads[i_col * 2 + 1]; + } + + if (this->context_.config_.verbosity_ > 2 && roads_kept[i_col].quality > 0) { + edm::LogInfo("L1TEMTFpp") << "Road Kept" + << " zone " << roads_kept[i_col].zone << " col " << roads_kept[i_col].col << " pat " + << roads_kept[i_col].pattern << " qual " << roads_kept[i_col].quality << std::endl; + } + } + } + + // Mergesort-reduce to n best roads + // This will sort descending order (higher-value means lower-index) and keep the first n roads + + // Sort the first 32 cols since there are 144 columns and we wish to sort powers of 2, therefore 128 to keep priorities. + data::mergesort( + roads_kept, 32, 16, [](const road_t& lhs, const road_t& rhs) -> int { return lhs.quality < rhs.quality; }); + + // Shift everything 16 cols to the left + for (unsigned int i = 16; i < keep_n_roads; ++i) { + roads_kept[i] = roads_kept[i + 16]; + } + + // Merge-sort the remaining 128 cols + data::mergesort(roads_kept, 128, first_n, [](const road_t& lhs, const road_t& rhs) -> int { + return lhs.quality < rhs.quality; + }); + + // Collect best roads + for (unsigned int i_col = 0; i_col < first_n; ++i_col) { + top_roads.push_back(roads_kept[i_col]); + } + } // End Loop Zones + + // Debug Info + if (this->context_.config_.verbosity_ > 2) { + for (const auto& road : top_roads) { + // Short-Circuit: Skip quality-0 roads + if (road.quality == 0) { + continue; + } + + edm::LogInfo("L1TEMTFpp") << "Top Road" + << " zone " << road.zone << " col " << road.col << " pat " << road.pattern << " qual " + << road.quality << std::endl; + } + } + + // Mergesort-reduce to n best roads + // This will sort descending order (higher-value means lower-index) and keep the first n roads + + // Sort the first 8 cols since there are 12 cols and we wish to sort powers of 2, therefore 8 to keep priorities + data::mergesort( + &top_roads[0], 8, 4, [](const road_t& lhs, const road_t& rhs) -> int { return lhs.quality < rhs.quality; }); + + // Shift everything 4 cols to the left + for (unsigned int i = 4; i < top_roads.size(); ++i) { + top_roads[i] = top_roads[i + 4]; + } + + // Merge-sort remaining 8 cols + data::mergesort( + &top_roads[0], 8, first_n, [](const road_t& lhs, const road_t& rhs) -> int { return lhs.quality < rhs.quality; }); + + // Collect best roads + for (unsigned int i_road = 0; i_road < first_n; ++i_road) { + const auto& road = top_roads[i_road]; + + best_roads.push_back(road); + + // Debug Info + if (this->context_.config_.verbosity_ > 1 && road.quality > 0) { + edm::LogInfo("L1TEMTFpp") << "Best Road " << i_road << " zone " << road.zone << " col " << road.col << " pat " + << road.pattern << " qual " << road.quality << std::endl; + } + } +} diff --git a/L1Trigger/L1TMuonEndCapPhase2/src/Algo/TrackBuildingLayer.cc b/L1Trigger/L1TMuonEndCapPhase2/src/Algo/TrackBuildingLayer.cc new file mode 100644 index 0000000000000..14fb5cb966137 --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/src/Algo/TrackBuildingLayer.cc @@ -0,0 +1,572 @@ +#include "FWCore/MessageLogger/interface/MessageLogger.h" + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFContext.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Utils/DataUtils.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Utils/DebugUtils.h" + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Algo/TrackBuildingLayer.h" + +using namespace emtf::phase2; +using namespace emtf::phase2::algo; + +// Static +seg_theta_t TrackBuildingLayer::calc_theta_median(std::vector thetas) { + auto i_last = thetas.size() - 1; + + // Sort Thetas + // This will sort ascending order (lower-value means lower-index) + data::mergesort(&thetas[0], thetas.size(), [](seg_theta_t lower_index_value, seg_theta_t larger_index_value) -> int { + return lower_index_value > larger_index_value ? 1 : 0; + }); + + // Check if any model_thm_site is null + // Since the theta array has been sorted, it's enough + // to check the last index, because the invalid value will be the max + seg_theta_t invalid_theta = -1; // This maps to 255 since it underflows + + bool any_invalid = thetas[i_last] == invalid_theta; + + // Calculate median + if (any_invalid) { + // Use the min value as the median if there are any invalid thetas + return thetas[0]; + } else { + // Calculate the median if all thetas are valid + return data::getMedianOfSorted(&thetas[0], thetas.size()); + } +} + +// Members +TrackBuildingLayer::TrackBuildingLayer(const EMTFContext& context) : context_(context) {} + +void TrackBuildingLayer::apply(const segment_collection_t& segments, + const std::vector& roads, + const bool& displaced_en, + std::vector& tracks) const { + // Apply + for (unsigned int i_road = 0; i_road < roads.size(); ++i_road) { + // Get road and track + const auto& road = roads[i_road]; + auto& track = tracks.emplace_back(); + + // Initialize track + track.phi = 0; + track.theta = 0; + track.valid = 0; + + for (unsigned int site_id = 0; site_id < v3::kNumTrackSites; ++site_id) { + track.site_segs[site_id] = 0; + track.site_mask[site_id] = 0; + track.site_rm_mask[site_id] = 0; + } + + for (unsigned int i_feature = 0; i_feature < v3::kNumTrackFeatures; ++i_feature) { + track.features[i_feature] = 0; + } + + // Short-Circuit: If the road has quality-0 skip it + if (road.quality == 0) { + continue; + } + + // Debug Info + if (this->context_.config_.verbosity_ > 1) { + if (i_road == 0) { + edm::LogInfo("L1TEMTFpp") << std::endl; + edm::LogInfo("L1TEMTFpp") << "===========================================================================" + << std::endl; + edm::LogInfo("L1TEMTFpp") << "BEGIN TRACK BUILDING" << std::endl; + edm::LogInfo("L1TEMTFpp") << "---------------------------------------------------------------------------" + << std::endl; + } + + edm::LogInfo("L1TEMTFpp") << "***************************************************************************" + << std::endl; + edm::LogInfo("L1TEMTFpp") << "Begin building track " << i_road << std::endl; + } + + // Attach segments + attachSegments(segments, road, displaced_en, track); + + // Debug Info + if (this->context_.config_.verbosity_ > 1) { + edm::LogInfo("L1TEMTFpp") << "End building track " << i_road << std::endl; + + if (i_road == (roads.size() - 1)) { + edm::LogInfo("L1TEMTFpp") << "---------------------------------------------------------------------------" + << std::endl; + edm::LogInfo("L1TEMTFpp") << "END TRACK BUILDING" << std::endl; + edm::LogInfo("L1TEMTFpp") << "===========================================================================" + << std::endl; + } + } + } +} + +void TrackBuildingLayer::attachSegments(const segment_collection_t& segments, + const road_t& road, + const bool& displaced_en, + track_t& track) const { + // =========================================================================== + // Constants + // --------------------------------------------------------------------------- + seg_theta_t invalid_theta = -1; // This will map to 255 since it underflows + + // =========================================================================== + // Unpack road + // --------------------------------------------------------------------------- + // trk_col: Recall that the hitmap is 288 cols wide, and the full chamber hitmap is 315 cols; + // the chamber hitmap doesn't fit in the hitmap, so we skipped the first 27 cols. + // In order to calculate the full hitmap col, we need to add back the 27 cols that we skipped. + // sector_col: The sector's column is the center col of the phi map adding back the 27 skipped cols. + const auto trk_zone = road.zone; + const auto trk_pattern = road.pattern; + const auto trk_quality = road.quality; + + int bit_sel_zone = (1u << trk_zone); + + const trk_col_t trk_col = road.col + v3::kHitmapCropColStart; + const trk_col_t sector_col = static_cast(v3::kHitmapNCols / 2) + v3::kHitmapCropColStart; + + // =========================================================================== + // Initialize vars + // --------------------------------------------------------------------------- + std::array trk_seg_phi_diff; + std::array trk_seg_theta; + + for (unsigned int site_id = 0; site_id < v3::kNumTrackSites; ++site_id) { + trk_seg_phi_diff[site_id] = 0; + trk_seg_theta[site_id] = 0; + } + + // =========================================================================== + // Unpack model + // --------------------------------------------------------------------------- + const auto& model = context_.model_; + const auto& model_hm = model.zones_[trk_zone].hitmap; + const auto& model_ftc = model.features_; + + auto* model_pat = &(model.zones_[trk_zone].prompt_patterns[trk_pattern]); + + if (displaced_en) { + model_pat = &(model.zones_[trk_zone].disp_patterns[trk_pattern]); + } + + // =========================================================================== + // Convert column center to emtf_phi units + // --------------------------------------------------------------------------- + // Each column is emtf_phi=1<(trk_col) << v3::kHitmapColFactorLog2) + (1 << (v3::kHitmapColFactorLog2 - 1)); + seg_phi_t sector_abs_phi = + (static_cast(sector_col) << v3::kHitmapColFactorLog2) + (1 << (v3::kHitmapColFactorLog2 - 1)); + + // Calculate track phi + // Note this is the track phi with respect to the sector center + trk_feature_t trk_rel_phi = static_cast(trk_abs_phi) - static_cast(sector_abs_phi); + + // =========================================================================== + // Get pattern info for each row + // --------------------------------------------------------------------------- + std::array trk_pat_begin; + std::array trk_pat_center; + std::array trk_pat_end; + std::array trk_pat_phi; + + for (unsigned int i_row = 0; i_row < v3::kHitmapNRows; ++i_row) { + // Get the model pattern + const auto& model_pat_row = (*model_pat)[i_row]; + + // Offset the pattern's begin, center, and end by the track column + trk_pat_begin[i_row] = trk_col + model_pat_row.begin; + trk_pat_center[i_row] = trk_col + model_pat_row.center; + trk_pat_end[i_row] = trk_col + model_pat_row.end; + trk_pat_phi[i_row] = 0; + + // Short-Circuit: If the pattern's center is less than the padding used + // when matching the pattern to the hitmap then the pattern center is 0. + // This is because at that point, the center is out-of-bounds. + if (trk_pat_center[i_row] <= v3::kPatternMatchingPadding) + continue; + + // When the center is beyond the padding, then the pattern + // is in-bound, therefore we subtract the padding offset. + // To get the center in terms of the non-padded row BW we need to remove padding + // since col-padding + 1 should map to 1 in the non-padded hitmap + const auto& temp_trk_pat_center = trk_pat_center[i_row] - v3::kPatternMatchingPadding; + + // Convert the pattern center to emtf_phi units + trk_pat_phi[i_row] = (static_cast(temp_trk_pat_center) << v3::kHitmapColFactorLog2) + + (1 << (v3::kHitmapColFactorLog2 - 1)); + } + + // =========================================================================== + // Select segments using phi only + // --------------------------------------------------------------------------- + + // clang-format off + std::vector> site_chambers = { + { 0, 1, 2, 9, 10, 11, 45}, // ME1/1 + { 3, 4, 5, 12, 13, 14, 46}, // ME1/2 + { 18, 19, 20, 48, 21, 22, 23, 24, 25, 26, 49}, // ME2/1 + ME2/2 + { 27, 28, 29, 50, 30, 31, 32, 33, 34, 35, 51}, // ME3/1 + ME3/2 + { 36, 37, 38, 52, 39, 40, 41, 42, 43, 44, 53}, // ME4/1 + ME4/2 + { 57, 58, 59, 66, 67, 68, 100}, // RE1/2 + { 75, 76, 77, 78, 79, 80, 103}, // RE2/2 + { 81, 82, 83, 104, 84, 85, 86, 87, 88, 89, 105}, // RE3/1 + RE3/2 + { 90, 91, 92, 106, 93, 94, 95, 96, 97, 98, 107}, // RE4/1 + RE4/2 + { 54, 55, 56, 63, 64, 65, 99}, // GE1/1 + { 72, 73, 74, 102}, // GE2/1 + {108, 109, 110, 111, 112, 113, 114} // ME0 + }; + + std::vector site_chamber_orders = { + 0, 0, 2, 2, 2, 0, 0, 2, 2, 0, 1, 0 + }; + + std::vector> chamber_orders = { + {-1, -1, 6, -1, 0, 1, -1, 2, 3, -1, 4, 5}, + { 3, -1, -1, 0, -1, -1, 1, -1, -1, 2, -1, -1}, + { 3, -1, 10, 0, 4, 5, 1, 6, 7, 2, 8, 9} + }; + // clang-format on + + auto n_rows = model_hm.size(); + + for (unsigned int i_row = 0; i_row < n_rows; ++i_row) { // Begin loop rows + + const auto& model_hm_row = model_hm[i_row]; + + const auto& trk_pat_row_begin = trk_pat_begin[i_row]; + const auto& trk_pat_row_end = trk_pat_end[i_row]; + const auto& trk_pat_row_phi = trk_pat_phi[i_row]; + + if (this->context_.config_.verbosity_ > 2) { + edm::LogInfo("L1TEMTFpp") << "Pattern Row:" + << " row " << i_row << " begin " << trk_pat_row_begin << " end " << trk_pat_row_end + << " phi " << trk_pat_row_phi << std::endl; + } + + for (const auto& model_hm_site : model_hm_row) { // Begin loop sites in row + + const int site_id = static_cast(model_hm_site.id); + + auto& site_seg_id = track.site_segs[site_id]; + auto& site_bit = track.site_mask[site_id]; + auto& site_min_phi_diff = trk_seg_phi_diff[site_id]; + + const auto& s_chambers = site_chambers[site_id]; + const auto& s_chamber_order_id = site_chamber_orders[site_id]; + const auto& s_chamber_order = chamber_orders[s_chamber_order_id]; + + for (const auto& chamber_idx : s_chamber_order) { // Begin loop chambers in site + + if (chamber_idx == -1) + continue; + + int chamber_id = s_chambers[chamber_idx]; + + for (unsigned int i_ch_seg = 0; i_ch_seg < v3::kChamberSegments; ++i_ch_seg) { // Begin loop segments + + const int seg_id = chamber_id * v3::kChamberSegments + i_ch_seg; + const auto& seg = segments[seg_id]; + + // Short-Circuit: If the segment is invalid move on + if (!seg.valid) { + continue; + } + + // Short-Circuit: If the segment is not in the zone move on + if ((seg.zones & bit_sel_zone) != bit_sel_zone) { + continue; + } + + // Short-Circuit: If the segment is outside of the pattern move on + const trk_col_t seg_col = (seg.phi >> 4) + v3::kPatternMatchingPadding; + + if (!(trk_pat_row_begin <= seg_col && seg_col <= trk_pat_row_end)) { + continue; + } + + // Calculate abs diff between the pattern's row phi and the segment's phi + seg_phi_t diff; + + if (trk_pat_row_phi > seg.phi) { + diff = trk_pat_row_phi - seg.phi; + } else { + diff = seg.phi - trk_pat_row_phi; + } + + if (this->context_.config_.verbosity_ > 2) { + edm::LogInfo("L1TEMTFpp") << "Site candidate:" + << " site_id " << site_id << " seg_id " << seg_id << " seg_phi " << seg.phi + << " seg_theta1 " << seg.theta1 << " seg_theta2 " << seg.theta2 << " seg_bend " + << seg.bend << std::endl; + } + + // Short-Circuit: If the difference is larger than the min diff move on + if (site_bit == 1 && site_min_phi_diff <= diff) + continue; + + // Select better segment + site_seg_id = seg_id; + site_bit = 1; + site_min_phi_diff = diff; + } // End loop segments + + } // End loop chambers in site + + // Debug Info + if (this->context_.config_.verbosity_ > 2 && site_bit == 1) { + edm::LogInfo("L1TEMTFpp") << "Segment attached:" + << " site_id " << site_id << " seg_id " << site_seg_id << " seg_phi " + << segments[site_seg_id].phi << " seg_theta1 " << segments[site_seg_id].theta1 + << " seg_theta2 " << segments[site_seg_id].theta2 << " seg_bend " + << segments[site_seg_id].bend << std::endl; + } + } // End loop sites in row + + } // End loop rows + + // =========================================================================== + // Calculate theta medians + // --------------------------------------------------------------------------- + const auto& model_thmc = model.theta_medians_; + + std::vector theta_medians; + + for (const auto& model_thm : model_thmc) { // Begin loop model theta medians + + std::vector group_medians; + + for (const auto& model_thm_group : model_thm) { // Begin loop theta median groups + + std::vector group; + + for (const auto& model_thm_site : model_thm_group) { // Begin loop group sites + int site_id = static_cast(model_thm_site.id); + + const auto& site_bit = track.site_mask[site_id]; + + // Initialize as invalid theta + auto& theta = group.emplace_back(invalid_theta); + + // Short-Circuit: If no segment was selected, move on. + if (site_bit == 0) + continue; + + // Get selected segment's theta value + const auto& site_seg_id = track.site_segs[site_id]; + const auto& site_seg = segments[site_seg_id]; + + if (model_thm_site.theta_id == theta_id_t::kTheta1) { + theta = site_seg.theta1; + } else if (model_thm_site.theta_id == theta_id_t::kTheta2) { + theta = site_seg.theta2; + } + + // If the segment theta is 0 this is invalid theta value + if (theta == 0) { + theta = invalid_theta; + } + } // End loop group sites + + // Calculate theta median + if (this->context_.config_.verbosity_ > 2) { + for (const auto& theta : group) { + edm::LogInfo("L1TEMTFpp") << "theta " << theta << std::endl; + } + } + + auto group_median = calc_theta_median(group); + group_medians.push_back(group_median); + + if (this->context_.config_.verbosity_ > 2) { + edm::LogInfo("L1TEMTFpp") << "group_median " << group_median << std::endl; + } + } // End loop theta median groups + + // Calculate model_thm_group median + auto theta_median = calc_theta_median(group_medians); + theta_medians.push_back(theta_median); + + if (this->context_.config_.verbosity_ > 2) { + edm::LogInfo("L1TEMTFpp") << "theta_median " << theta_median << std::endl; + } + } // End loop theta medians + + // =========================================================================== + // Select track theta + // --------------------------------------------------------------------------- + seg_theta_t trk_abs_theta; + + if (trk_zone != 2) { + trk_abs_theta = theta_medians[0]; + } else { + trk_abs_theta = theta_medians[1]; + } + + // If median is invalid, try station 1 median + if (trk_abs_theta == invalid_theta) { + trk_abs_theta = theta_medians[2]; + } + + // If all medians are invalid use 0 (0 is an invalid theta) + if (trk_abs_theta == invalid_theta) { + trk_abs_theta = 0; + } + + // =========================================================================== + // Compare segment theta to track theta + // --------------------------------------------------------------------------- + + // if theta_window < diff, it is invalid + + // clang-format off + std::vector> site_theta_window = { + {5, 0, 2, 2, 2, 34, 0, 3, 3, 5, 6, 5}, + {5, 9, 5, 4, 5, 14, 7, 7, 7, 7, 7, 4}, + {11, 6, 5, 6, 6, 10, 8, 8, 9, 8, 0, 0} + }; + // clang-format on + + if (displaced_en) { + // clang-format off + site_theta_window = { + {14, 40, 4, 3, 3, 45, 0, 4, 4, 15, 8, 13}, + {16, 18, 7, 5, 5, 22, 7, 7, 8, 17, 9, 14}, + {26, 15, 8, 9, 9, 17, 11, 9, 10, 26, 21, 0} + }; + // clang-format on + } + + for (unsigned int site_id = 0; site_id < v3::kNumTrackSites; ++site_id) { + auto& site_bit = track.site_mask[site_id]; + auto& site_rm_bit = track.site_rm_mask[site_id]; + + // Get Theta Window + const auto& theta_window = site_theta_window[trk_zone][site_id]; + + // Short-Circuit: If no segment was selected, move on. + if (site_bit == 0) + continue; + + const auto& site_seg_id = track.site_segs[site_id]; + const auto& site_seg = segments[site_seg_id]; + + // Init differences with out-of-bounds values + seg_theta_t diff_1 = theta_window + 1; + seg_theta_t diff_2 = theta_window + 1; + + // Calculate abs theta 1 diff + if (site_seg.theta1 != 0) { + if (site_seg.theta1 < trk_abs_theta) { + diff_1 = trk_abs_theta - site_seg.theta1; + } else { + diff_1 = site_seg.theta1 - trk_abs_theta; + } + } + + // Calculate abs theta 2 diff + if (site_seg.theta2 != 0) { + if (site_seg.theta2 < trk_abs_theta) { + diff_2 = trk_abs_theta - site_seg.theta2; + } else { + diff_2 = site_seg.theta2 - trk_abs_theta; + } + } + + // Select the theta with the smallest difference + if (diff_1 <= diff_2 && diff_1 < theta_window) { + // Select theta 1 as the correct theta value + trk_seg_theta[site_id] = site_seg.theta1; + } else if (diff_2 < theta_window) { + // Select theta 2 as the correct theta value + trk_seg_theta[site_id] = site_seg.theta2; + } else { + // Invalidate site if both differences are outside of the theta window + site_bit = 0; + site_rm_bit = 1; + + // Debug Info + if (this->context_.config_.verbosity_ > 4) { + edm::LogInfo("L1TEMTFpp") << "Segment outside of theta window; detatched:" + << " site_id " << site_id << " seg_id " << site_seg_id << " seg_phi " << site_seg.phi + << " seg_theta1 " << site_seg.theta1 << " seg_theta2 " << site_seg.theta2 + << std::endl; + } + } + } + + // =========================================================================== + // Assign Data + // --------------------------------------------------------------------------- + track.zone = trk_zone; + track.col = trk_col; + track.pattern = trk_pattern; + track.quality = trk_quality; + track.phi = trk_abs_phi; + track.theta = trk_abs_theta; + track.valid = 1; + + // =========================================================================== + // Fill features + // --------------------------------------------------------------------------- + int i_feature = 0; + + for (auto& model_ft : model_ftc) { + for (auto& model_ft_site : model_ft.sites) { + int site_id = static_cast(model_ft_site); + + const auto& site_seg_id = track.site_segs[site_id]; + const auto& site_bit = track.site_mask[site_id]; + const auto& site_seg = segments[site_seg_id]; + + auto& trk_feature = track.features[i_feature++]; + + // Short-Circuit: No segment attached + if (site_bit == 0) { + continue; + } + + // Fill features + if (model_ft.id == feature_id_t::kPhi) { + // Note: This is the segment's phi with respect to the track's abs phi + trk_feature = static_cast(site_seg.phi) - static_cast(trk_abs_phi); + } else if (model_ft.id == feature_id_t::kTheta) { + // Note: This is the segment's theta with respect to the track's abs theta + trk_feature = static_cast(trk_seg_theta[site_id]) - static_cast(trk_abs_theta); + } else if (model_ft.id == feature_id_t::kBend) { + trk_feature = site_seg.bend; + } else if (model_ft.id == feature_id_t::kQuality) { + trk_feature = site_seg.qual1; + } + } + } + + // Additional features + track.features[i_feature++] = trk_quality > 0 ? trk_rel_phi : decltype(trk_rel_phi)(0); + track.features[i_feature++] = trk_quality > 0 ? trk_abs_theta : decltype(trk_abs_theta)(0); + track.features[i_feature++] = trk_quality; + track.features[i_feature++] = 0; // unused + + // Debug Info + if (this->context_.config_.verbosity_ > 1) { + edm::LogInfo("L1TEMTFpp") << "Track" + << " zone " << track.zone << " col " << track.col << " pat " << track.pattern << " qual " + << track.quality << " sector_abs_phi " << sector_abs_phi << " abs_phi " << track.phi + << " rel_phi " << trk_rel_phi << " abs_theta " << track.theta << " features " + << std::endl; + + for (unsigned int i = 0; i < v3::kNumTrackFeatures; ++i) { + if (i > 0) { + edm::LogInfo("L1TEMTFpp") << " "; + } + + edm::LogInfo("L1TEMTFpp") << track.features[i]; + } + + edm::LogInfo("L1TEMTFpp") << std::endl; + } +} diff --git a/L1Trigger/L1TMuonEndCapPhase2/src/DAQ/CSCTPCollector.cc b/L1Trigger/L1TMuonEndCapPhase2/src/DAQ/CSCTPCollector.cc new file mode 100644 index 0000000000000..4d88c4c2c4bc5 --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/src/DAQ/CSCTPCollector.cc @@ -0,0 +1,209 @@ +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/ConsumesCollector.h" +#include "FWCore/MessageLogger/interface/MessageLogger.h" + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFConfiguration.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFConstants.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFContext.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/TPrimitives.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/SubsystemTags.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Utils/DebugUtils.h" + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/CSCTPCollector.h" + +using namespace emtf::phase2; + +CSCTPCollector::CSCTPCollector(const EMTFContext& context, edm::ConsumesCollector& i_consumes_collector) + : context_(context), + input_token_(i_consumes_collector.consumes(context.config_.csc_input_)) {} + +void CSCTPCollector::collect(const edm::Event& i_event, BXTPCMap& bx_tpc_map) const { + edm::Handle csc_digis; + i_event.getByToken(input_token_, csc_digis); + + // Collect + TPCollection tpc; + + auto chamber = csc_digis->begin(); + auto chend = csc_digis->end(); + + for (; chamber != chend; ++chamber) { + auto digi = (*chamber).second.first; + auto dend = (*chamber).second.second; + + for (; digi != dend; ++digi) { + tpc.emplace_back((*chamber).first, *digi); + } + } + + // Find wires + std::map, std::vector > chamber_wires_map; + + for (auto& tp_entry : tpc) { + const auto& tp_det_id = tp_entry.tp_.detId(); + + const CSCData& tp_data = tp_entry.tp_.getCSCData(); + const int tp_bx = tp_data.bx + this->context_.config_.csc_bx_shift_; + const int tp_wire = tp_data.keywire; + + auto key = std::make_pair(tp_det_id.rawId(), tp_bx); + auto res = chamber_wires_map.find(key); + + if (res == chamber_wires_map.end()) { + // Case: Chamber not found + chamber_wires_map[key].push_back(tp_wire); + } else { + // Case: Chamber found + // Lookup wire if found move on, otherwise add it. + bool wire_found = false; + + auto& chamber_wires = res->second; + + for (const auto& a_wire : chamber_wires) { + // Short-Circuit: If wire matches stop + if (a_wire == tp_wire) { + wire_found = true; + break; + } + } + + // Case: Wire not found, add it. + if (!wire_found) { + chamber_wires.push_back(tp_wire); + } + } + } + + // Map to BX + for (auto& tp_entry : tpc) { + const auto& tp_det_id = tp_entry.tp_.detId(); + const CSCData& tp_data = tp_entry.tp_.getCSCData(); + + const int tp_endcap = tp_det_id.endcap(); // 1: +endcap, 2: -endcap + const int tp_endcap_pm = (tp_endcap == 2) ? -1 : tp_endcap; // 1: +endcap, -1: -endcap + const int tp_sector = tp_det_id.triggerSector(); + const int tp_station = tp_det_id.station(); + const int tp_ring = tp_det_id.ring(); + const int tp_chamber = tp_det_id.chamber(); + const int tp_layer = tp_det_id.layer(); + + const int tp_csc_id = tp_data.cscID; + + const int tp_bx = tp_data.bx + this->context_.config_.csc_bx_shift_; + + // Get wires + int tp_wire1 = tp_data.keywire; + int tp_wire2 = -1; + + auto tp_wire_key = std::make_pair(tp_det_id.rawId(), tp_bx); + const auto& tp_wires = chamber_wires_map.at(tp_wire_key); + + emtf_assert((!tp_wires.empty()) && (tp_wires.size() <= 2)); + + if (tp_wires.size() > 1) { + tp_wire1 = tp_wires.at(0); + tp_wire2 = tp_wires.at(1); + } + + // Calculate detector info + const int tp_subsector = csc::getTriggerSubsector(tp_station, tp_chamber); + const auto tp_face_dir = csc::getFaceDirection(tp_station, tp_ring, tp_chamber); + + // Assertion checks + const auto& [max_strip, max_wire] = csc::getMaxStripAndWire(tp_station, tp_ring); + const auto& [max_pattern, max_quality] = csc::getMaxPatternAndQuality(tp_station, tp_ring); + + emtf_assert(kMinEndcap <= tp_endcap && tp_endcap <= kMaxEndcap); + emtf_assert(kMinTrigSector <= tp_sector && tp_sector <= kMaxTrigSector); + emtf_assert((0 <= tp_subsector) and (tp_subsector <= 2)); + emtf_assert(1 <= tp_station && tp_station <= 4); + emtf_assert(1 <= tp_ring && tp_ring <= 4); + emtf_assert(1 <= tp_chamber && tp_chamber <= 36); + emtf_assert(1 <= tp_csc_id && tp_csc_id <= 9); + emtf_assert(tp_data.strip < max_strip); + emtf_assert(tp_data.keywire < max_wire); + emtf_assert(tp_data.pattern < max_pattern); + emtf_assert(0 < tp_data.quality && tp_data.quality < max_quality); + emtf_assert(tp_data.valid); + + // Check for corrupted LCT data. Data corruption could occur due to software + // or hardware issues, if corrupted, reject the LCT. + if (!(tp_data.strip < max_strip)) { + edm::LogWarning("L1TEMTFpp") << "Found error in LCT strip: " << tp_data.strip << " (allowed range: 0-" + << max_strip - 1 << ")."; + + edm::LogWarning("L1TEMTFpp") + << "From endcap " << tp_endcap << ", sector " << tp_sector << ", station " << tp_station << ", ring " + << tp_ring << ", cscid " << tp_csc_id + << ". (Note that this LCT may be reported multiple times. See source code for explanations.)"; + + continue; + } + + if (!(tp_data.keywire < max_wire)) { + edm::LogWarning("L1TEMTFpp") << "Found error in LCT wire: " << tp_data.keywire << " (allowed range: 0-" + << max_wire - 1 << ")."; + + edm::LogWarning("L1TEMTFpp") + << "From endcap " << tp_endcap << ", sector " << tp_sector << ", station " << tp_station << ", ring " + << tp_ring << ", cscid " << tp_csc_id + << ". (Note that this LCT may be reported multiple times. See source code for explanations.)"; + + continue; + } + + if (!(tp_data.valid == true)) { + edm::LogWarning("L1TEMTFpp") << "Found error in LCT valid: " << tp_data.valid << " (allowed value: 1)."; + + edm::LogWarning("L1TEMTFpp") + << "From endcap " << tp_endcap << ", sector " << tp_sector << ", station " << tp_station << ", ring " + << tp_ring << ", cscid " << tp_csc_id + << ". (Note that this LCT may be reported multiple times. See source code for explanations.)"; + + continue; + } + + if (!(tp_data.pattern < max_pattern)) { + edm::LogWarning("L1TEMTFpp") << "Found error in LCT pattern: " << tp_data.pattern << " (allowed range: 0-" + << max_pattern - 1 << ")."; + + edm::LogWarning("L1TEMTFpp") + << "From endcap " << tp_endcap << ", sector " << tp_sector << ", station " << tp_station << ", ring " + << tp_ring << ", cscid " << tp_csc_id + << ". (Note that this LCT may be reported multiple times. See source code for explanations.)"; + + continue; + } + + if (!(0 < tp_data.quality && tp_data.quality < max_quality)) { + edm::LogWarning("L1TEMTFpp") << "Found error in LCT quality: " << tp_data.quality << " (allowed range: 1-" + << max_quality - 1 << ")."; + + edm::LogWarning("L1TEMTFpp") + << "From endcap " << tp_endcap << ", sector " << tp_sector << ", station " << tp_station << ", ring " + << tp_ring << ", cscid " << tp_csc_id + << ". (Note that this LCT may be reported multiple times. See source code for explanations.)"; + + continue; + } + + // Add info + tp_entry.info_.bx = tp_bx; + + tp_entry.info_.endcap = tp_endcap; + tp_entry.info_.endcap_pm = tp_endcap_pm; + tp_entry.info_.sector = tp_sector; + tp_entry.info_.subsector = tp_subsector; + tp_entry.info_.station = tp_station; + tp_entry.info_.ring = tp_ring; + tp_entry.info_.chamber = tp_chamber; + tp_entry.info_.layer = tp_layer; + + tp_entry.info_.csc_id = tp_csc_id; + tp_entry.info_.csc_facing = tp_face_dir; + tp_entry.info_.csc_first_wire = tp_wire1; + tp_entry.info_.csc_second_wire = tp_wire2; + + bx_tpc_map[tp_bx].push_back(tp_entry); + } +} diff --git a/L1Trigger/L1TMuonEndCapPhase2/src/DAQ/CSCTPConverter.cc b/L1Trigger/L1TMuonEndCapPhase2/src/DAQ/CSCTPConverter.cc new file mode 100644 index 0000000000000..2b014e3e0595f --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/src/DAQ/CSCTPConverter.cc @@ -0,0 +1,175 @@ +#include "FWCore/MessageLogger/interface/MessageLogger.h" + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFConfiguration.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFConstants.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFContext.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Data/HostLut.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Data/SiteLut.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Data/ZoneLut.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/SubsystemTags.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Utils/DebugUtils.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Utils/CSCUtils.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Utils/TPUtils.h" + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/CSCTPConverter.h" + +using namespace emtf::phase2; + +CSCTPConverter::CSCTPConverter(const EMTFContext& context, const int& endcap, const int& sector) + : context_(context), endcap_(endcap), sector_(sector) {} + +void CSCTPConverter::convert(const TriggerPrimitive& tp, const TPInfo& tp_info, EMTFHit& hit) const { + // Unpack Id + const auto& tp_hit_id = tp_info.hit_id; + const auto& tp_segment_id = tp_info.segment_id; + + // Unpack trigger primitive + const auto& tp_det_id = tp.detId(); + const auto& tp_data = tp.getCSCData(); + + // Unpack detector info + const auto tp_subsystem = L1TMuon::kCSC; + + const int tp_raw_id = tp_det_id.rawId(); + + const int tp_endcap_pm = tp_info.endcap_pm; + const int tp_subsector = tp_info.subsector; + const int tp_chamber = tp_info.chamber; + const int tp_station = tp_info.station; + const int tp_ring = tp_info.ring; + const int tp_layer = tp_info.layer; + + const int tp_csc_id = tp_info.csc_id; + const auto tp_csc_facing = tp_info.csc_facing; + + // Unpack data + const int tp_strip = tp_data.strip; + const int tp_strip_quart_bit = tp_data.strip_quart_bit; + const int tp_strip_eighth_bit = tp_data.strip_eighth_bit; + const int tp_strip_quart = tp_data.strip_quart; + const int tp_strip_eighth = tp_data.strip_eighth; + + const int tp_wire1 = tp_info.csc_first_wire; + const int tp_wire2 = tp_info.csc_second_wire; + + int tp_bend; + const int tp_slope = tp_data.slope; + + const int tp_bx = tp_info.bx; + const int tp_subbx = 0; // no fine resolution timing + const float tp_time = 0; // no fine resolution timing. Note: Check with Efe, Jia Fu gets this from digi directly. + + const auto tp_selection = tp_info.selection; + + const int tp_pattern = tp_data.pattern; + const int tp_quality = 6; + + // Apply CSC Run 2 pattern -> bend conversion + // Override tp_bend + constexpr int tp_bend_lut_size = 11; + constexpr int tp_bend_lut[tp_bend_lut_size] = {-5, 5, -4, 4, -3, 3, -2, 2, -1, 1, 0}; + emtf_assert(tp_pattern < tp_bend_lut_size); + tp_bend = tp_bend_lut[tp_pattern]; + tp_bend *= tp_endcap_pm; // sign flip depending on endcap + + // ID scheme used in FW + const int tp_ilink = tp_info.ilink; + + // Get Global Coordinates + const GlobalPoint& gp_w1 = this->context_.geometry_translator_.getGlobalPoint(tp); + const float glob_phi_w1 = tp::radToDeg(gp_w1.phi().value()); + const float glob_theta_w1 = tp::radToDeg(gp_w1.theta().value()); + const double glob_rho_w1 = gp_w1.perp(); + const double glob_z_w1 = gp_w1.z(); + + // Calculate EMTF Values + const int emtf_phi_w1 = tp::calcPhiInt(sector_, glob_phi_w1); + const int emtf_bend_w1 = std::clamp(tp_bend * 4, -16, 15); // 5-bit, signed + const int emtf_theta_w1 = tp::calcThetaInt(tp_endcap_pm, glob_theta_w1); + const int emtf_qual_w1 = std::clamp(tp_quality, 0, 15); // 4-bit, unsigned + const int emtf_site_w1 = context_.site_lut_.lookup({tp_subsystem, tp_station, tp_ring}); + const int emtf_host_w1 = context_.host_lut_.lookup({tp_subsystem, tp_station, tp_ring}); + const int emtf_zones_w1 = context_.zone_lut_.getZones(emtf_host_w1, emtf_theta_w1); + + // Calculated Ambiguous Info + int emtf_theta_w2 = 0; + int emtf_qual_w2 = tp_pattern; + + if (tp_wire2 > -1) { + auto tp_w2 = tp; + + tp_w2.accessCSCData().keywire = tp_wire2; + + const GlobalPoint& gp_w2 = this->context_.geometry_translator_.getGlobalPoint(tp_w2); + const double glob_theta_w2 = tp::radToDeg(gp_w2.theta().value()); + + emtf_theta_w2 = tp::calcThetaInt(tp_endcap_pm, glob_theta_w2); + } + + emtf_assert((0 <= emtf_phi_w1) and (emtf_phi_w1 < 5040)); + emtf_assert((1 <= emtf_theta_w1) and (emtf_theta_w1 < 128)); + emtf_assert((0 <= emtf_theta_w2) and (emtf_theta_w2 < 128)); + + // Get flags + const bool tp_flag_neighbor = (tp_selection == TPSelection::kNeighbor); + const bool tp_flag_substitute = tp_info.flag_substitute; + const bool tp_flag_valid = tp_data.valid; + + // Set properties + hit.setId(tp_hit_id); + + hit.setRawDetId(tp_raw_id); + hit.setSubsystem(L1TMuon::kCSC); + hit.setEndcap(tp_endcap_pm); + hit.setSector(sector_); + hit.setSubsector(tp_subsector); + hit.setStation(tp_station); + hit.setRing(tp_ring); + hit.setLayer(tp_layer); + hit.setChamber(tp_chamber); + + hit.setCscId(tp_csc_id); + hit.setCscFR(tp_csc_facing == csc::Facing::kRear); + + hit.setStrip(tp_strip); + hit.setStripLo(tp_strip); + hit.setStripHi(tp_strip); + hit.setStripQuart(tp_strip_quart); + hit.setStripEighth(tp_strip_eighth); + hit.setStripQuartBit(tp_strip_quart_bit); + hit.setStripEighthBit(tp_strip_eighth_bit); + + hit.setWire1(tp_wire1); + hit.setWire2(tp_wire2); + + hit.setBend(tp_bend); + hit.setSlope(tp_slope); + + hit.setBx(tp_bx); + hit.setSubbx(tp_subbx); + + hit.setQuality(tp_quality); + hit.setPattern(tp_pattern); + + hit.setGlobPhi(glob_phi_w1); + hit.setGlobTheta(glob_theta_w1); + hit.setGlobPerp(glob_rho_w1); + hit.setGlobZ(glob_z_w1); + hit.setGlobTime(tp_time); + + hit.setEmtfChamber(tp_ilink); + hit.setEmtfSegment(tp_segment_id); + hit.setEmtfPhi(emtf_phi_w1); + hit.setEmtfBend(emtf_bend_w1); + hit.setEmtfTheta1(emtf_theta_w1); + hit.setEmtfTheta2(emtf_theta_w2); + hit.setEmtfQual1(emtf_qual_w1); + hit.setEmtfQual2(emtf_qual_w2); + hit.setEmtfSite(emtf_site_w1); + hit.setEmtfHost(emtf_host_w1); + hit.setEmtfZones(emtf_zones_w1); + + hit.setFlagNeighbor(tp_flag_neighbor); + hit.setFlagSubstitute(tp_flag_substitute); + hit.setFlagValid(tp_flag_valid); +} diff --git a/L1Trigger/L1TMuonEndCapPhase2/src/DAQ/CSCTPSelector.cc b/L1Trigger/L1TMuonEndCapPhase2/src/DAQ/CSCTPSelector.cc new file mode 100644 index 0000000000000..383856addd562 --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/src/DAQ/CSCTPSelector.cc @@ -0,0 +1,125 @@ +#include "FWCore/MessageLogger/interface/MessageLogger.h" + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFConfiguration.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFConstants.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFContext.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/SubsystemTags.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/TPrimitives.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Utils/DebugUtils.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Utils/CSCUtils.h" + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/CSCTPSelector.h" + +using namespace emtf::phase2; + +CSCTPSelector::CSCTPSelector(const EMTFContext& context, const int& endcap, const int& sector) + : context_(context), endcap_(endcap), sector_(sector) {} + +void CSCTPSelector::select(const TriggerPrimitive& tp, TPInfo tp_info, ILinkTPCMap& ilink_tpc_map) const { + emtf_assert(tp.subsystem() == L1TMuon::kCSC); + + // Map CSC trigger primitives to input links + int ilink = getInputLink(tp, tp_info); // Returns CSC "link" index (0 - 53) + + // Short-Circuit: Link not found (ilink = -1) + if (ilink < 0) { + return; + } + + // Should have at most 2 TP + if (ilink_tpc_map[ilink].size() < 2) { + ilink_tpc_map[ilink].emplace_back(tp, tp_info); + } else { + edm::LogWarning("L1TEMTFpp") << "\n******************* EMTF EMULATOR: SUPER-BIZZARE CASE *******************"; + edm::LogWarning("L1TEMTFpp") << "Found 3 CSC trigger primitives in the same chamber"; + + for (unsigned int i_tp = 0; i_tp < 3; i_tp++) { + const auto& tp_err = ((i_tp < 2) ? ilink_tpc_map[ilink].at(i_tp).tp_ : tp); + + edm::LogWarning("L1TEMTFpp") << "LCT #" << i_tp + 1 << ": BX " << tp_err.getBX() << ", endcap " + << tp_err.detId().endcap() << ", sector " + << tp_err.detId().triggerSector() << ", station " + << tp_err.detId().station() << ", ring " << tp_err.detId().ring() + << ", chamber " << tp_err.detId().chamber() << ", CSC ID " + << tp_err.getCSCData().cscID << ": strip " << tp_err.getStrip() << ", wire " + << tp_err.getWire(); + } + + edm::LogWarning("L1TEMTFpp") << "************************* ONLY KEEP FIRST TWO *************************\n\n"; + } +} + +// =========================================================================== +// Utils +// =========================================================================== +int CSCTPSelector::getInputLink(const TriggerPrimitive& tp, TPInfo& tp_info) const { + int ilink = -1; + + // Unpack detector info + const int tp_endcap = tp_info.endcap; + const int tp_sector = tp_info.sector; + const int tp_subsector = tp_info.subsector; + const int tp_station = tp_info.station; + const int tp_ring = tp_info.ring; + const int tp_csc_id = tp_info.csc_id; + + // Find selection type + auto tp_selection = TPSelection::kNone; + + if (csc::isTPInSector(endcap_, sector_, tp_endcap, tp_sector)) { + tp_selection = TPSelection::kNative; + } else if (this->context_.config_.include_neighbor_en_ && + csc::isTPInNeighborSector(endcap_, sector_, tp_endcap, tp_sector, tp_subsector, tp_station, tp_csc_id)) { + tp_selection = TPSelection::kNeighbor; + } else { // Short-Circuit: tp_selection = TPSelection::kNone + return ilink; + } + + // Get chamber input link for this sector processor + ilink = calcInputLink(tp_subsector, tp_station, tp_ring, tp_csc_id, tp_selection); + + // Add selection info + tp_info.ilink = ilink; + tp_info.selection = tp_selection; + + return ilink; +} + +// Returns CSC input "link". Index used by FW for unique chamber identification. +int CSCTPSelector::calcInputLink(const int& tp_subsector, + const int& tp_station, + const int& tp_ring, + const int& tp_csc_id, + const TPSelection& tp_selection) const { + int ilink = -1; + + // Links + // ME1,2,3,4 : 0..17, 18..26, 27..35, 36..44 + // ME1,2,3,4 (N) : 45..47, 48..49, 50..51, 52..53 + + if (tp_selection == TPSelection::kNative) { + const int ilink_offset = 0; + + if (tp_station == 1) { + ilink = ilink_offset + (tp_subsector - 1) * 9 + (tp_csc_id - 1); + } else { + ilink = ilink_offset + tp_station * 9 + (tp_csc_id - 1); + } + + emtf_assert((0 <= ilink) && (ilink < 45)); + } else { + const int ilink_offset = 45; + + if (tp_station == 1) { + ilink = ilink_offset + ((tp_station - 1) * 2) + (tp_csc_id - 1) / 3; + } else if (tp_ring == 1) { + ilink = ilink_offset + ((tp_station - 1) * 2) + 1; + } else { + ilink = ilink_offset + ((tp_station - 1) * 2) + 2; + } + + emtf_assert((45 <= ilink) && (ilink < 54)); + } + + return ilink; +} diff --git a/L1Trigger/L1TMuonEndCapPhase2/src/DAQ/GE0TPCollector.cc b/L1Trigger/L1TMuonEndCapPhase2/src/DAQ/GE0TPCollector.cc new file mode 100644 index 0000000000000..a029372420bef --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/src/DAQ/GE0TPCollector.cc @@ -0,0 +1,134 @@ +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/ConsumesCollector.h" + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFConfiguration.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFConstants.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFContext.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/SubsystemTags.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/TPrimitives.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Utils/CSCUtils.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Utils/DebugUtils.h" + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/GE0TPCollector.h" + +using namespace emtf::phase2; + +GE0TPCollector::GE0TPCollector(const EMTFContext& context, edm::ConsumesCollector& i_consumes_collector) + : context_(context), + input_token_(i_consumes_collector.consumes(context.config_.ge0_input_)) {} + +void GE0TPCollector::collect(const edm::Event& i_event, BXTPCMap& bx_tpc_map) const { + // Constants + // First quarter of GE0 chamber (5 deg) and last quarter + static const int me0_max_partition = 9; + static const int me0_nstrips = 384; + static const int me0_nphipositions = me0_nstrips * 2; + static const int phiposition_q1 = me0_nphipositions / 4; + static const int phiposition_q3 = (me0_nphipositions / 4) * 3; + + // Read GE0 digis + TPCollection tpc; + + edm::Handle me0_digis; + i_event.getByToken(input_token_, me0_digis); + + auto chamber = me0_digis->begin(); + auto chend = me0_digis->end(); + + for (; chamber != chend; ++chamber) { + auto digi = (*chamber).second.first; + auto dend = (*chamber).second.second; + + for (; digi != dend; ++digi) { + tpc.emplace_back((*chamber).first, *digi); + } + } + + // Map to BX + for (auto& tp_entry : tpc) { + const auto& tp_det_id = tp_entry.tp_.detId(); + const ME0Data& tp_data = tp_entry.tp_.getME0Data(); + + const int tp_region = tp_det_id.region(); // 0: barrel, +/-1: endcap + const int tp_endcap = (tp_region == -1) ? 2 : tp_region; // 1: +endcap, 2: -endcap + const int tp_endcap_pm = (tp_endcap == 2) ? -1 : tp_endcap; // 1: +endcap, -1: -endcap + const int tp_station = 1; // ME0DetId station was always 1! + const int tp_ring = 4; + const int tp_layer = tp_det_id.layer(); + const int tp_roll = tp_det_id.roll(); + const int tp_me0_chamber = tp_det_id.chamber(); + + const int tp_pad = tp_data.phiposition; + const int tp_partition = tp_data.partition; + const int tp_bx = tp_data.bx + this->context_.config_.me0_bx_shift_; + + // Reject if outside eta of 2.4 + if (tp_partition > me0_max_partition) { + continue; + } + + // Calculate EMTF Info + // Split 20-deg chamber into 10-deg chamber + // GE0 chamber is rotated by -5 deg relative to CSC chamber. + // GE0 chamber 1 starts at -10 deg, CSC chamber 1 starts at -5 deg. + const int tp_phiposition = tp_data.phiposition; // in half-strip unit + + int tp_chamber = (tp_me0_chamber - 1) * 2 + 1; + + if (tp_endcap == 1) { + // positive endcap + // phiposition increases counter-clockwise + if (tp_phiposition < phiposition_q1) { + tp_chamber = csc::getNext10DegChamber(tp_chamber); + } else if (tp_phiposition < phiposition_q3) { + // Do nothing + } else { + tp_chamber = csc::getPrev10DegChamber(tp_chamber); + } + } else { + // negative endcap + // phiposition increases clockwise + if (tp_phiposition < phiposition_q1) { + tp_chamber = csc::getPrev10DegChamber(tp_chamber); + } else if (tp_phiposition < phiposition_q3) { + // Do nothing + } else { + tp_chamber = csc::getNext10DegChamber(tp_chamber); + } + } + + const int tp_sector = csc::getTriggerSector(tp_station, tp_ring, tp_chamber); + const int tp_subsector = csc::getTriggerSubsector(tp_station, tp_chamber); + const int tp_csc_id = csc::getId(tp_station, tp_ring, tp_chamber); + const auto tp_csc_facing = csc::getFaceDirection(tp_station, tp_ring, tp_chamber); + + // Assertion checks + emtf_assert(kMinEndcap <= tp_endcap && tp_endcap <= kMaxEndcap); + emtf_assert(kMinTrigSector <= tp_sector && tp_sector <= kMaxTrigSector); + emtf_assert((1 <= tp_subsector) and (tp_subsector <= 2)); + emtf_assert(tp_station == 1); + emtf_assert(tp_ring == 4); + emtf_assert((1 <= tp_chamber) and (tp_chamber <= 36)); + emtf_assert(1 <= tp_csc_id && tp_csc_id <= 3); + emtf_assert(0 <= tp_pad && tp_pad <= 767); + emtf_assert(0 <= tp_partition && tp_partition <= 15); + + // Add info + tp_entry.info_.bx = tp_bx; + + tp_entry.info_.endcap = tp_endcap; + tp_entry.info_.endcap_pm = tp_endcap_pm; + tp_entry.info_.sector = tp_sector; + tp_entry.info_.subsector = tp_subsector; + tp_entry.info_.station = tp_station; + tp_entry.info_.ring = tp_ring; + tp_entry.info_.layer = tp_layer; + tp_entry.info_.roll = tp_roll; + tp_entry.info_.chamber = tp_chamber; + + tp_entry.info_.csc_id = tp_csc_id; + tp_entry.info_.csc_facing = tp_csc_facing; + + bx_tpc_map[tp_bx].push_back(tp_entry); + } +} diff --git a/L1Trigger/L1TMuonEndCapPhase2/src/DAQ/GE0TPConverter.cc b/L1Trigger/L1TMuonEndCapPhase2/src/DAQ/GE0TPConverter.cc new file mode 100644 index 0000000000000..b136e8db897c6 --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/src/DAQ/GE0TPConverter.cc @@ -0,0 +1,138 @@ +#include "FWCore/MessageLogger/interface/MessageLogger.h" + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFConfiguration.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFConstants.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFContext.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Data/HostLut.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Data/SiteLut.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Data/ZoneLut.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/SubsystemTags.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Utils/DebugUtils.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Utils/CSCUtils.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Utils/TPUtils.h" + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/GE0TPConverter.h" + +using namespace emtf::phase2; + +GE0TPConverter::GE0TPConverter(const EMTFContext& context, const int& endcap, const int& sector) + : context_(context), endcap_(endcap), sector_(sector) {} + +void GE0TPConverter::convert(const TriggerPrimitive& tp, const TPInfo& tp_info, EMTFHit& hit) const { + // Unpack Id + const auto& tp_hit_id = tp_info.hit_id; + const int tp_segment_id = tp_info.segment_id; + + // Unpack trigger primitive + const auto& tp_det_id = tp.detId(); + const auto& tp_data = tp.getME0Data(); + + // Unpack detector info + const auto tp_subsystem = L1TMuon::kME0; + + const int tp_raw_id = tp_det_id.rawId(); + + const int tp_endcap_pm = tp_info.endcap_pm; + const int tp_subsector = tp_info.subsector; + const int tp_station = tp_info.station; + const int tp_ring = tp_info.ring; + const int tp_layer = tp_info.layer; + // const int tp_chamber = tp_info.chamber; + + const int tp_csc_id = tp_info.csc_id; + const auto tp_csc_facing = tp_info.csc_facing; + + // Unpack data + const int tp_phiposition = tp_data.phiposition; // in half-strip unit + const int tp_partition = tp_data.partition; // in half-roll unit + + const int tp_bend = static_cast(tp_data.deltaphi) * (tp_data.bend == 0 ? 1 : -1); + + const int tp_bx = tp_info.bx; + const int tp_subbx = 0; // no fine resolution timing + const float tp_time = 0; // no fine resolution timing. + + const auto tp_selection = tp_info.selection; + + const int tp_quality = tp_data.quality; + + // ID scheme used in FW + const int tp_ilink = tp_info.ilink; + + // Get Global Coordinates + const GlobalPoint& gp = this->context_.geometry_translator_.getGlobalPoint(tp); + const float glob_phi = tp::radToDeg(gp.phi().value()); + const float glob_theta = tp::radToDeg(gp.theta().value()); + const double glob_rho = gp.perp(); + const double glob_z = gp.z(); + + // Calculate EMTF Values + const int emtf_phi = tp::calcPhiInt(sector_, glob_phi); + const int emtf_bend = std::clamp(tp_bend / 2, -64, 63); // 7-bit, signed + const int emtf_theta = tp::calcThetaInt(tp_endcap_pm, glob_theta); + const int emtf_qual = std::clamp(tp_quality, 0, 15); // 4-bit, unsigned + const int emtf_site = context_.site_lut_.lookup({tp_subsystem, tp_station, tp_ring}); + const int emtf_host = context_.host_lut_.lookup({tp_subsystem, tp_station, tp_ring}); + const int emtf_zones = context_.zone_lut_.getZones(emtf_host, emtf_theta); + + emtf_assert((0 <= emtf_phi) and (emtf_phi < 5040)); + emtf_assert((1 <= emtf_theta) and (emtf_theta < 128)); + + // Get flags + const bool tp_flag_neighbor = (tp_selection == TPSelection::kNeighbor); + const bool tp_flag_substitute = tp_info.flag_substitute; + const bool tp_flag_valid = true; // given by digi, not trigger_primitive :( + + // Set properties + hit.setId(tp_hit_id); + + hit.setRawDetId(tp_raw_id); + hit.setSubsystem(L1TMuon::kME0); + hit.setEndcap(tp_endcap_pm); + hit.setSector(sector_); + hit.setSubsector(tp_subsector); + hit.setStation(tp_station); + hit.setRing(tp_ring); + hit.setLayer(tp_layer); + hit.setChamber(tp_det_id.chamber()); // Save original chamber + + hit.setCscId(tp_csc_id); + hit.setCscFR(tp_csc_facing == csc::Facing::kRear); + + hit.setStrip(tp_phiposition); + hit.setStripLo(tp_phiposition); + hit.setStripHi(tp_phiposition); + + hit.setWire1(tp_partition); + hit.setWire2(0); + + hit.setBend(tp_bend); + + hit.setBx(tp_bx); + hit.setSubbx(tp_subbx); + + hit.setQuality(tp_quality); + hit.setPattern(0); + + hit.setGlobPhi(glob_phi); + hit.setGlobTheta(glob_theta); + hit.setGlobPerp(glob_rho); + hit.setGlobZ(glob_z); + hit.setGlobTime(tp_time); + + hit.setEmtfChamber(tp_ilink); + hit.setEmtfSegment(tp_segment_id); + hit.setEmtfPhi(emtf_phi); + hit.setEmtfBend(emtf_bend); + hit.setEmtfTheta1(emtf_theta); + hit.setEmtfTheta2(0); + hit.setEmtfQual1(emtf_qual); + hit.setEmtfQual2(0); + hit.setEmtfSite(emtf_site); + hit.setEmtfHost(emtf_host); + hit.setEmtfZones(emtf_zones); + + hit.setFlagNeighbor(tp_flag_neighbor); + hit.setFlagSubstitute(tp_flag_substitute); + hit.setFlagValid(tp_flag_valid); +} diff --git a/L1Trigger/L1TMuonEndCapPhase2/src/DAQ/GE0TPSelector.cc b/L1Trigger/L1TMuonEndCapPhase2/src/DAQ/GE0TPSelector.cc new file mode 100644 index 0000000000000..9f3ca2f9972f2 --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/src/DAQ/GE0TPSelector.cc @@ -0,0 +1,89 @@ +#include "FWCore/MessageLogger/interface/MessageLogger.h" + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFConfiguration.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFConstants.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFContext.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/SubsystemTags.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/TPrimitives.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Utils/DebugUtils.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Utils/CSCUtils.h" + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/GE0TPSelector.h" + +using namespace emtf::phase2; + +GE0TPSelector::GE0TPSelector(const EMTFContext& context, const int& endcap, const int& sector) + : context_(context), endcap_(endcap), sector_(sector) {} + +void GE0TPSelector::select(const TriggerPrimitive& tp, TPInfo tp_info, ILinkTPCMap& ilink_tpc_map) const { + emtf_assert(tp.subsystem() == L1TMuon::kME0); + + // Map GE0 trigger primitives to input links + int ilink = getInputLink(tp, tp_info); // Returns GE0 "link" index + + // Short-Circuit: Link not found (ilink = -1) + if (ilink < 0) { + return; + } + + ilink_tpc_map[ilink].emplace_back(tp, tp_info); +} + +// =========================================================================== +// Utils +// =========================================================================== +int GE0TPSelector::getInputLink(const TriggerPrimitive& tp, TPInfo& tp_info) const { + int ilink = -1; + + // Unpack detector info + const int tp_endcap = tp_info.endcap; + const int tp_sector = tp_info.sector; + const int tp_subsector = tp_info.subsector; + const int tp_station = tp_info.station; + const int tp_csc_id = tp_info.csc_id; + + // Find selection type + auto tp_selection = TPSelection::kNone; + + if (csc::isTPInSector(endcap_, sector_, tp_endcap, tp_sector)) { + tp_selection = TPSelection::kNative; + } else if (this->context_.config_.include_neighbor_en_ && + csc::isTPInNeighborSector(endcap_, sector_, tp_endcap, tp_sector, tp_subsector, tp_station, tp_csc_id)) { + tp_selection = TPSelection::kNeighbor; + } else { // Short-Circuit: tp_selection = TPSelection::kNone + return ilink; + } + + // Get chamber input link for this sector processor + ilink = calcInputLink(tp_subsector, tp_csc_id, tp_selection); + + // Add selection info + tp_info.ilink = ilink; + tp_info.selection = tp_selection; + + return ilink; +} + +int GE0TPSelector::calcInputLink(const int& tp_subsector, const int& tp_csc_id, const TPSelection& tp_selection) const { + int ilink = -1; + + // Links + // GE0 : 108..113 + // GE0 (N) : 114 + + if (tp_selection == TPSelection::kNative) { + const int ilink_offset = 108; + + ilink = ilink_offset + ((tp_subsector - 1) * 3) + (tp_csc_id - 1); + + emtf_assert((108 <= ilink) && (ilink < 114)); + } else { + const int ilink_offset = 114; + + ilink = ilink_offset; + + emtf_assert(ilink == ilink_offset); + } + + return ilink; +} diff --git a/L1Trigger/L1TMuonEndCapPhase2/src/DAQ/GEMTPCollector.cc b/L1Trigger/L1TMuonEndCapPhase2/src/DAQ/GEMTPCollector.cc new file mode 100644 index 0000000000000..b6dd63ecafaae --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/src/DAQ/GEMTPCollector.cc @@ -0,0 +1,187 @@ +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/ConsumesCollector.h" + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFConfiguration.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFConstants.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFContext.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/GEMTPCollector.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/SubsystemTags.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/TPrimitives.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Utils/DebugUtils.h" + +using namespace emtf::phase2; + +GEMTPCollector::GEMTPCollector(const EMTFContext& context, edm::ConsumesCollector& i_consumes_collector) + : context_(context), + input_token_(i_consumes_collector.consumes(context.config_.gem_input_)) {} + +void GEMTPCollector::collect(const edm::Event& i_event, BXTPCMap& bx_tpc_map) const { + // Constants + static const int max_delta_roll = 1; + static const int max_delta_pad_ge11 = 4; + static const int max_delta_pad_ge21 = 4; + + // Read GEM digis + TPCollection tpc; + + edm::Handle gem_digis; + i_event.getByToken(input_token_, gem_digis); + + auto chamber = gem_digis->begin(); + auto chend = gem_digis->end(); + + for (; chamber != chend; ++chamber) { + auto digi = (*chamber).second.first; + auto dend = (*chamber).second.second; + + for (; digi != dend; ++digi) { + // Short-Circuit: Ignore invalid digis + bool tp_valid = (*digi).isValid(); + + if (!tp_valid) { + continue; + } + + // Append digi + tpc.emplace_back((*chamber).first, *digi); + } + } + + // Find Copads + std::map, std::vector>> chamber_copads_map; + + for (auto& tp_entry : tpc) { + const auto& tp_det_id = tp_entry.tp_.detId(); + const GEMData& tp_data = tp_entry.tp_.getGEMData(); + + const int tp_region = tp_det_id.region(); // 0: barrel, +/-1: endcap + const int tp_station = tp_det_id.station(); + const int tp_ring = tp_det_id.ring(); + const int tp_chamber = tp_det_id.chamber(); + const int tp_layer = tp_det_id.layer(); + + const uint16_t tp_roll = tp_det_id.roll(); + const uint16_t tp_pad_lo = tp_data.pad_low; + const uint16_t tp_pad_hi = tp_data.pad_hi; + + const int tp_bx = tp_data.bx + this->context_.config_.gem_bx_shift_; + + GEMDetId tp_mod_det_id(tp_region, tp_ring, tp_station, 0, tp_chamber, 0); + auto key = std::make_pair(tp_mod_det_id.rawId(), tp_bx); + + if (tp_layer == 1) { + // Layer 1 is incidence + // If key does not exist, insert an empty vector. If key exists, do nothing. + decltype(chamber_copads_map)::mapped_type copads; + chamber_copads_map.insert({key, copads}); + } else if (tp_layer == 2) { + // Layer 2 is coincidence + decltype(chamber_copads_map)::mapped_type::value_type copad{{tp_roll, tp_pad_lo, tp_pad_hi}}; + chamber_copads_map[key].push_back(copad); + } + } + + // Map to BX + for (auto& tp_entry : tpc) { + const auto& tp_det_id = tp_entry.tp_.detId(); + const GEMData& tp_data = tp_entry.tp_.getGEMData(); + + const int tp_region = tp_det_id.region(); // 0: barrel, +/-1: endcap + const int tp_endcap = (tp_region == -1) ? 2 : tp_region; // 1: +endcap, 2: -endcap + const int tp_endcap_pm = (tp_endcap == 2) ? -1 : tp_endcap; // 1: +endcap, -1: -endcap + const int tp_station = tp_det_id.station(); + const int tp_ring = tp_det_id.ring(); + const int tp_layer = tp_det_id.layer(); + const int tp_chamber = tp_det_id.chamber(); + + const int tp_roll = tp_det_id.roll(); + const int tp_pad = (tp_data.pad_low + tp_data.pad_hi) / 2; + const int tp_pad_lo = tp_data.pad_low; + const int tp_pad_hi = tp_data.pad_hi; + + const int tp_bx = tp_data.bx + this->context_.config_.gem_bx_shift_; + + // Get Copad Info + GEMDetId tp_mod_det_id(tp_region, tp_ring, tp_station, 0, tp_chamber, 0); + auto tp_copads_key = std::make_pair(tp_mod_det_id.rawId(), tp_bx); + auto tp_copads = chamber_copads_map.at(tp_copads_key); + + // Check Copads + bool tp_is_substitute = false; + + if (tp_layer == 1) { + // layer 1 is used as incidence + const bool is_ge21 = (tp_station == 2); + + auto match_fn = [&tp_roll, &tp_pad_lo, &tp_pad_hi, &is_ge21](const std::array& elem) { + // Unpack entry + // Compare roll and (pad_lo, pad_hi)-range with tolerance + const auto& [c_roll_tmp, c_pad_lo_tmp, c_pad_hi_tmp] = elem; + int c_roll_lo = static_cast(c_roll_tmp) - max_delta_roll; + int c_roll_hi = static_cast(c_roll_tmp) + max_delta_roll; + int c_pad_lo = static_cast(c_pad_lo_tmp) - (is_ge21 ? max_delta_pad_ge21 : max_delta_pad_ge11); + int c_pad_hi = static_cast(c_pad_hi_tmp) + (is_ge21 ? max_delta_pad_ge21 : max_delta_pad_ge11); + + // Two ranges overlap if (range_a_lo <= range_b_hi) and (range_a_hi >= range_b_lo) + return (tp_roll <= c_roll_hi) and (tp_roll >= c_roll_lo) and (tp_pad_lo <= c_pad_hi) and + (tp_pad_hi >= c_pad_lo); + }; + + auto match = std::find_if(tp_copads.begin(), tp_copads.end(), match_fn); + + if (match != tp_copads.end()) { + // Has copad + tp_is_substitute = false; + } else if (tp_copads.empty()) { + // Kinda has copad + tp_is_substitute = true; + } else { + // Short-Circuit: Didn't find coincidence + continue; + } + } else if (tp_layer == 2) { + // Short-Circuit: layer 2 is used as coincidence + continue; + } + + // Calculate EMTF Info + const int tp_sector = csc::getTriggerSector(tp_station, tp_ring, tp_chamber); + const int tp_subsector = csc::getTriggerSubsector(tp_station, tp_chamber); + const int tp_csc_id = csc::getId(tp_station, tp_ring, tp_chamber); + const auto tp_csc_facing = csc::getFaceDirection(tp_station, tp_ring, tp_chamber); + + // Assertion checks + emtf_assert(kMinEndcap <= tp_endcap && tp_endcap <= kMaxEndcap); + emtf_assert(kMinTrigSector <= tp_sector && tp_sector <= kMaxTrigSector); + emtf_assert((0 <= tp_subsector) and (tp_subsector <= 2)); + emtf_assert(1 <= tp_station && tp_station <= 2); + emtf_assert(tp_ring == 1); + emtf_assert((1 <= tp_chamber) and (tp_chamber <= 36)); + emtf_assert(1 <= tp_csc_id && tp_csc_id <= 3); + emtf_assert(tp_station == 1 or (1 <= tp_roll && tp_roll <= 16)); + emtf_assert(tp_station != 1 or (1 <= tp_roll && tp_roll <= 8)); + emtf_assert(1 <= tp_layer && tp_layer <= 2); + emtf_assert((tp_station == 1 && 0 <= tp_pad && tp_pad <= 191) || (tp_station != 1)); + emtf_assert((tp_station == 2 && 0 <= tp_pad && tp_pad <= 383) || (tp_station != 2)); + + // Add info + tp_entry.info_.bx = tp_bx; + + tp_entry.info_.endcap = tp_endcap; + tp_entry.info_.endcap_pm = tp_endcap_pm; + tp_entry.info_.sector = tp_sector; + tp_entry.info_.subsector = tp_subsector; + tp_entry.info_.station = tp_station; + tp_entry.info_.ring = tp_ring; + tp_entry.info_.roll = tp_roll; + tp_entry.info_.layer = tp_layer; + tp_entry.info_.chamber = tp_chamber; + + tp_entry.info_.csc_id = tp_csc_id; + tp_entry.info_.csc_facing = tp_csc_facing; + + tp_entry.info_.flag_substitute = tp_is_substitute; + + bx_tpc_map[tp_bx].push_back(tp_entry); + } +} diff --git a/L1Trigger/L1TMuonEndCapPhase2/src/DAQ/GEMTPConverter.cc b/L1Trigger/L1TMuonEndCapPhase2/src/DAQ/GEMTPConverter.cc new file mode 100644 index 0000000000000..6765afff669d3 --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/src/DAQ/GEMTPConverter.cc @@ -0,0 +1,143 @@ +#include "FWCore/MessageLogger/interface/MessageLogger.h" + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFConfiguration.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFConstants.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFContext.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Data/HostLut.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Data/SiteLut.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Data/ZoneLut.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/SubsystemTags.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Utils/DebugUtils.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Utils/CSCUtils.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Utils/TPUtils.h" + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/GEMTPConverter.h" + +using namespace emtf::phase2; + +GEMTPConverter::GEMTPConverter(const EMTFContext& context, const int& endcap, const int& sector) + : context_(context), endcap_(endcap), sector_(sector) {} + +void GEMTPConverter::convert(const TriggerPrimitive& tp, const TPInfo& tp_info, EMTFHit& hit) const { + // Unpack Id + const auto& tp_hit_id = tp_info.hit_id; + const auto& tp_segment_id = tp_info.segment_id; + + // Unpack trigger primitive + const auto& tp_det_id = tp.detId(); + const auto& tp_data = tp.getGEMData(); + + // Unpack detector info + const auto tp_subsystem = L1TMuon::kGEM; + + const int tp_raw_id = tp_det_id.rawId(); + + const int tp_endcap_pm = tp_info.endcap_pm; + const int tp_subsector = tp_info.subsector; + const int tp_station = tp_info.station; + const int tp_ring = tp_info.ring; + const int tp_roll = tp_info.roll; + const int tp_layer = tp_info.layer; + const int tp_chamber = tp_info.chamber; + + const auto tp_csc_facing = tp_info.csc_facing; + const int tp_csc_id = tp_info.csc_id; + + // Unpack data + const int tp_pad_lo = tp_data.pad_low; + const int tp_pad_hi = tp_data.pad_hi; + const int tp_pad = (tp_pad_lo + tp_pad_hi) / 2; + const int tp_clus_width = (tp_pad_hi - tp_pad_lo + 1); + + const int tp_bend = 0; // not applicable + + const int tp_bx = tp_info.bx; + const int tp_subbx = 0; // no fine resolution timing + const float tp_time = 0; // no fine resolution timing. Note: Check with Efe, Jia Fu gets this from digi directly. + + const auto tp_selection = tp_info.selection; + + // Use cluster width as quality. GE2/1 strip pitch is the same as GE1/1 strip pitch. + const int tp_quality = tp_clus_width; + + // ID scheme used in FW + const int tp_ilink = tp_info.ilink; + + // Get Global Coordinates + // const GlobalPoint& gp = get_global_point(detgeom, detid, digi); + const GlobalPoint& gp = this->context_.geometry_translator_.getGlobalPoint(tp); + const float glob_phi = tp::radToDeg(gp.phi().value()); + const float glob_theta = tp::radToDeg(gp.theta().value()); + const double glob_rho = gp.perp(); + const double glob_z = gp.z(); + + // Calculate EMTF Values + const int emtf_phi = tp::calcPhiInt(sector_, glob_phi); + const int emtf_bend = 0; + const int emtf_theta = tp::calcThetaInt(tp_endcap_pm, glob_theta); + const int emtf_qual = 0; + const int emtf_site = context_.site_lut_.lookup({tp_subsystem, tp_station, tp_ring}); + const int emtf_host = context_.host_lut_.lookup({tp_subsystem, tp_station, tp_ring}); + const int emtf_zones = context_.zone_lut_.getZones(emtf_host, emtf_theta); + + emtf_assert((0 <= emtf_phi) and (emtf_phi < 5040)); + emtf_assert((1 <= emtf_theta) and (emtf_theta < 128)); + + // Get flags + const bool tp_flag_neighbor = (tp_selection == TPSelection::kNeighbor); + const bool tp_flag_substitute = tp_info.flag_substitute; + const bool tp_flag_valid = true; // given by digi, not trigger_primitive + + // Set properties + hit.setId(tp_hit_id); + + hit.setRawDetId(tp_raw_id); + hit.setSubsystem(L1TMuon::kGEM); + hit.setEndcap(tp_endcap_pm); + hit.setSector(sector_); + hit.setSubsector(tp_subsector); + hit.setStation(tp_station); + hit.setRing(tp_ring); + hit.setLayer(tp_layer); + hit.setChamber(tp_chamber); + + hit.setCscId(tp_csc_id); + hit.setCscFR(tp_csc_facing == csc::Facing::kRear); + + hit.setStrip(tp_pad); + hit.setStripLo(tp_pad_lo); + hit.setStripHi(tp_pad_hi); + + hit.setWire1(tp_roll); + hit.setWire2(0); + + hit.setBend(tp_bend); + + hit.setBx(tp_bx); + hit.setSubbx(tp_subbx); + + hit.setQuality(tp_quality); + hit.setPattern(0); + + hit.setGlobPhi(glob_phi); + hit.setGlobTheta(glob_theta); + hit.setGlobPerp(glob_rho); + hit.setGlobZ(glob_z); + hit.setGlobTime(tp_time); + + hit.setEmtfChamber(tp_ilink); + hit.setEmtfSegment(tp_segment_id); + hit.setEmtfPhi(emtf_phi); + hit.setEmtfBend(emtf_bend); + hit.setEmtfTheta1(emtf_theta); + hit.setEmtfTheta2(0); + hit.setEmtfQual1(emtf_qual); + hit.setEmtfQual2(0); + hit.setEmtfSite(emtf_site); + hit.setEmtfHost(emtf_host); + hit.setEmtfZones(emtf_zones); + + hit.setFlagNeighbor(tp_flag_neighbor); + hit.setFlagSubstitute(tp_flag_substitute); + hit.setFlagValid(tp_flag_valid); +} diff --git a/L1Trigger/L1TMuonEndCapPhase2/src/DAQ/GEMTPSelector.cc b/L1Trigger/L1TMuonEndCapPhase2/src/DAQ/GEMTPSelector.cc new file mode 100644 index 0000000000000..5a47d8020ad68 --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/src/DAQ/GEMTPSelector.cc @@ -0,0 +1,104 @@ +#include "FWCore/MessageLogger/interface/MessageLogger.h" + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFConfiguration.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFConstants.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFContext.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/SubsystemTags.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/TPrimitives.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Utils/DebugUtils.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Utils/CSCUtils.h" + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/GEMTPSelector.h" + +using namespace emtf::phase2; + +GEMTPSelector::GEMTPSelector(const EMTFContext& context, const int& endcap, const int& sector) + : context_(context), endcap_(endcap), sector_(sector) {} + +void GEMTPSelector::select(const TriggerPrimitive& tp, TPInfo tp_info, ILinkTPCMap& ilink_tpc_map) const { + emtf_assert(tp.subsystem() == L1TMuon::kGEM); + + // Map GEM trigger primitives to input links + int ilink = getInputLink(tp, tp_info); // Returns GEM "link" index + + // Short-Circuit: Link not found (ilink = -1) + if (ilink < 0) { + return; + } + + ilink_tpc_map[ilink].emplace_back(tp, tp_info); +} + +// =========================================================================== +// Utils +// =========================================================================== +int GEMTPSelector::getInputLink(const TriggerPrimitive& tp, TPInfo& tp_info) const { + int ilink = -1; + + // Unpack detector info + const int tp_endcap = tp_info.endcap; + const int tp_sector = tp_info.sector; + const int tp_subsector = tp_info.subsector; + const int tp_station = tp_info.station; + const int tp_ring = tp_info.ring; + const int tp_csc_id = tp_info.csc_id; + + // Find selection type + auto tp_selection = TPSelection::kNone; + + if (csc::isTPInSector(endcap_, sector_, tp_endcap, tp_sector)) { + tp_selection = TPSelection::kNative; + } else if (this->context_.config_.include_neighbor_en_ && + csc::isTPInNeighborSector(endcap_, sector_, tp_endcap, tp_sector, tp_subsector, tp_station, tp_csc_id)) { + tp_selection = TPSelection::kNeighbor; + } else { // Short-Circuit: tp_selection = TPSelection::kNone + return ilink; + } + + // Get chamber input link for this sector processor + ilink = calcInputLink(tp_subsector, tp_station, tp_ring, tp_csc_id, tp_selection); + + // Add selection info + tp_info.ilink = ilink; + tp_info.selection = tp_selection; + + return ilink; +} + +int GEMTPSelector::calcInputLink(const int& tp_subsector, + const int& tp_station, + const int& tp_ring, + const int& tp_csc_id, + const TPSelection& tp_selection) const { + int ilink = -1; + + // Links + // RE1,2,3,4 + GE1,2 : 54..71, 72..80, 81..89, 90..98 + // RE1,2,3,4 + GE1,2 (N) : 99..101, 102..103, 104..105, 106..107 + + if (tp_selection == TPSelection::kNative) { + const int ilink_offset = 54; + + if (tp_station == 1) { + ilink = ilink_offset + (tp_subsector - 1) * 9 + (tp_csc_id - 1); + } else { + ilink = ilink_offset + tp_station * 9 + (tp_csc_id - 1); + } + + emtf_assert((54 <= ilink) && (ilink < 99)); + } else { + const int ilink_offset = 99; + + if (tp_station == 1) { + ilink = ilink_offset + ((tp_station - 1) * 2) + ((tp_csc_id - 1) / 3); + } else if (tp_ring == 1) { + ilink = ilink_offset + ((tp_station - 1) * 2) + 1; + } else { + ilink = ilink_offset + ((tp_station - 1) * 2) + 2; + } + + emtf_assert((99 <= ilink) && (ilink < 108)); + } + + return ilink; +} diff --git a/L1Trigger/L1TMuonEndCapPhase2/src/DAQ/ME0TPCollector.cc b/L1Trigger/L1TMuonEndCapPhase2/src/DAQ/ME0TPCollector.cc new file mode 100644 index 0000000000000..0c10b6fa201b2 --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/src/DAQ/ME0TPCollector.cc @@ -0,0 +1,134 @@ +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/ConsumesCollector.h" + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFConfiguration.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFConstants.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFContext.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/SubsystemTags.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/TPrimitives.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Utils/CSCUtils.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Utils/DebugUtils.h" + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/ME0TPCollector.h" + +using namespace emtf::phase2; + +ME0TPCollector::ME0TPCollector(const EMTFContext& context, edm::ConsumesCollector& i_consumes_collector) + : context_(context), + input_token_(i_consumes_collector.consumes(context.config_.me0_input_)) {} + +void ME0TPCollector::collect(const edm::Event& i_event, BXTPCMap& bx_tpc_map) const { + // Constants + // First quarter of ME0 chamber (5 deg) and last quarter + static const int me0_max_partition = 9; + static const int me0_nstrips = 384; + static const int me0_nphipositions = me0_nstrips * 2; + static const int phiposition_q1 = me0_nphipositions / 4; + static const int phiposition_q3 = (me0_nphipositions / 4) * 3; + + // Read ME0 digis + TPCollection tpc; + + edm::Handle me0_digis; + i_event.getByToken(input_token_, me0_digis); + + auto chamber = me0_digis->begin(); + auto chend = me0_digis->end(); + + for (; chamber != chend; ++chamber) { + auto digi = (*chamber).second.first; + auto dend = (*chamber).second.second; + + for (; digi != dend; ++digi) { + tpc.emplace_back((*chamber).first, *digi); + } + } + + // Map to BX + for (auto& tp_entry : tpc) { + const auto& tp_det_id = tp_entry.tp_.detId(); + const ME0Data& tp_data = tp_entry.tp_.getME0Data(); + + const int tp_region = tp_det_id.region(); // 0: barrel, +/-1: endcap + const int tp_endcap = (tp_region == -1) ? 2 : tp_region; // 1: +endcap, 2: -endcap + const int tp_endcap_pm = (tp_endcap == 2) ? -1 : tp_endcap; // 1: +endcap, -1: -endcap + const int tp_station = tp_det_id.station(); + const int tp_ring = 4; + const int tp_layer = tp_det_id.layer(); + const int tp_roll = tp_det_id.roll(); + const int tp_me0_chamber = tp_det_id.chamber(); + + const int tp_pad = tp_data.phiposition; + const int tp_partition = tp_data.partition; + const int tp_bx = tp_data.bx + this->context_.config_.me0_bx_shift_; + + // Reject if outside eta of 2.4 + if (tp_partition > me0_max_partition) { + continue; + } + + // Calculate EMTF Info + // Split 20-deg chamber into 10-deg chamber + // ME0 chamber is rotated by -5 deg relative to CSC chamber. + // ME0 chamber 1 starts at -10 deg, CSC chamber 1 starts at -5 deg. + const int tp_phiposition = tp_data.phiposition; // in half-strip unit + + int tp_chamber = (tp_me0_chamber - 1) * 2 + 1; + + if (tp_endcap == 1) { + // positive endcap + // phiposition increases counter-clockwise + if (tp_phiposition < phiposition_q1) { + tp_chamber = csc::getNext10DegChamber(tp_chamber); + } else if (tp_phiposition < phiposition_q3) { + // Do nothing + } else { + tp_chamber = csc::getPrev10DegChamber(tp_chamber); + } + } else { + // negative endcap + // phiposition increases clockwise + if (tp_phiposition < phiposition_q1) { + tp_chamber = csc::getPrev10DegChamber(tp_chamber); + } else if (tp_phiposition < phiposition_q3) { + // Do nothing + } else { + tp_chamber = csc::getNext10DegChamber(tp_chamber); + } + } + + const int tp_sector = csc::getTriggerSector(tp_station, tp_ring, tp_chamber); + const int tp_subsector = csc::getTriggerSubsector(tp_station, tp_chamber); + const int tp_csc_id = csc::getId(tp_station, tp_ring, tp_chamber); + const auto tp_csc_facing = csc::getFaceDirection(tp_station, tp_ring, tp_chamber); + + // Assertion checks + emtf_assert(kMinEndcap <= tp_endcap && tp_endcap <= kMaxEndcap); + emtf_assert(kMinTrigSector <= tp_sector && tp_sector <= kMaxTrigSector); + emtf_assert((1 <= tp_subsector) and (tp_subsector <= 2)); + emtf_assert(tp_station == 1); + emtf_assert(tp_ring == 4); + emtf_assert((1 <= tp_chamber) and (tp_chamber <= 36)); + emtf_assert(1 <= tp_csc_id && tp_csc_id <= 3); + emtf_assert(0 <= tp_pad && tp_pad <= 767); + emtf_assert(0 <= tp_partition && tp_partition <= 15); + + // Add info + tp_entry.info_.bx = tp_bx; + + tp_entry.info_.endcap = tp_endcap; + tp_entry.info_.endcap_pm = tp_endcap_pm; + tp_entry.info_.sector = tp_sector; + tp_entry.info_.subsector = tp_subsector; + tp_entry.info_.station = tp_station; + tp_entry.info_.ring = tp_ring; + tp_entry.info_.layer = tp_layer; + tp_entry.info_.roll = tp_roll; + tp_entry.info_.chamber = tp_chamber; + + tp_entry.info_.csc_id = tp_csc_id; + tp_entry.info_.csc_facing = tp_csc_facing; + + bx_tpc_map[tp_bx].push_back(tp_entry); + } +} diff --git a/L1Trigger/L1TMuonEndCapPhase2/src/DAQ/ME0TPConverter.cc b/L1Trigger/L1TMuonEndCapPhase2/src/DAQ/ME0TPConverter.cc new file mode 100644 index 0000000000000..7b3a5f8a1f704 --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/src/DAQ/ME0TPConverter.cc @@ -0,0 +1,138 @@ +#include "FWCore/MessageLogger/interface/MessageLogger.h" + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFConfiguration.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFConstants.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFContext.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Data/HostLut.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Data/SiteLut.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Data/ZoneLut.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/SubsystemTags.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Utils/DebugUtils.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Utils/CSCUtils.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Utils/TPUtils.h" + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/ME0TPConverter.h" + +using namespace emtf::phase2; + +ME0TPConverter::ME0TPConverter(const EMTFContext& context, const int& endcap, const int& sector) + : context_(context), endcap_(endcap), sector_(sector) {} + +void ME0TPConverter::convert(const TriggerPrimitive& tp, const TPInfo& tp_info, EMTFHit& hit) const { + // Unpack Id + const auto& tp_hit_id = tp_info.hit_id; + const int tp_segment_id = tp_info.segment_id; + + // Unpack trigger primitive + const auto& tp_det_id = tp.detId(); + const auto& tp_data = tp.getME0Data(); + + // Unpack detector info + const auto tp_subsystem = L1TMuon::kME0; + + const int tp_raw_id = tp_det_id.rawId(); + + const int tp_endcap_pm = tp_info.endcap_pm; + const int tp_subsector = tp_info.subsector; + const int tp_station = tp_info.station; + const int tp_ring = tp_info.ring; + const int tp_layer = tp_info.layer; + // const int tp_chamber = tp_info.chamber; + + const int tp_csc_id = tp_info.csc_id; + const auto tp_csc_facing = tp_info.csc_facing; + + // Unpack data + const int tp_phiposition = tp_data.phiposition; // in half-strip unit + const int tp_partition = tp_data.partition; // in half-roll unit + + const int tp_bend = static_cast(tp_data.deltaphi) * (tp_data.bend == 0 ? 1 : -1); + + const int tp_bx = tp_info.bx; + const int tp_subbx = 0; // no fine resolution timing + const float tp_time = 0; // no fine resolution timing. + + const auto tp_selection = tp_info.selection; + + const int tp_quality = tp_data.quality; + + // ID scheme used in FW + const int tp_ilink = tp_info.ilink; + + // Get Global Coordinates + const GlobalPoint& gp = this->context_.geometry_translator_.getGlobalPoint(tp); + const float glob_phi = tp::radToDeg(gp.phi().value()); + const float glob_theta = tp::radToDeg(gp.theta().value()); + const double glob_rho = gp.perp(); + const double glob_z = gp.z(); + + // Calculate EMTF Values + const int emtf_phi = tp::calcPhiInt(sector_, glob_phi); + const int emtf_bend = std::clamp(tp_bend / 2, -64, 63); // 7-bit, signed + const int emtf_theta = tp::calcThetaInt(tp_endcap_pm, glob_theta); + const int emtf_qual = std::clamp(tp_quality, 0, 15); // 4-bit, unsigned + const int emtf_site = context_.site_lut_.lookup({tp_subsystem, tp_station, tp_ring}); + const int emtf_host = context_.host_lut_.lookup({tp_subsystem, tp_station, tp_ring}); + const int emtf_zones = context_.zone_lut_.getZones(emtf_host, emtf_theta); + + emtf_assert((0 <= emtf_phi) and (emtf_phi < 5040)); + emtf_assert((1 <= emtf_theta) and (emtf_theta < 128)); + + // Get flags + const bool tp_flag_neighbor = (tp_selection == TPSelection::kNeighbor); + const bool tp_flag_substitute = tp_info.flag_substitute; + const bool tp_flag_valid = true; // given by digi, not trigger_primitive :( + + // Set properties + hit.setId(tp_hit_id); + + hit.setRawDetId(tp_raw_id); + hit.setSubsystem(L1TMuon::kME0); + hit.setEndcap(tp_endcap_pm); + hit.setSector(sector_); + hit.setSubsector(tp_subsector); + hit.setStation(tp_station); + hit.setRing(tp_ring); + hit.setLayer(tp_layer); + hit.setChamber(tp_det_id.chamber()); // Save original chamber + + hit.setCscId(tp_csc_id); + hit.setCscFR(tp_csc_facing == csc::Facing::kRear); + + hit.setStrip(tp_phiposition); + hit.setStripLo(tp_phiposition); + hit.setStripHi(tp_phiposition); + + hit.setWire1(tp_partition); + hit.setWire2(0); + + hit.setBend(tp_bend); + + hit.setBx(tp_bx); + hit.setSubbx(tp_subbx); + + hit.setQuality(tp_quality); + hit.setPattern(0); + + hit.setGlobPhi(glob_phi); + hit.setGlobTheta(glob_theta); + hit.setGlobPerp(glob_rho); + hit.setGlobZ(glob_z); + hit.setGlobTime(tp_time); + + hit.setEmtfChamber(tp_ilink); + hit.setEmtfSegment(tp_segment_id); + hit.setEmtfPhi(emtf_phi); + hit.setEmtfBend(emtf_bend); + hit.setEmtfTheta1(emtf_theta); + hit.setEmtfTheta2(0); + hit.setEmtfQual1(emtf_qual); + hit.setEmtfQual2(0); + hit.setEmtfSite(emtf_site); + hit.setEmtfHost(emtf_host); + hit.setEmtfZones(emtf_zones); + + hit.setFlagNeighbor(tp_flag_neighbor); + hit.setFlagSubstitute(tp_flag_substitute); + hit.setFlagValid(tp_flag_valid); +} diff --git a/L1Trigger/L1TMuonEndCapPhase2/src/DAQ/ME0TPSelector.cc b/L1Trigger/L1TMuonEndCapPhase2/src/DAQ/ME0TPSelector.cc new file mode 100644 index 0000000000000..0cf5bdc94fe92 --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/src/DAQ/ME0TPSelector.cc @@ -0,0 +1,89 @@ +#include "FWCore/MessageLogger/interface/MessageLogger.h" + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFConfiguration.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFConstants.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFContext.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/SubsystemTags.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/TPrimitives.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Utils/DebugUtils.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Utils/CSCUtils.h" + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/ME0TPSelector.h" + +using namespace emtf::phase2; + +ME0TPSelector::ME0TPSelector(const EMTFContext& context, const int& endcap, const int& sector) + : context_(context), endcap_(endcap), sector_(sector) {} + +void ME0TPSelector::select(const TriggerPrimitive& tp, TPInfo tp_info, ILinkTPCMap& ilink_tpc_map) const { + emtf_assert(tp.subsystem() == L1TMuon::kME0); + + // Map ME0 trigger primitives to input links + int ilink = getInputLink(tp, tp_info); // Returns ME0 "link" index + + // Short-Circuit: Link not found (ilink = -1) + if (ilink < 0) { + return; + } + + ilink_tpc_map[ilink].emplace_back(tp, tp_info); +} + +// =========================================================================== +// Utils +// =========================================================================== +int ME0TPSelector::getInputLink(const TriggerPrimitive& tp, TPInfo& tp_info) const { + int ilink = -1; + + // Unpack detector info + const int tp_endcap = tp_info.endcap; + const int tp_sector = tp_info.sector; + const int tp_subsector = tp_info.subsector; + const int tp_station = tp_info.station; + const int tp_csc_id = tp_info.csc_id; + + // Find selection type + auto tp_selection = TPSelection::kNone; + + if (csc::isTPInSector(endcap_, sector_, tp_endcap, tp_sector)) { + tp_selection = TPSelection::kNative; + } else if (this->context_.config_.include_neighbor_en_ && + csc::isTPInNeighborSector(endcap_, sector_, tp_endcap, tp_sector, tp_subsector, tp_station, tp_csc_id)) { + tp_selection = TPSelection::kNeighbor; + } else { // Short-Circuit: tp_selection = TPSelection::kNone + return ilink; + } + + // Get chamber input link for this sector processor + ilink = calcInputLink(tp_subsector, tp_csc_id, tp_selection); + + // Add selection info + tp_info.ilink = ilink; + tp_info.selection = tp_selection; + + return ilink; +} + +int ME0TPSelector::calcInputLink(const int& tp_subsector, const int& tp_csc_id, const TPSelection& tp_selection) const { + int ilink = -1; + + // Links + // ME0 : 108..113 + // ME0 (N) : 114 + + if (tp_selection == TPSelection::kNative) { + const int ilink_offset = 108; + + ilink = ilink_offset + ((tp_subsector - 1) * 3) + (tp_csc_id - 1); + + emtf_assert((108 <= ilink) && (ilink < 114)); + } else { + const int ilink_offset = 114; + + ilink = ilink_offset; + + emtf_assert(ilink == ilink_offset); + } + + return ilink; +} diff --git a/L1Trigger/L1TMuonEndCapPhase2/src/DAQ/RPCTPCollector.cc b/L1Trigger/L1TMuonEndCapPhase2/src/DAQ/RPCTPCollector.cc new file mode 100644 index 0000000000000..edb44b095a352 --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/src/DAQ/RPCTPCollector.cc @@ -0,0 +1,160 @@ +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/ConsumesCollector.h" + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFConfiguration.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFConstants.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFContext.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/RPCTPCollector.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/SubsystemTags.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/TPrimitives.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Utils/DebugUtils.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Utils/RPCUtils.h" + +using namespace emtf::phase2; + +RPCTPCollector::RPCTPCollector(const EMTFContext& context, edm::ConsumesCollector& i_consumes_collector) + : context_(context), + input_token_(i_consumes_collector.consumes(context.config_.rpc_input_)) {} + +void RPCTPCollector::collect(const edm::Event& i_event, BXTPCMap& bx_tpc_map) const { + // Constants + static const int clus_width_cut = 4; + static const int clus_width_cut_irpc = 6; + + // Read RPC digis + TPCollection tpc; + + edm::Handle rpc_digis; + i_event.getByToken(input_token_, rpc_digis); + + auto digi = rpc_digis->begin(); + auto digi_end = rpc_digis->end(); + + for (; digi != digi_end; ++digi) { + tpc.emplace_back(digi->rpcId(), *digi); + } + + // Map to BX + for (auto& tp_entry : tpc) { + const auto& tp_det_id = tp_entry.tp_.detId(); + const RPCData& tp_data = tp_entry.tp_.getRPCData(); + + const int tp_region = tp_det_id.region(); // 0: barrel, +/-1: endcap + const int tp_endcap = (tp_region == -1) ? 2 : tp_region; // 1: +endcap, 2: -endcap + const int tp_endcap_pm = (tp_endcap == 2) ? -1 : tp_endcap; // 1: +endcap, -1: -endcap + + // RPC sector is rotated by -20 deg relative to CSC sector. + // RPC sector 1 starts at -5 deg, CSC sector 1 starts at 15 deg. + const int tp_rpc_sector = tp_det_id.sector(); // 1 - 6 (60 degrees in phi, sector 1 begins at -5 deg) + + // RPC subsector is defined differently than CSC subsector. + // RPC subsector is used to label the chamber within a sector. + const int tp_rpc_subsector = tp_det_id.subsector(); + + const int tp_station = tp_det_id.station(); // 1 - 4 + const int tp_ring = tp_det_id.ring(); // 2 - 3 (increasing theta) + const int tp_roll = + tp_det_id.roll(); // 1 - 3 (decreasing theta; aka A - C; space between rolls is 9 - 15 in theta_fp) + const int tp_layer = tp_det_id.layer(); // Always 1 in the Endcap, 1 or 2 in the Barrel + + const int tp_strip = (tp_data.strip_low + tp_data.strip_hi) / 2; // in full-strip unit + const int tp_strip_lo = tp_data.strip_low; + const int tp_strip_hi = tp_data.strip_hi; + const int tp_clus_width = (tp_strip_hi - tp_strip_lo + 1); + + const bool tp_is_CPPF = tp_data.isCPPF; + + const int tp_bx = tp_data.bx + this->context_.config_.rpc_bx_shift_; + + // Check Ring + bool tp_is_substitute = (tp_ring == 3); + + // Calculate type + const bool tp_is_barrel = (tp_region == 0); + + rpc::Type tp_rpc_type; + + if ((!tp_is_barrel) && (tp_station >= 3) && (tp_ring == 1)) { + tp_rpc_type = rpc::Type::kiRPC; + } else { + tp_rpc_type = rpc::Type::kRPC; + } + + // Short-Circuit: Skip Barrel RPC (region = 0) + if (tp_region == 0) { + continue; + } + + // Short-Circuit: Skip Overlap region (RE1/3, RE2/3) + if (tp_station <= 2 && tp_ring == 3) { + continue; + } + + // Short-Circuit: Reject wide clusters + if (tp_rpc_type == rpc::Type::kiRPC) { + if (tp_clus_width > clus_width_cut_irpc) { + continue; + } + } else { + if (tp_clus_width > clus_width_cut) { + continue; + } + } + + // Calculate EMTF Info + int tp_chamber; + + if (tp_rpc_type == rpc::Type::kiRPC) { + tp_chamber = (tp_rpc_sector - 1) * 3 + tp_rpc_subsector; + } else { + tp_chamber = (tp_rpc_sector - 1) * 6 + tp_rpc_subsector; + } + + const int tp_sector = csc::getTriggerSector(tp_station, tp_ring, tp_chamber); + const int tp_subsector = csc::getTriggerSubsector(tp_station, tp_chamber); + const int tp_csc_id = csc::getId(tp_station, tp_ring, tp_chamber); + const auto tp_csc_facing = csc::getFaceDirection(tp_station, tp_ring, tp_chamber); + + // Assertion checks + emtf_assert(kMinEndcap <= tp_endcap && tp_endcap <= kMaxEndcap); + emtf_assert(kMinTrigSector <= tp_sector && tp_sector <= kMaxTrigSector); + emtf_assert(0 <= tp_subsector && tp_subsector <= 2); + emtf_assert(1 <= tp_station && tp_station <= 4); + emtf_assert(1 <= tp_chamber && tp_chamber <= 36); + emtf_assert((1 <= tp_csc_id) and (tp_csc_id <= 9)); + + if (tp_rpc_type == rpc::Type::kiRPC) { + emtf_assert(tp_ring == 1); + emtf_assert(1 <= tp_roll && tp_roll <= 5); + emtf_assert(1 <= tp_strip && tp_strip <= 96); + } else { + emtf_assert(2 <= tp_ring && tp_ring <= 3); + emtf_assert(1 <= tp_roll && tp_roll <= 3); + emtf_assert(tp_is_CPPF || (1 <= tp_strip && tp_strip <= 32)); + } + + emtf_assert(tp_data.valid); + + // Add info + tp_entry.info_.bx = tp_bx; + + tp_entry.info_.endcap = tp_endcap; + tp_entry.info_.endcap_pm = tp_endcap_pm; + tp_entry.info_.sector = tp_sector; + tp_entry.info_.subsector = tp_subsector; + tp_entry.info_.station = tp_station; + tp_entry.info_.ring = tp_ring; + tp_entry.info_.roll = tp_roll; + tp_entry.info_.layer = tp_layer; + tp_entry.info_.chamber = tp_chamber; + + tp_entry.info_.csc_id = tp_csc_id; + tp_entry.info_.csc_facing = tp_csc_facing; + + tp_entry.info_.rpc_type = tp_rpc_type; + + tp_entry.info_.flag_substitute = tp_is_substitute; + + bx_tpc_map[tp_bx].push_back(tp_entry); + } +} diff --git a/L1Trigger/L1TMuonEndCapPhase2/src/DAQ/RPCTPConverter.cc b/L1Trigger/L1TMuonEndCapPhase2/src/DAQ/RPCTPConverter.cc new file mode 100644 index 0000000000000..52cada1253ed0 --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/src/DAQ/RPCTPConverter.cc @@ -0,0 +1,175 @@ +#include "FWCore/MessageLogger/interface/MessageLogger.h" + +#include "Geometry/RPCGeometry/interface/RPCGeometry.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFConfiguration.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFConstants.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFContext.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Data/HostLut.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Data/SiteLut.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Data/ZoneLut.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/SubsystemTags.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Utils/DebugUtils.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Utils/CSCUtils.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Utils/RPCUtils.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Utils/TPUtils.h" + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/RPCTPConverter.h" + +using namespace emtf::phase2; + +RPCTPConverter::RPCTPConverter(const EMTFContext& context, const int& endcap, const int& sector) + : context_(context), endcap_(endcap), sector_(sector) {} + +void RPCTPConverter::convert(const TriggerPrimitive& tp, const TPInfo& tp_info, EMTFHit& hit) const { + // Unpack Id + const auto& tp_hit_id = tp_info.hit_id; + const auto& tp_segment_id = tp_info.segment_id; + + // Unpack trigger primitive + const auto& tp_det_id = tp.detId(); + const auto& tp_data = tp.getRPCData(); + + // Unpack detector info + const auto tp_subsystem = L1TMuon::kRPC; + + const int tp_raw_id = tp_det_id.rawId(); + + const int tp_endcap_pm = tp_info.endcap_pm; + const int tp_subsector = tp_info.subsector; + const int tp_station = tp_info.station; + const int tp_ring = tp_info.ring; + const int tp_roll = tp_info.roll; + const int tp_layer = tp_info.layer; + const int tp_chamber = tp_info.chamber; + + const auto tp_csc_facing = tp_info.csc_facing; + const int tp_csc_id = tp_info.csc_id; + const auto tp_rpc_type = tp_info.rpc_type; + + // Unpack data + const int tp_strip = (tp_data.strip_low + tp_data.strip_hi) / 2; // in full-strip unit + const int tp_strip_lo = tp_data.strip_low; + const int tp_strip_hi = tp_data.strip_hi; + const int tp_clus_width = (tp_strip_hi - tp_strip_lo + 1); + + int tp_bend = 0; // not applicable + + const int tp_bx = tp_info.bx; + const float tp_time = tp_data.time; + float tp_subbx_f32 = tp_time - (std::round(tp_time / 25.) * 25.); // reduce range to [-12.5,12.5] ns + int tp_subbx = static_cast(std::round(tp_subbx_f32 * 16. / 25.)); + tp_subbx = std::clamp(tp_subbx, -8, 7); // 4-bit, signed + int tp_bx_check = static_cast(std::round(tp_time / 25.)); + + // Not sure why sometimes digi.time() returns 0? + emtf_assert(((not(std::abs(tp_time) < 1e-6)) and (tp_bx == tp_bx_check)) or (std::abs(tp_time) < 1e-6)); + + const auto tp_selection = tp_info.selection; + + // Use cluster width as quality. + int tp_quality; + + if (tp_rpc_type == rpc::Type::kiRPC) { + tp_quality = tp_clus_width; + } else { + tp_quality = tp_clus_width * 3 / 2; // RPC strip pitch is 1.5 times the iRPC strip pitch. + } + + // ID scheme used in FW + const int tp_ilink = tp_info.ilink; + + // Get Global Coordinates + float glob_phi; + float glob_theta; + double glob_rho; + double glob_z; + + if (tp_rpc_type == rpc::Type::kiRPC) { + // Handle iRPC Coordinates + const RPCRoll* roll = + dynamic_cast(this->context_.geometry_translator_.getRPCGeometry().roll(tp_det_id)); + const GlobalPoint& irpc_gp = roll->surface().toGlobal(LocalPoint(tp_data.x, tp_data.y, 0)); + + glob_phi = tp::radToDeg(irpc_gp.phi().value()); + glob_theta = tp::radToDeg(irpc_gp.theta().value()); + glob_rho = irpc_gp.perp(); + glob_z = irpc_gp.z(); + } else { + // Handle RPC Coordinates + const GlobalPoint& gp = this->context_.geometry_translator_.getGlobalPoint(tp); + glob_phi = tp::radToDeg(gp.phi().value()); + glob_theta = tp::radToDeg(gp.theta().value()); + glob_rho = gp.perp(); + glob_z = gp.z(); + } + + // Calculate EMTF Values + const int emtf_phi = tp::calcPhiInt(sector_, glob_phi); + const int emtf_bend = 0; + const int emtf_theta = tp::calcThetaInt(tp_endcap_pm, glob_theta); + const int emtf_qual = 0; + const int emtf_site = context_.site_lut_.lookup({tp_subsystem, tp_station, tp_ring}); + const int emtf_host = context_.host_lut_.lookup({tp_subsystem, tp_station, tp_ring}); + const int emtf_zones = context_.zone_lut_.getZones(emtf_host, emtf_theta); + + emtf_assert((0 <= emtf_phi) and (emtf_phi < 5040)); + emtf_assert((1 <= emtf_theta) and (emtf_theta < 128)); + + // Get flags + const bool tp_flag_neighbor = (tp_selection == TPSelection::kNeighbor); + const bool tp_flag_substitute = tp_info.flag_substitute; + const bool tp_flag_valid = tp_data.valid; + + // Set all the variables + hit.setId(tp_hit_id); + + hit.setRawDetId(tp_raw_id); + hit.setSubsystem(tp_subsystem); + hit.setEndcap(tp_endcap_pm); + hit.setSector(sector_); + hit.setSubsector(tp_subsector); + hit.setStation(tp_station); + hit.setRing(tp_ring); + hit.setLayer(tp_layer); + hit.setChamber(tp_chamber); + + hit.setCscId(tp_csc_id); + hit.setCscFR(tp_csc_facing == csc::Facing::kRear); + + hit.setStrip(tp_strip); + hit.setStripLo(tp_strip_lo); + hit.setStripHi(tp_strip_hi); + + hit.setWire1(tp_roll); + hit.setWire2(0); + + hit.setBend(tp_bend); + + hit.setBx(tp_bx); + hit.setSubbx(tp_subbx); + + hit.setQuality(tp_quality); + hit.setPattern(0); + + hit.setGlobPhi(glob_phi); + hit.setGlobTheta(glob_theta); + hit.setGlobPerp(glob_rho); + hit.setGlobZ(glob_z); + hit.setGlobTime(tp_time); + + hit.setEmtfChamber(tp_ilink); + hit.setEmtfSegment(tp_segment_id); + hit.setEmtfPhi(emtf_phi); + hit.setEmtfBend(emtf_bend); + hit.setEmtfTheta1(emtf_theta); + hit.setEmtfTheta2(0); + hit.setEmtfQual1(emtf_qual); + hit.setEmtfQual2(0); + hit.setEmtfSite(emtf_site); + hit.setEmtfHost(emtf_host); + hit.setEmtfZones(emtf_zones); + + hit.setFlagNeighbor(tp_flag_neighbor); + hit.setFlagSubstitute(tp_flag_substitute); + hit.setFlagValid(tp_flag_valid); +} diff --git a/L1Trigger/L1TMuonEndCapPhase2/src/DAQ/RPCTPSelector.cc b/L1Trigger/L1TMuonEndCapPhase2/src/DAQ/RPCTPSelector.cc new file mode 100644 index 0000000000000..628ba6a8d4804 --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/src/DAQ/RPCTPSelector.cc @@ -0,0 +1,113 @@ +#include "FWCore/MessageLogger/interface/MessageLogger.h" + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFConfiguration.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFConstants.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFContext.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/SubsystemTags.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/TPrimitives.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Utils/DebugUtils.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Utils/CSCUtils.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Utils/RPCUtils.h" + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/RPCTPSelector.h" + +using namespace emtf::phase2; + +RPCTPSelector::RPCTPSelector(const EMTFContext& context, const int& endcap, const int& sector) + : context_(context), endcap_(endcap), sector_(sector) {} + +void RPCTPSelector::select(const TriggerPrimitive& tp, TPInfo tp_info, ILinkTPCMap& ilink_tpc_map) const { + emtf_assert(tp.subsystem() == L1TMuon::kRPC); + + // Map RPC trigger primitives to input links + int ilink = getInputLink(tp, tp_info); // Returns RPC "link" index + + // Short-Circuit: Link not found (ilink = -1) + if (ilink < 0) { + return; + } + + ilink_tpc_map[ilink].emplace_back(tp, tp_info); +} + +// =========================================================================== +// Utils +// =========================================================================== +int RPCTPSelector::getInputLink(const TriggerPrimitive& tp, TPInfo& tp_info) const { + int ilink = -1; + + // Unpack detector info + const int tp_endcap = tp_info.endcap; + const int tp_sector = tp_info.sector; + const int tp_subsector = tp_info.subsector; + const int tp_station = tp_info.station; + const int tp_ring = tp_info.ring; + const int tp_csc_id = tp_info.csc_id; + + const RPCData& tp_data = tp.getRPCData(); + const int tp_emtf_sect = tp_data.emtf_sector; + const bool tp_is_CPPF = tp_data.isCPPF; + + // Short-Circuit: In neighbor chambers, have two separate CPPFDigis for the two EMTF sectors + if (tp_is_CPPF && (tp_emtf_sect != sector_)) + return ilink; + + // Find selection type + auto tp_selection = TPSelection::kNone; + + if (csc::isTPInSector(endcap_, sector_, tp_endcap, tp_sector)) { + tp_selection = TPSelection::kNative; + } else if (this->context_.config_.include_neighbor_en_ && + csc::isTPInNeighborSector(endcap_, sector_, tp_endcap, tp_sector, tp_subsector, tp_station, tp_csc_id)) { + tp_selection = TPSelection::kNeighbor; + } else { // Short-Circuit: tp_selection = TPSelection::kNone + return ilink; + } + + // Get chamber input link for this sector processor + ilink = calcInputLink(tp_subsector, tp_station, tp_ring, tp_csc_id, tp_selection); + + // Add selection info + tp_info.ilink = ilink; + tp_info.selection = tp_selection; + + return ilink; +} + +int RPCTPSelector::calcInputLink(const int& tp_subsector, + const int& tp_station, + const int& tp_ring, + const int& tp_csc_id, + const TPSelection& tp_selection) const { + int ilink = -1; + + // Links + // RE1,2,3,4 + GE1,2 : 54..71, 72..80, 81..89, 90..98 + // RE1,2,3,4 + GE1,2 (N) : 99..101, 102..103, 104..105, 106..107 + + if (tp_selection == TPSelection::kNative) { + const int ilink_offset = 54; + + if (tp_station == 1) { + ilink = ilink_offset + (tp_subsector - 1) * 9 + (tp_csc_id - 1); + } else { + ilink = ilink_offset + tp_station * 9 + (tp_csc_id - 1); + } + + emtf_assert((54 <= ilink) && (ilink < 99)); + } else { + const int ilink_offset = 99; + + if (tp_station == 1) { + ilink = ilink_offset + ((tp_station - 1) * 2) + ((tp_csc_id - 1) / 3); + } else if (tp_ring == 1) { + ilink = ilink_offset + ((tp_station - 1) * 2) + 1; + } else { + ilink = ilink_offset + ((tp_station - 1) * 2) + 2; + } + + emtf_assert((99 <= ilink) && (ilink < 108)); + } + + return ilink; +} diff --git a/L1Trigger/L1TMuonEndCapPhase2/src/DAQ/TPrimitives.cc b/L1Trigger/L1TMuonEndCapPhase2/src/DAQ/TPrimitives.cc new file mode 100644 index 0000000000000..800cf2a01f4c9 --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/src/DAQ/TPrimitives.cc @@ -0,0 +1,41 @@ +#include "L1Trigger/L1TMuon/interface/MuonTriggerPrimitive.h" + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/TPrimitives.h" + +using namespace emtf::phase2; + +TPEntry::TPEntry(const TPEntry& tp_entry) : tp_(tp_entry.tp_), info_(tp_entry.info_) { + // Do nothing +} + +TPEntry::TPEntry(const TriggerPrimitive& tp) : tp_(tp), info_() { + // Do nothing +} + +TPEntry::TPEntry(const TriggerPrimitive& tp, const TPInfo& tp_info) : tp_(tp), info_(tp_info) { + // Do nothing +} + +TPEntry::TPEntry(const CSCDetId& detid, const CSCCorrelatedLCTDigi& digi) : tp_(detid, digi), info_() { + // Do nothing +} + +TPEntry::TPEntry(const RPCDetId& detid, const RPCRecHit& rechit) : tp_(detid, rechit), info_() { + // Do nothing +} + +TPEntry::TPEntry(const GEMDetId& detid, const GEMPadDigiCluster& digi) : tp_(detid, digi), info_() { + // Do nothing +} + +TPEntry::TPEntry(const ME0DetId& detid, const ME0TriggerDigi& digi) : tp_(detid, digi), info_() { + // Do nothing +} + +TPEntry::TPEntry(const GEMDetId& detid, const ME0TriggerDigi& digi) : tp_(detid, digi), info_() { + // Do nothing +} + +TPEntry::~TPEntry() { + // Do nothing +} diff --git a/L1Trigger/L1TMuonEndCapPhase2/src/Data/ActivationLut.cc b/L1Trigger/L1TMuonEndCapPhase2/src/Data/ActivationLut.cc new file mode 100644 index 0000000000000..439983956200d --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/src/Data/ActivationLut.cc @@ -0,0 +1,223 @@ +#include + +#include "ap_int.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Data/ActivationLut.h" + +using namespace emtf::phase2; +using namespace emtf::phase2::data; + +ActivationLut::ActivationLut() { + // clang-format off + prompt_pt_lut_ = {{ + 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, + 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, + 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, + 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, + 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8101, 7970, 7842, 7719, 7595, 7479, 7362, 7246, 7137, 7028, + 6919, 6817, 6715, 6613, 6515, 6417, 6322, 6231, 6141, 6053, 5966, 5879, 5795, 5711, 5631, 5551, 5475, 5399, 5322, + 5250, 5177, 5104, 5035, 4966, 4897, 4832, 4762, 4701, 4635, 4573, 4512, 4453, 4392, 4333, 4275, 4217, 4162, 4108, + 4053, 3999, 3948, 3897, 3842, 3795, 3744, 3693, 3646, 3599, 3552, 3504, 3461, 3417, 3370, 3326, 3282, 3242, 3199, + 3159, 3115, 3075, 3035, 2995, 2959, 2919, 2882, 2842, 2806, 2770, 2733, 2697, 2664, 2628, 2595, 2559, 2526, 2493, + 2461, 2428, 2395, 2366, 2333, 2301, 2272, 2242, 2210, 2181, 2152, 2124, 2096, 2071, 2043, 2015, 1991, 1963, 1940, + 1916, 1889, 1865, 1842, 1819, 1796, 1773, 1753, 1730, 1708, 1689, 1666, 1647, 1625, 1606, 1588, 1569, 1547, 1529, + 1511, 1492, 1474, 1459, 1441, 1424, 1406, 1391, 1374, 1356, 1342, 1327, 1310, 1296, 1282, 1265, 1251, 1237, 1223, + 1209, 1195, 1181, 1168, 1154, 1141, 1127, 1117, 1103, 1090, 1077, 1066, 1053, 1043, 1030, 1020, 1007, 997, 986, 974, + 964, 954, 944, 931, 922, 912, 902, 892, 882, 873, 863, 854, 844, 835, 828, 818, 809, 799, 792, 783, 774, 767, 758, + 749, 742, 733, 726, 718, 711, 702, 695, 689, 680, 674, 667, 658, 652, 646, 639, 631, 624, 618, 612, 605, 599, 593, + 587, 581, 574, 568, 562, 556, 550, 544, 538, 532, 526, 520, 516, 510, 505, 499, 495, 489, 483, 480, 474, 468, 464, + 459, 453, 449, 444, 440, 434, 431, 425, 421, 416, 412, 407, 403, 398, 394, 391, 385, 382, 378, 373, 370, 366, 361, + 357, 354, 350, 345, 342, 338, 335, 330, 327, 323, 320, 317, 313, 310, 307, 302, 298, 295, 292, 289, 285, 282, 279, + 276, 273, 269, 266, 263, 260, 257, 254, 252, 249, 246, 243, 240, 237, 234, 232, 229, 226, 223, 220, 217, 216, 213, + 210, 207, 205, 202, 199, 196, 195, 192, 189, 188, 185, 182, 180, 178, 175, 173, 171, 168, 166, 164, 162, 159, 158, + 155, 152, 151, 148, 147, 144, 143, 140, 139, 136, 135, 132, 131, 128, 127, 124, 123, 120, 119, 116, 115, 114, 111, + 110, 107, 106, 105, 102, 101, 100, 97, 96, 93, 92, 91, 88, 87, 86, 84, 82, 81, 80, 77, 76, 75, 73, 71, 70, 69, 67, + 65, 64, 63, 61, 59, 58, 57, 56, 54, 52, 51, 50, 49, 47, 46, 44, 43, 42, 41, 39, 38, 37, 35, 34, 33, 32, 31, 29, 28, + 27, 25, 24, 23, 22, 21, 20, 19, 18, 16, 15, 14, 13, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 13, 14, 15, 16, 18, 19, 20, 21, 22, 23, 24, 25, 27, 28, 29, 31, 32, 33, 34, 35, 37, 38, 39, 41, 42, 43, 44, + 46, 47, 49, 50, 51, 52, 54, 56, 57, 58, 59, 61, 63, 64, 65, 67, 69, 70, 71, 73, 75, 76, 77, 80, 81, 82, 84, 86, 87, + 88, 91, 92, 93, 96, 97, 100, 101, 102, 105, 106, 107, 110, 111, 114, 115, 116, 119, 120, 123, 124, 127, 128, 131, + 132, 135, 136, 139, 140, 143, 144, 147, 148, 151, 152, 155, 158, 159, 162, 164, 166, 168, 171, 173, 175, 178, 180, + 182, 185, 188, 189, 192, 195, 196, 199, 202, 205, 207, 210, 213, 216, 217, 220, 223, 226, 229, 232, 234, 237, 240, + 243, 246, 249, 252, 254, 257, 260, 263, 266, 269, 273, 276, 279, 282, 285, 289, 292, 295, 298, 302, 307, 310, 313, + 317, 320, 323, 327, 330, 335, 338, 342, 345, 350, 354, 357, 361, 366, 370, 373, 378, 382, 385, 391, 394, 398, 403, + 407, 412, 416, 421, 425, 431, 434, 440, 444, 449, 453, 459, 464, 468, 474, 480, 483, 489, 495, 499, 505, 510, 516, + 520, 526, 532, 538, 544, 550, 556, 562, 568, 574, 581, 587, 593, 599, 605, 612, 618, 624, 631, 639, 646, 652, 658, + 667, 674, 680, 689, 695, 702, 711, 718, 726, 733, 742, 749, 758, 767, 774, 783, 792, 799, 809, 818, 828, 835, 844, + 854, 863, 873, 882, 892, 902, 912, 922, 931, 944, 954, 964, 974, 986, 997, 1007, 1020, 1030, 1043, 1053, 1066, 1077, + 1090, 1103, 1117, 1127, 1141, 1154, 1168, 1181, 1195, 1209, 1223, 1237, 1251, 1265, 1282, 1296, 1310, 1327, 1342, + 1356, 1374, 1391, 1406, 1424, 1441, 1459, 1474, 1492, 1511, 1529, 1547, 1569, 1588, 1606, 1625, 1647, 1666, 1689, + 1708, 1730, 1753, 1773, 1796, 1819, 1842, 1865, 1889, 1916, 1940, 1963, 1991, 2015, 2043, 2071, 2096, 2124, 2152, + 2181, 2210, 2242, 2272, 2301, 2333, 2366, 2395, 2428, 2461, 2493, 2526, 2559, 2595, 2628, 2664, 2697, 2733, 2770, + 2806, 2842, 2882, 2919, 2959, 2995, 3035, 3075, 3115, 3159, 3199, 3242, 3282, 3326, 3370, 3417, 3461, 3504, 3552, + 3599, 3646, 3693, 3744, 3795, 3842, 3897, 3948, 3999, 4053, 4108, 4162, 4217, 4275, 4333, 4392, 4453, 4512, 4573, + 4635, 4701, 4762, 4832, 4897, 4966, 5035, 5104, 5177, 5250, 5322, 5399, 5475, 5551, 5631, 5711, 5795, 5879, 5966, + 6053, 6141, 6231, 6322, 6417, 6515, 6613, 6715, 6817, 6919, 7028, 7137, 7246, 7362, 7479, 7595, 7719, 7842, 7970, + 8101, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, + 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, + 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, + 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, + 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191 + }}; + + disp_pt_lut_ = {{ + 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, + 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8187, + 7954, 7733, 7522, 7322, 7132, 6949, 6777, 6610, 6453, 6301, 6155, 6016, 5882, 5753, 5629, 5511, 5397, 5285, 5179, + 5076, 4978, 4881, 4789, 4699, 4612, 4528, 4447, 4368, 4292, 4218, 4146, 4075, 4008, 3942, 3878, 3815, 3754, 3695, + 3638, 3581, 3527, 3474, 3422, 3371, 3322, 3274, 3227, 3181, 3136, 3092, 3050, 3007, 2967, 2927, 2887, 2849, 2812, + 2774, 2739, 2704, 2669, 2635, 2602, 2569, 2538, 2507, 2477, 2446, 2416, 2388, 2359, 2331, 2304, 2278, 2251, 2225, + 2200, 2175, 2150, 2126, 2102, 2079, 2056, 2032, 2011, 1989, 1967, 1946, 1926, 1905, 1885, 1865, 1845, 1826, 1807, + 1788, 1770, 1752, 1735, 1716, 1700, 1682, 1665, 1648, 1632, 1616, 1599, 1584, 1569, 1553, 1538, 1523, 1509, 1494, + 1481, 1466, 1452, 1438, 1424, 1412, 1398, 1386, 1372, 1359, 1347, 1334, 1322, 1310, 1298, 1287, 1274, 1263, 1252, + 1240, 1229, 1218, 1208, 1197, 1185, 1175, 1165, 1154, 1144, 1134, 1124, 1114, 1105, 1095, 1085, 1076, 1066, 1058, + 1049, 1039, 1030, 1021, 1013, 1004, 995, 988, 979, 970, 963, 954, 946, 938, 930, 923, 915, 906, 899, 891, 884, 876, + 870, 863, 855, 848, 841, 834, 826, 820, 814, 806, 800, 794, 786, 780, 774, 767, 761, 755, 749, 742, 736, 730, 724, + 719, 712, 706, 700, 695, 689, 684, 677, 672, 666, 661, 656, 650, 645, 640, 635, 629, 624, 619, 614, 609, 604, 599, + 594, 589, 584, 579, 575, 570, 565, 560, 556, 551, 546, 542, 537, 532, 528, 523, 520, 515, 511, 506, 502, 498, 493, + 490, 486, 481, 477, 473, 470, 465, 461, 457, 453, 450, 446, 442, 438, 435, 431, 427, 423, 420, 416, 412, 408, 405, + 401, 397, 395, 391, 387, 383, 381, 377, 373, 371, 367, 363, 361, 357, 353, 351, 347, 345, 341, 338, 335, 332, 329, + 326, 322, 320, 316, 314, 311, 308, 305, 303, 299, 297, 294, 291, 288, 286, 284, 280, 278, 275, 273, 269, 267, 264, + 262, 260, 257, 255, 252, 249, 247, 244, 242, 239, 237, 235, 232, 230, 228, 225, 223, 221, 218, 216, 214, 213, 210, + 208, 206, 203, 201, 199, 198, 195, 193, 191, 188, 186, 185, 183, 180, 178, 177, 175, 172, 170, 169, 167, 164, 163, + 161, 159, 158, 155, 153, 152, 150, 148, 146, 144, 143, 141, 140, 138, 135, 134, 132, 131, 129, 128, 125, 124, 122, + 121, 119, 118, 115, 114, 112, 111, 109, 108, 106, 104, 103, 101, 100, 98, 97, 96, 94, 93, 91, 89, 88, 86, 85, 84, + 82, 81, 80, 77, 76, 75, 74, 72, 71, 70, 68, 67, 66, 65, 62, 61, 60, 59, 57, 56, 55, 54, 53, 51, 50, 49, 48, 47, 45, + 43, 42, 41, 40, 39, 37, 36, 35, 34, 33, 32, 31, 30, 28, 27, 26, 25, 24, 23, 22, 21, 20, 18, 17, 15, 14, 13, 12, 11, + 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 17, 18, 20, 21, 22, 23, 24, 25, + 26, 27, 28, 30, 31, 32, 33, 34, 35, 36, 37, 39, 40, 41, 42, 43, 45, 47, 48, 49, 50, 51, 53, 54, 55, 56, 57, 59, 60, + 61, 62, 65, 66, 67, 68, 70, 71, 72, 74, 75, 76, 77, 80, 81, 82, 84, 85, 86, 88, 89, 91, 93, 94, 96, 97, 98, 100, + 101, 103, 104, 106, 108, 109, 111, 112, 114, 115, 118, 119, 121, 122, 124, 125, 128, 129, 131, 132, 134, 135, 138, + 140, 141, 143, 144, 146, 148, 150, 152, 153, 155, 158, 159, 161, 163, 164, 167, 169, 170, 172, 175, 177, 178, 180, + 183, 185, 186, 188, 191, 193, 195, 198, 199, 201, 203, 206, 208, 210, 213, 214, 216, 218, 221, 223, 225, 228, 230, + 232, 235, 237, 239, 242, 244, 247, 249, 252, 255, 257, 260, 262, 264, 267, 269, 273, 275, 278, 280, 284, 286, 288, + 291, 294, 297, 299, 303, 305, 308, 311, 314, 316, 320, 322, 326, 329, 332, 335, 338, 341, 345, 347, 351, 353, 357, + 361, 363, 367, 371, 373, 377, 381, 383, 387, 391, 395, 397, 401, 405, 408, 412, 416, 420, 423, 427, 431, 435, 438, + 442, 446, 450, 453, 457, 461, 465, 470, 473, 477, 481, 486, 490, 493, 498, 502, 506, 511, 515, 520, 523, 528, 532, + 537, 542, 546, 551, 556, 560, 565, 570, 575, 579, 584, 589, 594, 599, 604, 609, 614, 619, 624, 629, 635, 640, 645, + 650, 656, 661, 666, 672, 677, 684, 689, 695, 700, 706, 712, 719, 724, 730, 736, 742, 749, 755, 761, 767, 774, 780, + 786, 794, 800, 806, 814, 820, 826, 834, 841, 848, 855, 863, 870, 876, 884, 891, 899, 906, 915, 923, 930, 938, 946, + 954, 963, 970, 979, 988, 995, 1004, 1013, 1021, 1030, 1039, 1049, 1058, 1066, 1076, 1085, 1095, 1105, 1114, 1124, + 1134, 1144, 1154, 1165, 1175, 1185, 1197, 1208, 1218, 1229, 1240, 1252, 1263, 1274, 1287, 1298, 1310, 1322, 1334, + 1347, 1359, 1372, 1386, 1398, 1412, 1424, 1438, 1452, 1466, 1481, 1494, 1509, 1523, 1538, 1553, 1569, 1584, 1599, + 1616, 1632, 1648, 1665, 1682, 1700, 1716, 1735, 1752, 1770, 1788, 1807, 1826, 1845, 1865, 1885, 1905, 1926, 1946, + 1967, 1989, 2011, 2032, 2056, 2079, 2102, 2126, 2150, 2175, 2200, 2225, 2251, 2278, 2304, 2331, 2359, 2388, 2416, + 2446, 2477, 2507, 2538, 2569, 2602, 2635, 2669, 2704, 2739, 2774, 2812, 2849, 2887, 2927, 2967, 3007, 3050, 3092, + 3136, 3181, 3227, 3274, 3322, 3371, 3422, 3474, 3527, 3581, 3638, 3695, 3754, 3815, 3878, 3942, 4008, 4075, 4146, + 4218, 4292, 4368, 4447, 4528, 4612, 4699, 4789, 4881, 4978, 5076, 5179, 5285, 5397, 5511, 5629, 5753, 5882, 6016, + 6155, 6301, 6453, 6610, 6777, 6949, 7132, 7322, 7522, 7733, 7954, 8187, 8191, 8191, 8191, 8191, 8191, 8191, 8191, + 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, + 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191 + }}; + + rels_lut_ = {{ + 64, 64, 64, 65, 65, 65, 66, 66, 66, 67, 67, 68, 68, 68, 69, 69, 69, 70, 70, 70, 71, 71, 71, 72, 72, 73, 73, 73, 74, + 74, 74, 75, 75, 75, 76, 76, 76, 77, 77, 78, 78, 78, 79, 79, 79, 80, 80, 80, 81, 81, 81, 82, 82, 82, 83, 83, 83, 84, + 84, 84, 85, 85, 85, 86, 86, 86, 87, 87, 87, 87, 88, 88, 88, 89, 89, 89, 90, 90, 90, 91, 91, 91, 91, 92, 92, 92, 93, + 93, 93, 93, 94, 94, 94, 95, 95, 95, 95, 96, 96, 96, 96, 97, 97, 97, 98, 98, 98, 98, 99, 99, 99, 99, 100, 100, 100, + 100, 101, 101, 101, 101, 101, 102, 102, 102, 102, 103, 103, 103, 103, 104, 104, 104, 104, 104, 105, 105, 105, 105, + 105, 106, 106, 106, 106, 106, 107, 107, 107, 107, 107, 108, 108, 108, 108, 108, 109, 109, 109, 109, 109, 109, 110, + 110, 110, 110, 110, 110, 111, 111, 111, 111, 111, 111, 112, 112, 112, 112, 112, 112, 112, 113, 113, 113, 113, 113, + 113, 113, 114, 114, 114, 114, 114, 114, 114, 115, 115, 115, 115, 115, 115, 115, 115, 116, 116, 116, 116, 116, 116, + 116, 116, 116, 117, 117, 117, 117, 117, 117, 117, 117, 117, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, + 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, + 120, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, + 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, + 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 14, 14, + 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, + 18, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 24, 24, 24, + 24, 25, 25, 25, 25, 26, 26, 26, 26, 26, 27, 27, 27, 27, 28, 28, 28, 28, 29, 29, 29, 29, 30, 30, 30, 31, 31, 31, 31, + 32, 32, 32, 32, 33, 33, 33, 34, 34, 34, 34, 35, 35, 35, 36, 36, 36, 36, 37, 37, 37, 38, 38, 38, 39, 39, 39, 40, 40, + 40, 40, 41, 41, 41, 42, 42, 42, 43, 43, 43, 44, 44, 44, 45, 45, 45, 46, 46, 46, 47, 47, 47, 48, 48, 48, 49, 49, 49, + 50, 50, 51, 51, 51, 52, 52, 52, 53, 53, 53, 54, 54, 54, 55, 55, 56, 56, 56, 57, 57, 57, 58, 58, 58, 59, 59, 59, 60, + 60, 61, 61, 61, 62, 62, 62, 63, 63 + }}; + + dxy_lut_ = {{ + 0, 0, 2, 2, 2, 2, 4, 4, 4, 4, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 10, 10, 10, 10, 11, 11, 11, 12, 12, 12, 12, 13, + 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 18, 18, 18, 19, 19, 19, 19, 20, 20, 20, 20, 22, 22, 22, + 22, 24, 24, 24, 24, 26, 26, 26, 26, 28, 28, 28, 28, 30, 30, 30, 33, 33, 33, 33, 36, 36, 36, 36, 39, 39, 39, 39, 43, + 43, 43, 43, 47, 47, 47, 47, 51, 51, 51, 51, 56, 56, 56, 62, 62, 62, 62, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, + -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, + -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, + -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, + -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, + -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, + -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, + -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, + -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, + -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, + -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, + -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, + -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, + -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, + -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, + -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, + -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, + -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, -64, + -62, -62, -62, -62, -56, -56, -56, -51, -51, -51, -51, -47, -47, -47, -47, -43, -43, -43, -43, -39, -39, -39, -39, + -36, -36, -36, -36, -33, -33, -33, -33, -30, -30, -30, -28, -28, -28, -28, -26, -26, -26, -26, -24, -24, -24, -24, + -22, -22, -22, -22, -20, -20, -20, -20, -19, -19, -19, -19, -18, -18, -18, -16, -16, -16, -16, -15, -15, -15, -15, + -14, -14, -14, -14, -13, -13, -13, -13, -12, -12, -12, -12, -11, -11, -11, -10, -10, -10, -10, -8, -8, -8, -8, -7, + -7, -7, -7, -6, -6, -6, -6, -4, -4, -4, -4, -2, -2, -2, -2, 0 + }}; + // clang-format on +} + +ActivationLut::~ActivationLut() { + // Do Nothing +} + +void ActivationLut::update(const edm::Event&, const edm::EventSetup&) { + // Do Nothing +} + +const trk_pt_t& ActivationLut::lookupPromptPt(const trk_nn_address_t& address) const { + ap_uint<10> bin = address.to_string(AP_HEX).c_str(); + return prompt_pt_lut_[bin]; +} + +const trk_pt_t& ActivationLut::lookupDispPt(const trk_nn_address_t& address) const { + ap_uint<10> bin = address.to_string(AP_HEX).c_str(); + return disp_pt_lut_[bin]; +} + +const trk_rels_t& ActivationLut::lookupRels(const trk_nn_address_t& address) const { + ap_uint<10> bin = address.to_string(AP_HEX).c_str(); + return rels_lut_[bin]; +} + +const trk_dxy_t& ActivationLut::lookupDxy(const trk_nn_address_t& address) const { + ap_uint<10> bin = address.to_string(AP_HEX).c_str(); + return dxy_lut_[bin]; +} diff --git a/L1Trigger/L1TMuonEndCapPhase2/src/Data/HostLut.cc b/L1Trigger/L1TMuonEndCapPhase2/src/Data/HostLut.cc new file mode 100644 index 0000000000000..d6792fc64302d --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/src/Data/HostLut.cc @@ -0,0 +1,52 @@ +#include + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Data/HostLut.h" + +using namespace emtf::phase2::data; + +// Static +const int HostLut::kInvalid = -1; + +// Member +HostLut::HostLut() { + lut_[{1, 1, 4}] = 0; // ME1/1a + lut_[{1, 1, 1}] = 0; // ME1/1b + lut_[{1, 1, 2}] = 1; // ME1/2 + lut_[{1, 1, 3}] = 2; // ME1/3 + lut_[{1, 2, 1}] = 3; // ME2/1 + lut_[{1, 2, 2}] = 4; // ME2/2 + lut_[{1, 3, 1}] = 5; // ME3/1 + lut_[{1, 3, 2}] = 6; // ME3/2 + lut_[{1, 4, 1}] = 7; // ME4/1 + lut_[{1, 4, 2}] = 8; // ME4/2 + lut_[{3, 1, 1}] = 9; // GE1/1 + lut_[{2, 1, 2}] = 10; // RE1/2 + lut_[{2, 1, 3}] = 11; // RE1/3 + lut_[{3, 2, 1}] = 12; // GE2/1 + lut_[{2, 2, 2}] = 13; // RE2/2 + lut_[{2, 2, 3}] = 13; // RE2/3 + lut_[{2, 3, 1}] = 14; // RE3/1 + lut_[{2, 3, 2}] = 15; // RE3/2 + lut_[{2, 3, 3}] = 15; // RE3/3 + lut_[{2, 4, 1}] = 16; // RE4/1 + lut_[{2, 4, 2}] = 17; // RE4/2 + lut_[{2, 4, 3}] = 17; // RE4/3 + lut_[{4, 1, 4}] = 18; // ME0 +} + +HostLut::~HostLut() { + // Do Nothing +} + +void HostLut::update(const edm::Event&, const edm::EventSetup&) { + // Do Nothing +} + +const int& HostLut::lookup(const std::tuple& key) const { + auto found = lut_.find(key); + + if (found == lut_.end()) + return HostLut::kInvalid; + + return found->second; +} diff --git a/L1Trigger/L1TMuonEndCapPhase2/src/Data/SiteLut.cc b/L1Trigger/L1TMuonEndCapPhase2/src/Data/SiteLut.cc new file mode 100644 index 0000000000000..92c75d20ba22a --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/src/Data/SiteLut.cc @@ -0,0 +1,52 @@ +#include + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Data/SiteLut.h" + +using namespace emtf::phase2::data; + +// Static +const int SiteLut::kInvalid = -1; + +// Member +SiteLut::SiteLut() { + lut_[{1, 1, 4}] = 0; // ME1/1a + lut_[{1, 1, 1}] = 0; // ME1/1b + lut_[{1, 1, 2}] = 1; // ME1/2 + lut_[{1, 1, 3}] = 1; // ME1/3 + lut_[{1, 2, 1}] = 2; // ME2/1 + lut_[{1, 2, 2}] = 2; // ME2/2 + lut_[{1, 3, 1}] = 3; // ME3/1 + lut_[{1, 3, 2}] = 3; // ME3/2 + lut_[{1, 4, 1}] = 4; // ME4/1 + lut_[{1, 4, 2}] = 4; // ME4/2 + lut_[{2, 1, 2}] = 5; // RE1/2 + lut_[{2, 1, 3}] = 5; // RE1/3 + lut_[{2, 2, 2}] = 6; // RE2/2 + lut_[{2, 2, 3}] = 6; // RE2/3 + lut_[{2, 3, 1}] = 7; // RE3/1 + lut_[{2, 3, 2}] = 7; // RE3/2 + lut_[{2, 3, 3}] = 7; // RE3/3 + lut_[{2, 4, 1}] = 8; // RE4/1 + lut_[{2, 4, 2}] = 8; // RE4/2 + lut_[{2, 4, 3}] = 8; // RE4/3 + lut_[{3, 1, 1}] = 9; // GE1/1 + lut_[{3, 2, 1}] = 10; // GE2/1 + lut_[{4, 1, 4}] = 11; // ME0 +} + +SiteLut::~SiteLut() { + // Do Nothing +} + +void SiteLut::update(const edm::Event&, const edm::EventSetup&) { + // Do Nothing +} + +const int& SiteLut::lookup(const std::tuple& key) const { + auto found = lut_.find(key); + + if (found == lut_.end()) + return SiteLut::kInvalid; + + return found->second; +} diff --git a/L1Trigger/L1TMuonEndCapPhase2/src/Data/TimeZoneLut.cc b/L1Trigger/L1TMuonEndCapPhase2/src/Data/TimeZoneLut.cc new file mode 100644 index 0000000000000..09b0d170d2855 --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/src/Data/TimeZoneLut.cc @@ -0,0 +1,58 @@ +#include + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Data/TimeZoneLut.h" + +using namespace emtf::phase2::data; + +// Static +bool TimeZoneLut::in_range(const std::pair& range, const int& bx) const { + return range.first <= bx && bx <= range.second; +} + +// Member +TimeZoneLut::TimeZoneLut() { + lut_[0] = {-1, 0}; // ME1/1 + lut_[1] = {-1, 0}; // ME1/2 + lut_[2] = {-1, 0}; // ME1/3 + lut_[3] = {-1, 0}; // ME2/1 + lut_[4] = {-1, 0}; // ME2/2 + lut_[5] = {-1, 0}; // ME3/1 + lut_[6] = {-1, 0}; // ME3/2 + lut_[7] = {-1, 0}; // ME4/1 + lut_[8] = {-1, 0}; // ME4/2 + lut_[9] = {-1, 0}; // GE1/1 + lut_[10] = {0, 0}; // RE1/2 + lut_[11] = {0, 0}; // RE1/3 + lut_[12] = {-1, 0}; // GE2/1 + lut_[13] = {0, 0}; // RE2/2 + lut_[14] = {0, 0}; // RE3/1 + lut_[15] = {0, 0}; // RE3/2 + lut_[16] = {0, 0}; // RE4/1 + lut_[17] = {0, 0}; // RE4/2 + lut_[18] = {0, 0}; // ME0 +} + +TimeZoneLut::~TimeZoneLut() { + // Do Nothing +} + +void TimeZoneLut::update(const edm::Event&, const edm::EventSetup&) { + // Do Nothing +} + +int TimeZoneLut::getTimezones(const int& host, const int& bx) const { + auto found = lut_.find(host); + + // Short-Circuit: Host doesn't exist + if (found == lut_.end()) + return 0x0; + + // Build word + int word = 0x0; + + word |= in_range(found->second, bx) ? 0b001 : 0; + word |= in_range(found->second, bx + 1) ? 0b010 : 0; // +1 BX delay + word |= in_range(found->second, bx + 2) ? 0b100 : 0; // +2 BX delay + + return word; +} diff --git a/L1Trigger/L1TMuonEndCapPhase2/src/Data/ZoneLut.cc b/L1Trigger/L1TMuonEndCapPhase2/src/Data/ZoneLut.cc new file mode 100644 index 0000000000000..9c73c5dc71bed --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/src/Data/ZoneLut.cc @@ -0,0 +1,125 @@ + +#include + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Data/ZoneLut.h" + +using namespace emtf::phase2::data; + +ZoneLut::ZoneLut() { + auto& zone0 = zones_.emplace_back(); + zone0.lut_[0] = {4, 26}; // ME1/1 + zone0.lut_[3] = {4, 25}; // ME2/1 + zone0.lut_[5] = {4, 25}; // ME3/1 + zone0.lut_[7] = {4, 25}; // ME4/1 + zone0.lut_[9] = {17, 26}; // GE1/1 + zone0.lut_[12] = {7, 25}; // GE2/1 + zone0.lut_[14] = {4, 25}; // RE3/1 + zone0.lut_[16] = {4, 25}; // RE4/1 + zone0.lut_[18] = {4, 23}; // ME0 + + auto& zone1 = zones_.emplace_back(); + zone1.lut_[0] = {24, 53}; // ME1/1 + zone1.lut_[1] = {46, 54}; // ME1/2 + zone1.lut_[3] = {23, 49}; // ME2/1 + zone1.lut_[5] = {23, 41}; // ME3/1 + zone1.lut_[6] = {44, 54}; // ME3/2 + zone1.lut_[7] = {23, 35}; // ME4/1 + zone1.lut_[8] = {38, 54}; // ME4/2 + zone1.lut_[9] = {24, 52}; // GE1/1 + zone1.lut_[10] = {52, 56}; // RE1/2 + zone1.lut_[12] = {23, 46}; // GE2/1 + zone1.lut_[14] = {23, 36}; // RE3/1 + zone1.lut_[15] = {40, 52}; // RE3/2 + zone1.lut_[16] = {23, 31}; // RE4/1 + zone1.lut_[17] = {35, 54}; // RE4/2 + + auto& zone2 = zones_.emplace_back(); + zone2.lut_[1] = {52, 88}; // ME1/2 + zone2.lut_[4] = {52, 88}; // ME2/2 + zone2.lut_[6] = {50, 88}; // ME3/2 + zone2.lut_[8] = {50, 88}; // ME4/2 + zone2.lut_[10] = {52, 84}; // RE1/2 + zone2.lut_[13] = {52, 88}; // RE2/2 + zone2.lut_[15] = {48, 84}; // RE3/2 + zone2.lut_[17] = {52, 84}; // RE4/2 +} + +ZoneLut::~ZoneLut() { + // Do Nothing +} + +void ZoneLut::update(const edm::Event&, const edm::EventSetup&) { + // Do Nothing +} + +int ZoneLut::getZones(const int& host, const int& theta) const { + int i = 0; + int word = 0; + + for (const auto& zone : zones_) { + bool in_zone = zone.contains(host, theta); + + if (in_zone) { + word |= (1u << i); + } + + ++i; + } + + return word; +} + +int ZoneLut::getZones(const int& host, const int& theta1, const int& theta2) const { + int i = 0; + int word = 0; + + for (const auto& zone : zones_) { + bool in_zone = zone.contains(host, theta1, theta2); + + if (in_zone) { + word |= (1u << i); + } + + ++i; + } + + return word; +} + +bool Zone::contains(const int& host, const int& theta) const { + // Short-Circuit: LUT not found + auto found = lut_.find(host); + + if (found == lut_.end()) + return false; + + // Short-Circuit: Must be within theta range + auto& theta_range = found->second; + + if (theta_range.first <= theta && theta <= theta_range.second) { + return true; + } + + return false; +} + +bool Zone::contains(const int& host, const int& theta1, const int& theta2) const { + // Short-Circuit: LUT not found + auto found = lut_.find(host); + + if (found == lut_.end()) + return false; + + // Short-Circuit: Must be within theta range + auto& theta_range = found->second; + + if (theta_range.first <= theta1 && theta1 <= theta_range.second) { + return true; + } + + if (theta_range.first <= theta2 && theta2 <= theta_range.second) { + return true; + } + + return false; +} diff --git a/L1Trigger/L1TMuonEndCapPhase2/src/EMTFConfiguration.cc b/L1Trigger/L1TMuonEndCapPhase2/src/EMTFConfiguration.cc new file mode 100644 index 0000000000000..7a98785970b05 --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/src/EMTFConfiguration.cc @@ -0,0 +1,52 @@ +#include + +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/EventSetup.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFConfiguration.h" + +using namespace emtf::phase2; + +EMTFConfiguration::EMTFConfiguration(const edm::ParameterSet& pset) { + verbosity_ = pset.getUntrackedParameter("Verbosity"); + + // Validation + validation_dir_ = pset.getParameter("ValidationDirectory"); + + // Neural Network + prompt_graph_path_ = pset.getParameter("PromptGraphPath"); + displ_graph_path_ = pset.getParameter("DisplacedGraphPath"); + + // Trigger + min_bx_ = pset.getParameter("MinBX"); + max_bx_ = pset.getParameter("MaxBX"); + bx_window_ = pset.getParameter("BXWindow"); + + // Subsystems + csc_en_ = pset.getParameter("CSCEnabled"); + rpc_en_ = pset.getParameter("RPCEnabled"); + gem_en_ = pset.getParameter("GEMEnabled"); + me0_en_ = pset.getParameter("ME0Enabled"); + ge0_en_ = pset.getParameter("GE0Enabled"); + + csc_bx_shift_ = pset.getParameter("CSCInputBXShift"); + rpc_bx_shift_ = pset.getParameter("RPCInputBXShift"); + gem_bx_shift_ = pset.getParameter("GEMInputBXShift"); + me0_bx_shift_ = pset.getParameter("ME0InputBXShift"); + + csc_input_ = pset.getParameter("CSCInput"); + rpc_input_ = pset.getParameter("RPCInput"); + gem_input_ = pset.getParameter("GEMInput"); + me0_input_ = pset.getParameter("ME0Input"); + ge0_input_ = pset.getParameter("GE0Input"); + + // Primitive Selection + include_neighbor_en_ = pset.getParameter("IncludeNeighborEnabled"); +} + +EMTFConfiguration::~EMTFConfiguration() {} + +void EMTFConfiguration::update(const edm::Event& i_event, const edm::EventSetup& i_event_setup) { + // Do Nothing +} diff --git a/L1Trigger/L1TMuonEndCapPhase2/src/EMTFContext.cc b/L1Trigger/L1TMuonEndCapPhase2/src/EMTFContext.cc new file mode 100644 index 0000000000000..c2171473846ba --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/src/EMTFContext.cc @@ -0,0 +1,108 @@ +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/EventSetup.h" +#include "FWCore/Framework/interface/ConsumesCollector.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" + +#include "L1Trigger/L1TMuon/interface/GeometryTranslator.h" + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFConfiguration.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFContext.h" + +using namespace emtf::phase2; + +EMTFContext::EMTFContext(const edm::ParameterSet& pset, edm::ConsumesCollector i_consumes_collector) + : // Helpers + geometry_translator_(i_consumes_collector), + + // EMTF + config_(pset), + model_(*this), + + // Prompt Neural Network + prompt_graph_ptr_(nullptr), + prompt_session_ptr_(nullptr), + + // Displaced Neural Network + disp_graph_ptr_(nullptr), + disp_session_ptr_(nullptr), + + // Data + site_lut_(), + host_lut_(), + zone_lut_(), + timezone_lut_(), + activation_lut_(), + + // Layers + hitmap_building_layer_(*this), + pattern_matching_layer_(*this), + road_sorting_layer_(*this), + track_building_layer_(*this), + duplicate_removal_layer_(*this), + parameter_assignment_layer_(*this), + output_layer_(*this) { + // Do Nothing +} + +EMTFContext::~EMTFContext() { + // Delete Prompt Neural Network + if (prompt_session_ptr_ != nullptr) { + tensorflow::closeSession(prompt_session_ptr_); + delete prompt_session_ptr_; + } + + if (prompt_graph_ptr_ != nullptr) { + delete prompt_graph_ptr_; + } + + // Delete Displaced Neural Network + if (disp_session_ptr_ != nullptr) { + tensorflow::closeSession(disp_session_ptr_); + delete disp_session_ptr_; + } + + if (disp_graph_ptr_ != nullptr) { + delete disp_graph_ptr_; + } +} + +void EMTFContext::update(const edm::Event& i_event, const edm::EventSetup& i_event_setup) { + // Update Helpers + geometry_translator_.checkAndUpdateGeometry(i_event_setup); + + // Update Config + config_.update(i_event, i_event_setup); + + // Update Prompt Neural Network + if (prompt_session_ptr_ != nullptr) { + delete prompt_session_ptr_; + } + + if (prompt_graph_ptr_ != nullptr) { + delete prompt_graph_ptr_; + } + + prompt_graph_ptr_ = tensorflow::loadGraphDef(edm::FileInPath(config_.prompt_graph_path_).fullPath()); + + prompt_session_ptr_ = tensorflow::createSession(prompt_graph_ptr_); + + // Update Displaced Neural Network + if (disp_session_ptr_ != nullptr) { + delete disp_session_ptr_; + } + + if (disp_graph_ptr_ != nullptr) { + delete disp_graph_ptr_; + } + + disp_graph_ptr_ = tensorflow::loadGraphDef(edm::FileInPath(config_.displ_graph_path_).fullPath()); + + disp_session_ptr_ = tensorflow::createSession(disp_graph_ptr_); + + // Update Data + site_lut_.update(i_event, i_event_setup); + host_lut_.update(i_event, i_event_setup); + zone_lut_.update(i_event, i_event_setup); + timezone_lut_.update(i_event, i_event_setup); + activation_lut_.update(i_event, i_event_setup); +} diff --git a/L1Trigger/L1TMuonEndCapPhase2/src/EMTFModel.cc b/L1Trigger/L1TMuonEndCapPhase2/src/EMTFModel.cc new file mode 100644 index 0000000000000..6bbf95e39d387 --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/src/EMTFModel.cc @@ -0,0 +1,661 @@ +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFContext.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Utils/DebugUtils.h" + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFModel.h" + +using namespace emtf::phase2; +using namespace emtf::phase2::model; + +EMTFModel::EMTFModel(const EMTFContext& context) : context_(context) { + // =========================================================================== + // Zone 0 + // =========================================================================== + + // clang-format off + zones::hitmap_t&& zone0_hm = { + { // Row 0 + { + site_id_t::kME0, { + {114, 38, 90 }, + {108, 75, 127}, + {109, 113, 165}, + {110, 150, 202}, + {111, 188, 240}, + {112, 225, 277}, + {113, 263, 315} + } + } + }, + { // Row 1 + { + site_id_t::kGE11, { + {99 , 38, 90 }, + {54 , 75, 127}, + {55 , 113, 165}, + {56 , 150, 202}, + {63 , 188, 240}, + {64 , 225, 277}, + {65 , 263, 315} + } + } + }, + { // Row 2 + { + site_id_t::kME11, { + {45 , 38, 90 }, + {0 , 75, 127}, + {1 , 113, 165}, + {2 , 150, 202}, + {9 , 188, 240}, + {10 , 225, 277}, + {11 , 263, 315} + } + } + }, + { // Row 3 + { + site_id_t::kGE21, { + {102, 0 , 90 }, + {72 , 75 , 165}, + {73 , 150 , 240}, + {74 , 225 , 315} + } + } + }, + { // Row 4 + { + site_id_t::kME2, { + {48 , 0 , 90 }, + {18 , 75 , 165}, + {19 , 150 , 240}, + {20 , 225 , 315} + } + } + }, + { // Row 5 + { + site_id_t::kME3, { + {50 , 0 , 90 }, + {27 , 75 , 165}, + {28 , 150 , 240}, + {29 , 225 , 315} + } + } + }, + { // Row 6 + { + site_id_t::kRE3, { + {104, 0 , 90 }, + {81 , 75 , 165}, + {82 , 150 , 240}, + {83 , 225 , 315} + } + } + }, + { // Row 7 + { + site_id_t::kME4, { + {52 , 0 , 90 }, + {36 , 75 , 165}, + {37 , 150 , 240}, + {38 , 225 , 315} + } + }, + { + site_id_t::kRE4, { + {106, 0 , 90 }, + {90 , 75 , 165}, + {91 , 150 , 240}, + {92 , 225 , 315} + } + } + }, + }; + + std::vector zone0_prompt_pd = { + {{49, 55, 61}, {49, 55, 61}, {50, 55, 60}, {53, 55, 57}, {53, 55, 57}, {54, 55, 56}, {54, 55, 56}, {53, 55, 57}}, + {{42, 47, 52}, {42, 47, 52}, {45, 49, 53}, {53, 54, 56}, {53, 55, 57}, {55, 56, 57}, {54, 56, 58}, {54, 56, 59}}, + {{58, 63, 68}, {58, 63, 68}, {57, 61, 65}, {54, 56, 57}, {53, 55, 57}, {53, 54, 55}, {52, 54, 56}, {51, 54, 56}}, + {{35, 42, 49}, {36, 42, 48}, {39, 45, 51}, {52, 54, 56}, {54, 55, 56}, {54, 57, 59}, {54, 57, 60}, {52, 57, 61}}, + {{61, 68, 75}, {62, 68, 74}, {59, 65, 71}, {54, 56, 58}, {54, 55, 56}, {51, 53, 56}, {50, 53, 56}, {49, 53, 58}}, + {{21, 33, 45}, {22, 33, 43}, {29, 39, 49}, {51, 54, 56}, {54, 55, 56}, {52, 57, 62}, {51, 57, 63}, {46, 55, 65}}, + {{65, 77, 89}, {67, 77, 88}, {61, 71, 81}, {54, 56, 59}, {54, 55, 56}, {48, 53, 58}, {47, 53, 59}, {45, 55, 64}} + }; + + zones::quality_lut_t zone0_prompt_ql = { + 0, 3, 3, 4, 3, 5, 4, 6, 1, 6, 6, 7, 21, 26, 24, 27, 1, 21, 21, 24, 22, 26, 24, 29, + 2, 25, 25, 27, 26, 30, 28, 31, 0, 17, 17, 20, 18, 34, 20, 37, 2, 42, 28, 45, 42, 46, 45, 49, + 9, 42, 42, 45, 43, 47, 46, 49, 10, 45, 45, 48, 47, 50, 49, 51, 0, 5, 5, 6, 17, 33, 19, 36, + 2, 7, 7, 7, 29, 46, 30, 49, 3, 42, 29, 46, 43, 47, 46, 50, 4, 45, 31, 49, 47, 50, 50, 51, + 1, 20, 19, 23, 22, 38, 23, 39, 4, 45, 30, 48, 46, 49, 48, 51, 11, 46, 46, 49, 47, 50, 50, 51, + 13, 48, 49, 51, 50, 51, 51, 51, 0, 16, 16, 18, 16, 32, 18, 35, 2, 41, 27, 43, 42, 44, 44, 47, + 9, 42, 41, 44, 42, 45, 44, 48, 10, 44, 44, 47, 44, 48, 48, 50, 8, 40, 40, 41, 40, 41, 40, 43, + 11, 52, 52, 55, 53, 57, 54, 61, 12, 52, 52, 55, 53, 58, 56, 61, 14, 55, 55, 60, 58, 62, 59, 63, + 1, 40, 23, 40, 40, 41, 40, 43, 5, 52, 31, 54, 53, 57, 54, 60, 12, 52, 53, 56, 53, 58, 57, 62, + 14, 55, 56, 60, 57, 61, 60, 63, 8, 41, 41, 43, 41, 43, 43, 47, 13, 54, 54, 59, 57, 61, 58, 63, + 15, 56, 56, 59, 58, 61, 60, 63, 15, 59, 59, 62, 62, 63, 62, 63 + }; + + std::vector zone0_disp_pd = { + {{50, 55, 60}, {50, 55, 60}, {50, 55, 60}, {53, 55, 57}, {53, 55, 57}, {54, 55, 56}, {53, 55, 57}, {53, 55, 57}}, + {{53, 61, 67}, {53, 61, 65}, {53, 60, 65}, {54, 56, 57}, {54, 56, 57}, {52, 54, 56}, {52, 54, 56}, {49, 53, 56}}, + {{43, 49, 57}, {45, 49, 57}, {45, 50, 57}, {53, 54, 56}, {53, 54, 56}, {54, 56, 58}, {54, 56, 58}, {54, 57, 61}}, + {{54, 63, 72}, {54, 63, 70}, {54, 63, 71}, {54, 57, 58}, {54, 56, 56}, {49, 53, 56}, {49, 52, 56}, {45, 51, 56}}, + {{38, 47, 56}, {40, 47, 56}, {39, 47, 56}, {52, 53, 56}, {54, 54, 56}, {54, 57, 61}, {54, 58, 61}, {54, 59, 65}}, + {{54, 64, 77}, {54, 66, 74}, {54, 66, 76}, {54, 57, 59}, {54, 56, 56}, {46, 52, 56}, {45, 50, 56}, {40, 48, 56}}, + {{33, 46, 56}, {36, 44, 56}, {34, 44, 56}, {51, 53, 56}, {54, 54, 56}, {54, 58, 64}, {54, 60, 65}, {54, 62, 70}} + }; + + zones::quality_lut_t zone0_disp_ql = { + 0, 3, 3, 4, 3, 5, 4, 5, 1, 6, 6, 7, 21, 26, 26, 30, 1, 22, 21, 25, 22, 26, 24, 29, + 2, 24, 24, 27, 25, 29, 29, 31, 0, 17, 17, 20, 18, 34, 20, 38, 2, 42, 28, 47, 42, 47, 46, 50, + 9, 42, 42, 46, 43, 47, 46, 49, 10, 45, 45, 49, 46, 49, 49, 51, 0, 6, 5, 6, 17, 33, 19, 36, + 2, 7, 7, 7, 28, 46, 31, 50, 3, 42, 27, 46, 43, 47, 46, 50, 4, 45, 30, 50, 46, 50, 50, 51, + 1, 20, 19, 23, 21, 37, 23, 39, 4, 45, 30, 48, 45, 49, 48, 51, 11, 45, 45, 49, 47, 50, 49, 51, + 13, 48, 48, 51, 49, 51, 51, 51, 0, 16, 16, 18, 16, 32, 18, 35, 2, 41, 27, 44, 41, 44, 44, 48, + 9, 42, 41, 44, 42, 45, 44, 48, 10, 44, 43, 47, 44, 48, 47, 50, 8, 40, 40, 41, 40, 41, 41, 43, + 11, 52, 52, 56, 53, 57, 57, 61, 12, 53, 52, 57, 53, 58, 58, 62, 14, 56, 55, 60, 57, 62, 61, 63, + 1, 40, 23, 40, 40, 41, 40, 43, 5, 52, 31, 55, 52, 55, 56, 60, 12, 53, 52, 56, 53, 58, 57, 61, + 13, 55, 54, 60, 55, 61, 60, 63, 8, 41, 40, 43, 42, 43, 43, 47, 14, 54, 54, 59, 54, 59, 60, 62, + 15, 56, 54, 59, 58, 62, 61, 63, 15, 59, 58, 62, 59, 63, 63, 63 + }; + // clang-format on + + zones_.push_back({zone0_hm, zone0_prompt_pd, zone0_prompt_ql, zone0_disp_pd, zone0_disp_ql}); + + // =========================================================================== + // Zone 1 + // =========================================================================== + + // clang-format off + zones::hitmap_t&& zone1_hm = { + { // Row 0 + { + site_id_t::kGE11, { + {99 , 38, 90 }, + {54 , 75, 127}, + {55 , 113, 165}, + {56 , 150, 202}, + {63 , 188, 240}, + {64 , 225, 277}, + {65 , 263, 315} + } + } + }, + { // Row 1 + { + site_id_t::kME11, { + {45 , 38, 90 }, + {0 , 75, 127}, + {1 , 113, 165}, + {2 , 150, 202}, + {9 , 188, 240}, + {10 , 225, 277}, + {11 , 263, 315} + } + } + }, + { // Row 2 + { + site_id_t::kME12, { + {46 , 38, 90 }, + {3 , 75, 127}, + {4 , 113, 165}, + {5 , 150, 202}, + {12 , 188, 240}, + {13 , 225, 277}, + {14 , 263, 315} + } + }, + { + site_id_t::kRE1, { + {100, 38, 90 }, + {57 , 75, 127}, + {58 , 113, 165}, + {59 , 150, 202}, + {66 , 188, 240}, + {67 , 225, 277}, + {68 , 263, 315} + } + } + }, + { // Row 3 + { + site_id_t::kGE21, { + {102, 0 , 90 }, + {72 , 75 , 165}, + {73 , 150 , 240}, + {74 , 225 , 315} + } + } + }, + { // Row 4 + { + site_id_t::kME2, { + {48 , 0 , 90 }, + {18 , 75 , 165}, + {19 , 150 , 240}, + {20 , 225 , 315} + } + } + }, + { // Row 5 + { + site_id_t::kME3, { + // ME3/1 + {50 , 0 , 90 }, + {27 , 75 , 165}, + {28 , 150 , 240}, + {29 , 225 , 315}, + // ME3/2 + {51 , 38, 90 }, + {30 , 75, 127}, + {31 , 113, 165}, + {32 , 150, 202}, + {33 , 188, 240}, + {34 , 225, 277}, + {35 , 263, 315} + } + } + }, + { // Row 6 + { + site_id_t::kRE3, { + // RE3/1 + {104, 0 , 90 }, + {81 , 75 , 165}, + {82 , 150 , 240}, + {83 , 225 , 315}, + // RE3/2 + {105, 38, 90 }, + {84 , 75, 127}, + {85 , 113, 165}, + {86 , 150, 202}, + {87 , 188, 240}, + {88 , 225, 277}, + {89 , 263, 315} + } + } + }, + { // Row 7 + { + site_id_t::kME4, { + // ME4/1 + {52 , 0 , 90 }, + {36 , 75 , 165}, + {37 , 150 , 240}, + {38 , 225 , 315}, + // ME4/2 + {53 , 38, 90 }, + {39 , 75, 127}, + {40 , 113, 165}, + {41 , 150, 202}, + {42 , 188, 240}, + {43 , 225, 277}, + {44 , 263, 315} + } + }, + { + site_id_t::kRE4, { + // RE4/1 + {106, 0 , 90 }, + {90 , 75 , 165}, + {91 , 150 , 240}, + {92 , 225 , 315}, + // RE4/2 + {107, 38, 90 }, + {93 , 75, 127}, + {94 , 113, 165}, + {95 , 150, 202}, + {96 , 188, 240}, + {97 , 225, 277}, + {98 , 263, 315} + } + } + } + }; + + std::vector zone1_prompt_pd = { + {{47, 55, 63}, {48, 55, 62}, {51, 55, 59}, {53, 55, 57}, {53, 55, 57}, {54, 55, 56}, {53, 55, 57}, {53, 55, 57}}, + {{38, 44, 50}, {41, 46, 51}, {49, 52, 54}, {53, 54, 56}, {53, 55, 57}, {54, 56, 57}, {54, 56, 58}, {53, 56, 58}}, + {{60, 66, 72}, {59, 64, 69}, {56, 58, 61}, {54, 56, 57}, {53, 55, 57}, {53, 54, 56}, {52, 54, 56}, {52, 54, 57}}, + {{29, 37, 44}, {32, 40, 47}, {46, 50, 53}, {52, 54, 56}, {54, 55, 56}, {53, 56, 59}, {51, 55, 59}, {48, 54, 59}}, + {{66, 73, 81}, {63, 70, 78}, {57, 60, 64}, {54, 56, 58}, {54, 55, 56}, {51, 54, 57}, {51, 55, 59}, {51, 56, 62}}, + {{16, 27, 39}, {21, 32, 42}, {43, 48, 53}, {52, 55, 57}, {54, 55, 56}, {44, 52, 59}, {40, 49, 59}, {31, 44, 59}}, + {{71, 83, 94}, {68, 78, 89}, {57, 62, 67}, {53, 55, 58}, {54, 55, 56}, {51, 58, 66}, {51, 61, 70}, {51, 66, 79}} + }; + + zones::quality_lut_t zone1_prompt_ql = { + 0, 3, 4, 6, 3, 5, 5, 7, 1, 7, 21, 25, 19, 23, 25, 27, 1, 20, 22, 25, 34, 36, 37, 39, + 2, 24, 26, 28, 36, 38, 39, 39, 0, 16, 18, 21, 32, 33, 34, 37, 4, 27, 42, 46, 42, 45, 45, 49, + 9, 42, 43, 46, 43, 46, 47, 50, 10, 45, 46, 50, 45, 48, 49, 51, 0, 7, 17, 20, 17, 18, 20, 23, + 3, 7, 28, 31, 27, 29, 30, 31, 4, 29, 43, 47, 42, 45, 47, 50, 6, 30, 46, 50, 46, 48, 49, 51, + 1, 19, 22, 24, 34, 35, 37, 38, 5, 29, 46, 49, 45, 48, 49, 51, 11, 46, 47, 50, 47, 49, 50, 51, + 13, 49, 50, 51, 48, 51, 51, 51, 0, 16, 16, 18, 32, 32, 33, 35, 2, 26, 42, 44, 41, 43, 44, 48, + 9, 41, 42, 45, 42, 44, 45, 48, 10, 44, 44, 48, 44, 47, 48, 50, 8, 40, 40, 41, 40, 40, 41, 43, + 11, 52, 53, 56, 52, 54, 56, 60, 12, 52, 53, 57, 53, 56, 58, 62, 14, 55, 57, 61, 57, 59, 61, 63, + 2, 22, 40, 41, 40, 40, 41, 43, 6, 31, 52, 55, 52, 54, 55, 59, 12, 52, 53, 57, 53, 54, 58, 61, + 14, 54, 57, 61, 55, 59, 60, 63, 8, 40, 41, 43, 41, 43, 44, 47, 13, 54, 56, 60, 56, 58, 60, 62, + 15, 55, 58, 62, 58, 59, 62, 63, 15, 59, 61, 63, 60, 62, 63, 63 + }; + + std::vector zone1_disp_pd = { + {{50, 55, 60}, {50, 55, 60}, {52, 55, 58}, {53, 55, 57}, {53, 55, 57}, {54, 55, 56}, {53, 55, 57}, {53, 55, 57}}, + {{53, 60, 65}, {53, 60, 65}, {54, 58, 61}, {54, 56, 57}, {54, 56, 57}, {53, 54, 56}, {52, 54, 56}, {50, 53, 56}}, + {{45, 50, 57}, {45, 50, 57}, {49, 52, 56}, {53, 54, 56}, {53, 54, 56}, {54, 56, 57}, {54, 56, 58}, {54, 57, 60}}, + {{53, 63, 71}, {53, 62, 69}, {54, 59, 63}, {54, 57, 58}, {54, 56, 56}, {50, 54, 56}, {50, 53, 56}, {47, 51, 56}}, + {{39, 47, 57}, {41, 48, 57}, {47, 51, 56}, {52, 53, 56}, {54, 54, 56}, {54, 56, 60}, {54, 57, 60}, {54, 59, 63}}, + {{54, 65, 73}, {54, 65, 74}, {54, 61, 67}, {54, 57, 59}, {54, 56, 56}, {47, 53, 56}, {47, 51, 56}, {43, 49, 56}}, + {{37, 45, 56}, {36, 45, 56}, {43, 49, 56}, {51, 53, 56}, {54, 54, 56}, {54, 57, 63}, {54, 59, 63}, {54, 61, 67}} + }; + + zones::quality_lut_t zone1_disp_ql = { + 0, 3, 4, 6, 4, 5, 6, 7, 1, 7, 22, 26, 20, 24, 25, 29, 1, 21, 22, 25, 34, 37, 37, 39, + 2, 23, 25, 28, 36, 38, 39, 39, 0, 17, 18, 20, 32, 33, 34, 37, 3, 27, 42, 46, 42, 45, 46, 50, + 9, 42, 43, 46, 43, 46, 47, 50, 10, 45, 46, 50, 45, 48, 49, 51, 0, 7, 17, 18, 16, 19, 20, 24, + 3, 7, 27, 31, 27, 30, 29, 31, 4, 28, 43, 47, 42, 47, 47, 50, 5, 30, 46, 50, 45, 49, 49, 51, + 1, 19, 21, 23, 34, 35, 36, 38, 5, 29, 45, 49, 45, 49, 48, 51, 11, 46, 47, 50, 46, 48, 50, 51, + 13, 49, 49, 51, 48, 51, 51, 51, 0, 16, 16, 18, 32, 32, 33, 35, 2, 26, 41, 44, 41, 44, 44, 48, + 9, 42, 42, 45, 42, 44, 45, 48, 10, 44, 44, 48, 44, 48, 47, 50, 8, 40, 40, 41, 40, 41, 41, 43, + 11, 52, 52, 57, 52, 55, 56, 61, 12, 53, 53, 57, 53, 57, 58, 62, 14, 55, 56, 61, 55, 61, 60, 63, + 2, 22, 40, 40, 40, 40, 41, 43, 6, 31, 52, 57, 52, 54, 55, 60, 12, 52, 53, 58, 53, 56, 58, 62, + 14, 56, 56, 61, 54, 59, 60, 63, 8, 40, 41, 43, 41, 43, 43, 47, 13, 54, 54, 60, 54, 58, 59, 63, + 15, 55, 57, 61, 58, 60, 62, 63, 15, 59, 59, 63, 59, 62, 62, 63 + }; + // clang-format on + + zones_.push_back({zone1_hm, zone1_prompt_pd, zone1_prompt_ql, zone1_disp_pd, zone1_disp_ql}); + + // =========================================================================== + // Zone 2 + // =========================================================================== + + // clang-format off + zones::hitmap_t&& zone2_hm = { + { // Row 0 + { + site_id_t::kME12, { + {46 , 38, 90 }, + {3 , 75, 127}, + {4 , 113, 165}, + {5 , 150, 202}, + {12 , 188, 240}, + {13 , 225, 277}, + {14 , 263, 315} + } + } + }, + { // Row 1 + { + site_id_t::kRE1, { + {100, 38, 90 }, + {57 , 75, 127}, + {58 , 113, 165}, + {59 , 150, 202}, + {66 , 188, 240}, + {67 , 225, 277}, + {68 , 263, 315} + } + } + }, + { // Row 2 + { + site_id_t::kRE2, { + {103, 38, 90 }, + {75 , 75, 127}, + {76 , 113, 165}, + {77 , 150, 202}, + {78 , 188, 240}, + {79 , 225, 277}, + {80 , 263, 315} + } + } + }, + { // Row 3 + { + site_id_t::kME2, { + {49 , 38, 90 }, + {21 , 75, 127}, + {22 , 113, 165}, + {23 , 150, 202}, + {24 , 188, 240}, + {25 , 225, 277}, + {26 , 263, 315} + } + } + }, + { // Row 4 + { + site_id_t::kME3, { + {51 , 38, 90 }, + {30 , 75, 127}, + {31 , 113, 165}, + {32 , 150, 202}, + {33 , 188, 240}, + {34 , 225, 277}, + {35 , 263, 315} + } + } + }, + { // Row 5 + { + site_id_t::kRE3, { + {105, 38, 90 }, + {84 , 75, 127}, + {85 , 113, 165}, + {86 , 150, 202}, + {87 , 188, 240}, + {88 , 225, 277}, + {89 , 263, 315} + } + } + }, + { // Row 6 + { + site_id_t::kME4, { + {53 , 38, 90 }, + {39 , 75, 127}, + {40 , 113, 165}, + {41 , 150, 202}, + {42 , 188, 240}, + {43 , 225, 277}, + {44 , 263, 315} + } + } + }, + { // Row 7 + { + site_id_t::kRE4, { + {107, 38, 90 }, + {93 , 75, 127}, + {94 , 113, 165}, + {95 , 150, 202}, + {96 , 188, 240}, + {97 , 225, 277}, + {98 , 263, 315}, + } + } + } + }; + + std::vector zone2_prompt_pd = { // Pattern N: Row0..RowM + {{52, 55, 58}, {52, 55, 58}, {53, 55, 57}, {53, 55, 57}, {54, 55, 56}, {53, 55, 57}, {53, 55, 57}, {53, 55, 57}}, + {{54, 57, 61}, {53, 57, 60}, {54, 56, 58}, {54, 56, 58}, {53, 55, 56}, {53, 54, 56}, {52, 54, 56}, {52, 54, 56}}, + {{49, 53, 56}, {50, 53, 57}, {52, 54, 56}, {52, 54, 56}, {54, 55, 57}, {54, 56, 57}, {54, 56, 58}, {54, 56, 58}}, + {{54, 57, 61}, {54, 57, 61}, {54, 56, 59}, {54, 56, 59}, {53, 54, 56}, {52, 54, 56}, {51, 54, 56}, {51, 53, 56}}, + {{49, 53, 56}, {49, 53, 56}, {51, 54, 56}, {51, 54, 56}, {54, 56, 57}, {54, 56, 58}, {54, 56, 59}, {54, 57, 59}}, + {{54, 59, 65}, {54, 60, 64}, {54, 57, 59}, {54, 56, 56}, {50, 54, 56}, {49, 53, 56}, {47, 52, 56}, {46, 51, 56}}, + {{45, 51, 56}, {46, 50, 56}, {51, 53, 56}, {54, 54, 56}, {54, 56, 60}, {54, 57, 61}, {54, 58, 63}, {54, 59, 64}} + }; + + zones::quality_lut_t zone2_prompt_ql = { + 0, 3, 3, 5, 1, 23, 7, 26, 1, 36, 22, 38, 2, 39, 25, 39, 0, 32, 18, 35, 4, 44, 44, 48, + 9, 44, 44, 49, 10, 49, 48, 51, 0, 17, 6, 21, 3, 28, 7, 30, 4, 44, 43, 48, 5, 48, 48, 51, + 1, 34, 21, 37, 4, 47, 47, 50, 10, 49, 48, 51, 11, 51, 50, 51, 0, 32, 16, 33, 3, 43, 43, 47, + 8, 43, 43, 47, 9, 47, 46, 50, 8, 40, 40, 42, 11, 53, 53, 57, 11, 54, 53, 58, 13, 58, 56, 62, + 2, 40, 40, 41, 5, 52, 52, 54, 11, 53, 52, 57, 12, 58, 54, 61, 8, 42, 42, 45, 12, 56, 55, 59, + 14, 57, 56, 61, 15, 62, 59, 63, 0, 16, 5, 19, 2, 27, 7, 29, 3, 43, 42, 46, 4, 46, 45, 50, + 1, 40, 40, 41, 6, 52, 52, 54, 10, 53, 52, 58, 12, 55, 54, 60, 1, 24, 7, 26, 5, 31, 7, 31, + 6, 53, 52, 57, 6, 58, 54, 60, 2, 41, 41, 45, 7, 55, 55, 59, 13, 56, 56, 61, 14, 60, 59, 63, + 0, 34, 20, 37, 4, 46, 46, 49, 9, 47, 46, 50, 10, 50, 49, 51, 8, 42, 42, 45, 12, 57, 56, 61, + 13, 57, 55, 62, 15, 62, 59, 63, 2, 41, 41, 44, 6, 55, 54, 59, 13, 58, 56, 61, 14, 61, 59, 63, + 9, 45, 45, 49, 14, 60, 60, 62, 15, 61, 60, 63, 15, 63, 62, 63 + }; + + std::vector zone2_disp_pd = { // Pattern N: Row0..RowM + {{52, 55, 58}, {52, 55, 58}, {53, 55, 57}, {53, 55, 57}, {54, 55, 56}, {53, 55, 57}, {53, 55, 57}, {53, 55, 57}}, + {{54, 57, 61}, {54, 57, 61}, {54, 56, 59}, {54, 56, 59}, {53, 55, 56}, {53, 54, 56}, {52, 54, 56}, {51, 54, 56}}, + {{49, 53, 56}, {49, 53, 56}, {51, 54, 56}, {51, 54, 56}, {54, 55, 57}, {54, 56, 57}, {54, 56, 58}, {54, 56, 59}}, + {{54, 58, 62}, {54, 58, 62}, {54, 56, 58}, {54, 56, 57}, {51, 54, 56}, {51, 53, 56}, {49, 53, 56}, {48, 52, 56}}, + {{48, 52, 56}, {48, 52, 56}, {52, 54, 56}, {53, 54, 56}, {54, 56, 59}, {54, 57, 59}, {54, 57, 61}, {54, 58, 62}}, + {{54, 60, 66}, {54, 60, 65}, {54, 57, 59}, {54, 56, 56}, {49, 53, 56}, {48, 52, 56}, {46, 52, 56}, {45, 51, 56}}, + {{44, 50, 56}, {45, 50, 56}, {51, 53, 56}, {54, 54, 56}, {54, 57, 61}, {54, 58, 62}, {54, 58, 64}, {54, 59, 65}} + }; + + zones::quality_lut_t zone2_disp_ql = { + 0, 3, 3, 5, 1, 23, 7, 26, 1, 36, 22, 38, 2, 39, 25, 39, 0, 32, 18, 35, 4, 44, 44, 48, + 9, 44, 44, 49, 10, 49, 48, 51, 0, 17, 6, 21, 3, 28, 7, 30, 4, 44, 43, 48, 5, 48, 48, 51, + 1, 34, 21, 37, 4, 47, 48, 50, 10, 49, 47, 51, 11, 51, 50, 51, 0, 32, 16, 33, 3, 43, 43, 47, + 8, 43, 43, 47, 9, 47, 46, 50, 8, 40, 40, 42, 11, 53, 52, 57, 11, 53, 52, 58, 13, 58, 56, 61, + 2, 40, 40, 41, 5, 52, 52, 55, 11, 53, 53, 57, 12, 56, 55, 61, 8, 42, 41, 45, 12, 56, 54, 59, + 14, 58, 56, 62, 15, 61, 59, 63, 0, 16, 6, 20, 2, 27, 7, 29, 3, 43, 42, 46, 4, 46, 46, 50, + 1, 40, 40, 41, 5, 53, 52, 54, 10, 53, 52, 58, 12, 55, 54, 60, 1, 24, 7, 26, 5, 31, 7, 31, + 6, 53, 52, 57, 6, 57, 54, 61, 2, 42, 41, 45, 7, 54, 55, 59, 13, 58, 55, 60, 14, 60, 59, 63, + 0, 34, 19, 37, 4, 46, 45, 49, 9, 47, 46, 50, 10, 50, 49, 51, 8, 42, 42, 45, 12, 57, 56, 61, + 13, 57, 56, 62, 15, 62, 60, 63, 2, 41, 41, 44, 6, 56, 54, 59, 13, 58, 55, 61, 14, 61, 59, 63, + 9, 45, 45, 49, 14, 60, 59, 62, 15, 62, 60, 63, 15, 63, 62, 63 + }; + // clang-format on + + zones_.push_back({zone2_hm, zone2_prompt_pd, zone2_prompt_ql, zone2_disp_pd, zone2_disp_ql}); + + // =========================================================================== + // Features + // =========================================================================== + // feat | ME1/1 | ME1/2 | ME2 | ME3 | ME4 | RE1 | RE2 | RE3 | RE4 | GE1/1 | GE2/1 | ME0 + // -----------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|------- + // emtf_phi | * | * | * | * | * | * | * | * | * | * | * | * + // emtf_theta | * | * | * | * | * | * | * | * | * | * | * | * + // emtf_bend | * | * | * | * | * | | | | | | | * + // emtf_qual | * | * | * | * | * | | | | | | | * + // emtf_time | | | | | | | | | | | | + + // clang-format off + features_ = { + { + feature_id_t::kPhi, { + site_id_t::kME11, site_id_t::kME12, site_id_t::kME2, site_id_t::kME3, site_id_t::kME4, + site_id_t::kRE1 , site_id_t::kRE2 , site_id_t::kRE3, site_id_t::kRE4, + site_id_t::kGE11, site_id_t::kGE21, site_id_t::kME0 + } + }, + { + feature_id_t::kTheta, { + site_id_t::kME11, site_id_t::kME12, site_id_t::kME2, site_id_t::kME3, site_id_t::kME4, + site_id_t::kRE1 , site_id_t::kRE2 , site_id_t::kRE3, site_id_t::kRE4, + site_id_t::kGE11, site_id_t::kGE21, site_id_t::kME0 + } + }, + { + feature_id_t::kBend, { + site_id_t::kME11, site_id_t::kME12, site_id_t::kME2, site_id_t::kME3, site_id_t::kME4, + site_id_t::kME0 + } + }, + { + feature_id_t::kQuality, { + site_id_t::kME11, site_id_t::kME12, site_id_t::kME2, site_id_t::kME3, site_id_t::kME4, + site_id_t::kME0 + } + }, + }; + // clang-format on + + // =========================================================================== + // Theta Options + // =========================================================================== + + // clang-format off + theta_medians_ = { + // ME2_t1, ME3_t1, ME4_t1, ME2_t2, ME3_t2, ME4_t2, GE21, RE3, RE4 + { + { + {site_id_t::kME2, theta_id_t::kTheta1}, + {site_id_t::kME3, theta_id_t::kTheta1}, + {site_id_t::kME4, theta_id_t::kTheta1} + }, + { + {site_id_t::kME2, theta_id_t::kTheta2}, + {site_id_t::kME3, theta_id_t::kTheta2}, + {site_id_t::kME4, theta_id_t::kTheta2} + }, + { + {site_id_t::kGE21, theta_id_t::kTheta1}, + {site_id_t::kRE3, theta_id_t::kTheta1}, + {site_id_t::kRE4, theta_id_t::kTheta1} + }, + }, + // ME2_t1, ME3_t1, ME4_t1, ME2_t2, ME3_t2, ME4_t2, RE2, RE3, RE4 + { + { + {site_id_t::kME2, theta_id_t::kTheta1}, + {site_id_t::kME3, theta_id_t::kTheta1}, + {site_id_t::kME4, theta_id_t::kTheta1} + }, + { + {site_id_t::kME2, theta_id_t::kTheta2}, + {site_id_t::kME3, theta_id_t::kTheta2}, + {site_id_t::kME4, theta_id_t::kTheta2} + }, + { + {site_id_t::kRE2, theta_id_t::kTheta1}, + {site_id_t::kRE3, theta_id_t::kTheta1}, + {site_id_t::kRE4, theta_id_t::kTheta1} + }, + }, + // ME12_t1, ME11_t1, ME0_t2, ME12_t2, ME11_t2, ME0_t2, RE1, GE11, ME0_t1 + { + { + {site_id_t::kME12, theta_id_t::kTheta1}, + {site_id_t::kME11, theta_id_t::kTheta1}, + {site_id_t::kME0 , theta_id_t::kTheta2} + }, + { + {site_id_t::kME12, theta_id_t::kTheta2}, + {site_id_t::kME11, theta_id_t::kTheta2}, + {site_id_t::kME0 , theta_id_t::kTheta2} + }, + { + {site_id_t::kRE1, theta_id_t::kTheta1}, + {site_id_t::kGE11, theta_id_t::kTheta1}, + {site_id_t::kME0, theta_id_t::kTheta1} + }, + }, + }; + // clang-format on + + // =========================================================================== + // Site Reduction + // =========================================================================== + // Site (out) | Site (in) + // -----------|------------------------------------------- + // ME1 | ME1/1, GE1/1, ME1/2, RE1/2 + // ME2 | ME2, GE2/1, RE2/2 + // ME3 | ME3, RE3 + // ME4 | ME4, RE4 + // ME0 | ME0 + + // clang-format off + reduced_sites_ = { + {reduced_site_id_t::kME1, {site_id_t::kME11, site_id_t::kGE11, site_id_t::kME12, site_id_t::kRE1}}, + {reduced_site_id_t::kME2, {site_id_t::kME2, site_id_t::kGE21, site_id_t::kRE2}}, + {reduced_site_id_t::kME3, {site_id_t::kME3, site_id_t::kRE3}}, + {reduced_site_id_t::kME4, {site_id_t::kME4, site_id_t::kRE4}}, + {reduced_site_id_t::kME0, {site_id_t::kME0}}, + }; + // clang-format on +} + +EMTFModel::~EMTFModel() { + // Do Nothing +} diff --git a/L1Trigger/L1TMuonEndCapPhase2/src/SectorProcessor.cc b/L1Trigger/L1TMuonEndCapPhase2/src/SectorProcessor.cc new file mode 100644 index 0000000000000..c64d2edecaec4 --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/src/SectorProcessor.cc @@ -0,0 +1,421 @@ +#include + +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/MessageLogger/interface/MessageLogger.h" + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFConstants.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFContext.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFTypes.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Algo/HitmapLayer.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/CSCTPConverter.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/CSCTPSelector.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/RPCTPConverter.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/RPCTPSelector.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/GEMTPConverter.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/GEMTPSelector.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/ME0TPConverter.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/ME0TPSelector.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/GE0TPConverter.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/GE0TPSelector.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/TPConverters.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/TPSelectors.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/TPrimitives.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Utils/DebugUtils.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Utils/CSCUtils.h" + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/SectorProcessor.h" + +using namespace emtf::phase2; + +SectorProcessor::SectorProcessor(const EMTFContext& context, const int& endcap, const int& sector) + : context_(context), endcap_(endcap), sector_(sector), event_(nullptr), bx_(nullptr) { + // =========================================================================== + // Register Selectors/Converters + // =========================================================================== + if (this->context_.config_.csc_en_) { + tp_selectors_[L1TMuon::kCSC] = std::make_unique(context_, endcap_, sector_); + tp_converters_[L1TMuon::kCSC] = std::make_unique(context_, endcap_, sector_); + } + + if (this->context_.config_.rpc_en_) { + tp_selectors_[L1TMuon::kRPC] = std::make_unique(context_, endcap_, sector_); + tp_converters_[L1TMuon::kRPC] = std::make_unique(context_, endcap_, sector_); + } + + if (this->context_.config_.gem_en_) { + tp_selectors_[L1TMuon::kGEM] = std::make_unique(context_, endcap_, sector_); + tp_converters_[L1TMuon::kGEM] = std::make_unique(context_, endcap_, sector_); + } + + if (this->context_.config_.me0_en_) { + tp_selectors_[L1TMuon::kME0] = std::make_unique(context_, endcap_, sector_); + tp_converters_[L1TMuon::kME0] = std::make_unique(context_, endcap_, sector_); + } + + if (this->context_.config_.ge0_en_) { + tp_selectors_[L1TMuon::kME0] = std::make_unique(context_, endcap_, sector_); + tp_converters_[L1TMuon::kME0] = std::make_unique(context_, endcap_, sector_); + } +} + +SectorProcessor::~SectorProcessor() { + // Do Nothing +} + +void SectorProcessor::configureEvent(const edm::Event& event) { + // Event + event_ = &event; + bx_ = nullptr; + + // Reset Window Hits + bx_window_hits_.clear(); + bx_ilink_tpc_maps_.clear(); +} + +void SectorProcessor::configureBx(const int& bx) { + // BX + bx_ = &bx; + + // Reset BX Maps + bx_ilink_tpc_maps_.clear(); + + // Remove BX TPCollections that aren't in the bx window + // Note that the first entry in bx_window_hits is the earliest BX + const auto min_bx = this->context_.config_.min_bx_; + const auto delay_bx = this->context_.config_.bx_window_ - 1; + const auto pop_after_bx = min_bx + delay_bx; + + if (pop_after_bx < bx) { + bx_window_hits_.erase(bx_window_hits_.begin()); + } +} + +void SectorProcessor::select(const TriggerPrimitive& tp, const TPInfo& tp_info) { + // Get TPSelector + auto tp_subsystem = tp.subsystem(); + + auto tp_selectors_it = tp_selectors_.find(tp_subsystem); + + // Short-Circuit: Operation not supported + if (tp_selectors_it == tp_selectors_.end()) { + edm::LogWarning("L1TEMTFpp") << "TPCollector has been implemented, " + << "but there is no TPSelector for " << tp_subsystem; + return; + } + + // Select TP that belongs to this Sector Processor + auto& bx_ilink_tpc_map = bx_ilink_tpc_maps_[tp_subsystem]; // reference to subsystem trigger primitive collection + + tp_selectors_it->second->select(tp, tp_info, bx_ilink_tpc_map); +} + +void SectorProcessor::process(EMTFHitCollection& out_hits, + EMTFTrackCollection& out_tracks, + EMTFInputCollection& out_inputs) { + // =========================================================================== + // Merge subsystem selections + // =========================================================================== + ILinkTPCMap bx_ilink_tpc_map; + + for (auto& [subsystem, ilink_tpc_map] : bx_ilink_tpc_maps_) { + copyTP(ilink_tpc_map, bx_ilink_tpc_map); + } + + // Free memory + bx_ilink_tpc_maps_.clear(); + + // =========================================================================== + // Convert trigger primitives to EMTF Hits + // =========================================================================== + + // Convert tp into hits + EMTFHitCollection bx_hits; + + convertTP(out_hits.size(), bx_ilink_tpc_map, bx_hits); + + // Append to bx window hits + bx_window_hits_.push_back(bx_hits); + + // Free memory + bx_ilink_tpc_map.clear(); + + // Record hits + out_hits.insert(out_hits.end(), bx_hits.begin(), bx_hits.end()); + + // =========================================================================== + // Current Algorithm only supports BX=0 + // =========================================================================== + + if ((*bx_) != 0) { + return; + } + + // =========================================================================== + // Convert EMTF Hits to Segments + // =========================================================================== + + // Init Segment to Hit Map + std::map seg_to_hit; + + // Convert bx window hits into segments + segment_collection_t segments; + + populateSegments(bx_window_hits_, seg_to_hit, segments); + + // Build Tracks + buildTracks(seg_to_hit, segments, false, out_tracks); // With prompt setup + buildTracks(seg_to_hit, segments, true, out_tracks); // With displaced setup + + // =========================================================================== + // Record segments/hits used in track building + // =========================================================================== + if (!seg_to_hit.empty()) { + EMTFInput::hits_t hit_id_col; + EMTFInput::segs_t seg_id_col; + + for (const auto& [seg_id, hit_id] : seg_to_hit) { + seg_id_col.push_back(seg_id); + hit_id_col.push_back(hit_id); + } + + EMTFInput emtf_input; + + const int endcap_pm = (endcap_ == 2) ? -1 : endcap_; // 1: +endcap, -1: -endcap + + emtf_input.setEndcap(endcap_pm); + emtf_input.setSector(sector_); + emtf_input.setBx(*bx_); + emtf_input.setHits(hit_id_col); + emtf_input.setSegs(seg_id_col); + + out_inputs.push_back(emtf_input); + } +} + +void SectorProcessor::copyTP(const ILinkTPCMap& source, ILinkTPCMap& target) const { + typedef typename ILinkTPCMap::iterator Iterator_t; + typedef typename ILinkTPCMap::mapped_type Collection_t; + + for (auto& source_kv : source) { + std::pair ins_res = target.insert(source_kv); + + // Short-Circuit: Insertion succeeded, move on + if (ins_res.second) { + continue; + } + + // Merge into target collection + const Collection_t& source_col = source_kv.second; + Collection_t& target_col = ins_res.first->second; + + target_col.insert(target_col.end(), source_col.begin(), source_col.end()); + } +} + +void SectorProcessor::convertTP(const int& initial_hit_id, const ILinkTPCMap& ilink_tpc_map, EMTFHitCollection& hits) { + EMTFHitCollection substitutes; + + for (const auto& [ilink, ilink_tpc] : ilink_tpc_map) { // loop input link trigger primitive collections + + unsigned int cnt_segments = 0; // Enumerates each segment in the same chamber + + for (const auto& tp_entry : ilink_tpc) { // loop trigger primitives + + // Unpack Entry + const auto& tp = tp_entry.tp_; // const reference + auto tp_info = tp_entry.info_; // copy info + + // Unpack trigger primitive + auto tp_subsystem = tp.subsystem(); + + // Get Converter + auto tp_converters_it = tp_converters_.find(tp_subsystem); + + // Short-Circuit: Operation not supported + if (tp_converters_it == tp_converters_.end()) { + edm::LogWarning("L1TEMTFpp") << "TPCollector & TPSelector have been implemented, " + << "but there is no TPConverter for " << tp_subsystem; + continue; + } + + // Set Segment Id + tp_info.segment_id = cnt_segments++; // Save and increase segment count + + // Convert + EMTFHit hit; + + tp_converters_it->second->convert(tp, tp_info, hit); + + // Append to hit collections + if (tp_info.flag_substitute) { + substitutes.push_back(hit); + } else { + hits.push_back(hit); + } + } + } + + // Substitutes are placed at the end of the hit collection + hits.insert(hits.end(), std::make_move_iterator(substitutes.begin()), std::make_move_iterator(substitutes.end())); + + // Assign Hit Ids + unsigned int cnt_hits = initial_hit_id; + + for (auto& hit : hits) { + hit.setId(cnt_hits++); + } +} + +void SectorProcessor::populateSegments(const std::vector& bx_window_hits, + std::map& seg_to_hit, + segment_collection_t& segments) { + // Initialize + for (unsigned int seg_id = 0; seg_id < v3::kNumSegments; ++seg_id) { + segments[seg_id].phi = 0; + segments[seg_id].bend = 0; + segments[seg_id].theta1 = 0; + segments[seg_id].theta2 = 0; + segments[seg_id].qual1 = 0; + segments[seg_id].qual2 = 0; + segments[seg_id].time = 0; + segments[seg_id].zones = 0; + segments[seg_id].tzones = 0; + segments[seg_id].cscfr = 0; + segments[seg_id].layer = 0; + segments[seg_id].bx = 0; + segments[seg_id].valid = 0; + } + + // Populate + auto bx_window_hits_rit = bx_window_hits.rbegin(); + auto bx_window_hits_rend = bx_window_hits.rend(); + + std::map next_ch_seg; + + for (; bx_window_hits_rit != bx_window_hits_rend; + ++bx_window_hits_rit) { // Begin loop from latest BX Collection to oldest BX Hit Collection + + const auto& bx_hits = *bx_window_hits_rit; + std::map bx_last_ch_seg; + + for (const auto& hit : bx_hits) { // Begin loop hits in BX + // Unpack Hit + const auto& hit_chamber = hit.emtfChamber(); + const auto& hit_segment = hit.emtfSegment(); + const auto& hit_valid = hit.flagValid(); + + emtf_assert(hit_valid); // segment must be valid + + // Get Channel Segment Count + unsigned int ch_seg = next_ch_seg[hit_chamber] + hit_segment; + + // Short-Circuit: Accept at most 2 segments + if (!(ch_seg < v3::kChamberSegments)) { + continue; + } + + // Calculate Host + const auto& hit_host = hit.emtfHost(); + + // Calculate Relative BX + // Note: Uses Hit BX relative to Sector Processor BX + const auto& hit_bx = hit.bx(); + const int hit_rel_bx = (hit_bx - *bx_); + + // Short-Circuit: Only use Relative BX=0 Segments + if (hit_rel_bx != 0) { + continue; + } + + // Calculate Timezone + const auto hit_timezones = context_.timezone_lut_.getTimezones(hit_host, hit_rel_bx); + + // Calculate algo seg + const unsigned int seg_id = hit_chamber * v3::kChamberSegments + ch_seg; + + emtf_assert(seg_id < v3::kNumSegments); + + seg_to_hit[seg_id] = hit.id(); + + // Populate segment + segments[seg_id].phi = hit.emtfPhi(); + segments[seg_id].bend = hit.emtfBend(); + segments[seg_id].theta1 = hit.emtfTheta1(); + segments[seg_id].theta2 = hit.emtfTheta2(); + segments[seg_id].qual1 = hit.emtfQual1(); + segments[seg_id].qual2 = hit.emtfQual2(); + segments[seg_id].time = hit.emtfTime(); + segments[seg_id].zones = hit.emtfZones(); + segments[seg_id].tzones = hit_timezones; + segments[seg_id].cscfr = hit.cscFR(); + segments[seg_id].layer = hit.layer(); + segments[seg_id].bx = hit.bx(); + segments[seg_id].valid = hit.flagValid(); + + // Debug Info + if (this->context_.config_.verbosity_ > 1) { + edm::LogInfo("L1TEMTFpp") << std::endl + << "Event: " << event_->id() << " Endcap: " << endcap_ << " Sector: " << sector_ + << " BX: " << (*bx_) << " Hit iLink: " << hit_chamber << " Hit iSeg: " << ch_seg + << " Hit Host " << hit_host << " Hit Rel BX " << (hit_bx - *bx_) << " Hit Timezones " + << hit_timezones << std::endl; + + edm::LogInfo("L1TEMTFpp") << " id " << seg_id << " phi " << segments[seg_id].phi << " bend " + << segments[seg_id].bend << " theta1 " << segments[seg_id].theta1 << " theta2 " + << segments[seg_id].theta2 << " qual1 " << segments[seg_id].qual1 << " qual2 " + << segments[seg_id].qual2 << " time " << segments[seg_id].time << " zones " + << segments[seg_id].zones << " timezones " << segments[seg_id].tzones << " cscfr " + << segments[seg_id].cscfr << " layer " << segments[seg_id].layer << " bx " + << segments[seg_id].bx << " valid " << segments[seg_id].valid << std::endl; + } + + // Update bx chamber last segment + bx_last_ch_seg[hit_chamber] = ch_seg; + } // End loop hits from BX + + for (auto& [chamber, ch_seg] : bx_last_ch_seg) { + next_ch_seg[chamber] = ch_seg + 1; + } + + bx_last_ch_seg.clear(); + } // End loop from latest BX Collection to oldest BX Hit Collection +} + +void SectorProcessor::buildTracks(const std::map& seg_to_hit, + const segment_collection_t& segments, + const bool& displaced_en, + EMTFTrackCollection& out_tracks) { + // Apply Hitmap Building Layer: Convert segments into hitmaps + std::vector zone_hitmaps; + + context_.hitmap_building_layer_.apply(segments, zone_hitmaps); + + // Apply Pattern Matching Layer: Match patterns to hitmaps to create roads + std::vector zone_roads; + + context_.pattern_matching_layer_.apply(zone_hitmaps, displaced_en, zone_roads); + + // Apply Road Sorting Layer: Find the best roads + std::vector best_roads; + + context_.road_sorting_layer_.apply(v3::kNumTracks, zone_roads, best_roads); + + // Apply Track Building Layer: Match segments to the best roads to create tracks + std::vector tracks; + + context_.track_building_layer_.apply(segments, best_roads, displaced_en, tracks); + + // Apply Duplicate Removal Layer: Removes tracks that share a segment, keeping the one that has the highest quality + context_.duplicate_removal_layer_.apply(tracks); + + // Apply Parameter Assigment Layer: Run NN on tracks + context_.parameter_assignment_layer_.apply(displaced_en, tracks); + + // Apply Output Layer + EMTFTrackCollection bx_tracks; + + context_.output_layer_.apply(endcap_, sector_, *bx_, seg_to_hit, tracks, displaced_en, bx_tracks); + + // Record tracks + out_tracks.insert(out_tracks.end(), bx_tracks.begin(), bx_tracks.end()); +} diff --git a/L1Trigger/L1TMuonEndCapPhase2/src/TrackFinder.cc b/L1Trigger/L1TMuonEndCapPhase2/src/TrackFinder.cc new file mode 100644 index 0000000000000..af240d0e0c8ff --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/src/TrackFinder.cc @@ -0,0 +1,221 @@ +#include +#include +#include + +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/EventSetup.h" +#include "FWCore/Framework/interface/ConsumesCollector.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/MessageLogger/interface/MessageLogger.h" + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFContext.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFConfiguration.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFConstants.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFTypes.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/SectorProcessor.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/TPrimitives.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/TPCollectors.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/CSCTPCollector.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/RPCTPCollector.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/GEMTPCollector.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/ME0TPCollector.h" +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/GE0TPCollector.h" + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/TrackFinder.h" + +using namespace emtf::phase2; + +TrackFinder::TrackFinder(const edm::ParameterSet& i_config, edm::ConsumesCollector&& i_consumes_collector) + : context_(i_config, i_consumes_collector), tp_collectors_(), sector_processors_() { + // =========================================================================== + // Emulation Setup + // =========================================================================== + + // Register Trigger Primitives + if (this->context_.config_.csc_en_) { + tp_collectors_.push_back(std::make_unique(context_, i_consumes_collector)); + } + + if (this->context_.config_.rpc_en_) { + tp_collectors_.push_back(std::make_unique(context_, i_consumes_collector)); + } + + if (this->context_.config_.gem_en_) { + tp_collectors_.push_back(std::make_unique(context_, i_consumes_collector)); + } + + if (this->context_.config_.me0_en_) { + tp_collectors_.push_back(std::make_unique(context_, i_consumes_collector)); + } + + if (this->context_.config_.ge0_en_) { + tp_collectors_.push_back(std::make_unique(context_, i_consumes_collector)); + } + + // Register Sector Processor + for (unsigned int endcap = kMinEndcap; endcap <= kMaxEndcap; ++endcap) { + for (unsigned int sector = kMinTrigSector; sector <= kMaxTrigSector; ++sector) { + sector_processors_.push_back(std::make_unique(context_, endcap, sector)); + } + } +} + +TrackFinder::~TrackFinder() { + // Do Nothing +} + +void TrackFinder::process( + // Input + const edm::Event& i_event, + const edm::EventSetup& i_event_setup, + // Output + EMTFHitCollection& out_hits, + EMTFTrackCollection& out_tracks, + EMTFInputCollection& out_inputs) { + // =========================================================================== + // Clear output collections + // =========================================================================== + + out_hits.clear(); + out_tracks.clear(); + out_inputs.clear(); + + // =========================================================================== + // Load the event configuration + // =========================================================================== + + context_.update(i_event, i_event_setup); + + // =========================================================================== + // Collect trigger primitives + // =========================================================================== + + // Build BX Sequence + std::vector bx_sequence; + + { + auto min_bx = this->context_.config_.min_bx_; + auto delay_bx = this->context_.config_.bx_window_ - 1; + auto max_bx = this->context_.config_.max_bx_ + delay_bx; + + for (int bx = min_bx; bx <= max_bx; ++bx) { + bx_sequence.push_back(bx); + } + } + + // Collect TP per BX + BXTPCMap bx_tpc_map; + + for (auto& tp_collector : tp_collectors_) { + tp_collector->collect(i_event, bx_tpc_map); + } + + // Debug Info + if (this->context_.config_.verbosity_ > 4) { + int n_tp = 0; + + // Loop BX + for (const auto& bx : bx_sequence) { + // Get trigger primitives for this BX + auto bx_tpc_map_it = bx_tpc_map.find(bx); + auto bx_tpc_map_end = bx_tpc_map.end(); + + // Short-Circuit: Empty trigger primitive collection + if (bx_tpc_map_it == bx_tpc_map_end) { + continue; + } + + // Reference TPC + auto& bx_tpc = bx_tpc_map_it->second; + + // Short-Circuit: Empty trigger primitive collection + if (bx_tpc.empty()) { + continue; + } + + // Print trigger primitives + edm::LogInfo("L1TEMTFpp") << "===========================================================================" + << std::endl; + edm::LogInfo("L1TEMTFpp") << "Begin TPC BX " << bx << " Dump" << std::endl; + edm::LogInfo("L1TEMTFpp") << "---------------------------------------------------------------------------" + << std::endl; + + n_tp += bx_tpc.size(); + + for (const auto& tp_entry : bx_tpc) { + tp_entry.tp_.print(std::cout); + + edm::LogInfo("L1TEMTFpp") << "---------------------------------------------------------------------------" + << std::endl; + } + + edm::LogInfo("L1TEMTFpp") << "End TPC BX " << bx << " Dump" << std::endl; + edm::LogInfo("L1TEMTFpp") << "===========================================================================" + << std::endl; + } + + // Print TPrimitives Summary + if (n_tp > 0) { + edm::LogInfo("L1TEMTFpp") << "Num of TriggerPrimitive: " << n_tp << std::endl; + edm::LogInfo("L1TEMTFpp") << "===========================================================================" + << std::endl; + } + } + + // =========================================================================== + // Run sector processors + // =========================================================================== + + // Before event + for (auto& sector_processor : sector_processors_) { + sector_processor->configureEvent(i_event); + } + + // Orderly loop BX + for (const auto& bx : bx_sequence) { + // Get trigger primitives for this BX + auto bx_tpc_map_it = bx_tpc_map.find(bx); + auto bx_tpc_map_end = bx_tpc_map.end(); + + TPCollection* bx_tpc_ptr = nullptr; + + if (bx_tpc_map_it != bx_tpc_map_end) { + bx_tpc_ptr = &(bx_tpc_map_it->second); + } + + // Loop over all sector processors + for (auto& sector_processor : sector_processors_) { + // Before BX + sector_processor->configureBx(bx); + + // Select trigger primitives in BX + if (bx_tpc_ptr != nullptr) { + for (const auto& tp_entry : *bx_tpc_ptr) { + const auto& tp = tp_entry.tp_; + const auto& tp_info = tp_entry.info_; + + sector_processor->select(tp, tp_info); + } + } + + // Process trigger primitives + sector_processor->process(out_hits, out_tracks, out_inputs); + } + + // Free memory: Removes BX TPCollections after all Sector Processors have selected their TPrimitives + if (bx_tpc_ptr != nullptr) { + bx_tpc_map.erase(bx_tpc_map_it); + } + } + + // Free memory: Drops any BX TPCollections outside of the [min bx, max bx] range + bx_tpc_map.clear(); +} + +void TrackFinder::onJobBegin() { + // Do Nothing +} + +void TrackFinder::onJobEnd() { + // Do Nothing +} diff --git a/L1Trigger/L1TMuonEndCapPhase2/src/Utils/CSCUtils.cc b/L1Trigger/L1TMuonEndCapPhase2/src/Utils/CSCUtils.cc new file mode 100644 index 0000000000000..30c6eabfc9982 --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/src/Utils/CSCUtils.cc @@ -0,0 +1,168 @@ +#include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/TPrimitives.h" + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Utils/CSCUtils.h" + +namespace emtf::phase2::csc { + + // Chambers + int getNext10DegChamber(int chamber) { return (chamber == 36) ? 1 : (chamber + 1); } + + int getPrev10DegChamber(int chamber) { return (chamber == 1) ? 36 : (chamber - 1); } + + int getNext20DegChamber(int chamber) { return (chamber == 18) ? 1 : (chamber + 1); } + + int getPrev20DegChamber(int chamber) { return (chamber == 1) ? 18 : (chamber - 1); } + + // Sectors + bool isTPInSector(int sp_endcap, int sp_sector, int tp_endcap, int tp_sector) { + return sp_endcap == tp_endcap && sp_sector == tp_sector; + } + + bool isTPInNeighborSector( + int sp_endcap, int sp_sector, int tp_endcap, int tp_sector, int tp_subsector, int tp_station, int tp_id) { + // Match endcap and neighbor sector + int neighbor_sector = ((sp_sector == 1) ? 6 : sp_sector - 1); + + if ((sp_endcap != tp_endcap) || (neighbor_sector != tp_sector)) + return false; + + // Match CSCID in station 1 + if (tp_station == 1) + return (tp_subsector == 2) && (tp_id == 3 || tp_id == 6 || tp_id == 9); + + // Match CSCID in other stations + return tp_id == 3 || tp_id == 9; + } + + // Use CSC trigger "CSC ID" definitions + // Copied from DataFormats/MuonDetId/src/CSCDetId.cc + int getId(int station, int ring, int chamber) { + int result = 0; + + if (station == 1) { + result = (chamber) % 3 + 1; // 1,2,3 + + switch (ring) { + case 1: + break; + case 2: + result += 3; // 4,5,6 + break; + case 3: + result += 6; // 7,8,9 + break; + case 4: + break; + } + } else { + if (ring == 1) { + result = (chamber + 1) % 3 + 1; // 1,2,3 + } else { + result = (chamber + 3) % 6 + 4; // 4,5,6,7,8,9 + } + } + + return result; + } + + // Use CSC trigger sector definitions + // Copied from DataFormats/MuonDetId/src/CSCDetId.cc + int getTriggerSector(int station, int ring, int chamber) { + int result = 0; + + if (station > 1 && ring > 1) { + result = ((static_cast(chamber - 3) & 0x7f) / 6) + 1; // ch 3-8->1, 9-14->2, ... 1,2 -> 6 + } else if (station == 1) { + result = ((static_cast(chamber - 3) & 0x7f) / 6) + 1; // ch 3-8->1, 9-14->2, ... 1,2 -> 6 + } else { + result = ((static_cast(chamber - 2) & 0x1f) / 3) + 1; // ch 2-4-> 1, 5-7->2, ... + } + + return (result <= 6) ? result + : 6; // max sector is 6, some calculations give a value greater than six but this is expected. + } + + int getTriggerSubsector(int station, int chamber) { + // station 2,3,4 --> subsector 0 + if (station != 1) { + return 0; + } + + // station 1 --> subsector 1 or 2 + if ((chamber % 6) > 2) { + return 1; + } + + return 2; + } + + // Copied from RecoMuon/DetLayers/src/MuonCSCDetLayerGeometryBuilder.cc + Facing getFaceDirection(int station, int ring, int chamber) { + bool is_not_overlapping = (station == 1 && ring == 3); + + // Not overlapping means it's facing backwards + if (is_not_overlapping) + return Facing::kRear; + + // odd chambers are bolted to the iron, which faces + // forward in stations 1 and 2, backward in stations 3 and 4 + bool is_even = (chamber % 2 == 0); + + if (station < 3) + return (is_even ? Facing::kRear : Facing::kFront); + + return (is_even ? Facing::kFront : Facing::kRear); + } + + // Number of halfstrips and wiregroups + // +----------------------------+------------+------------+ + // | Chamber type | Num of | Num of | + // | | halfstrips | wiregroups | + // +----------------------------+------------+------------+ + // | ME1/1a | 96 | 48 | + // | ME1/1b | 128 | 48 | + // | ME1/2 | 160 | 64 | + // | ME1/3 | 128 | 32 | + // | ME2/1 | 160 | 112 | + // | ME3/1, ME4/1 | 160 | 96 | + // | ME2/2, ME3/2, ME4/2 | 160 | 64 | + // +----------------------------+------------+------------+ + + std::pair getMaxStripAndWire(int station, int ring) { + int max_strip = 0; // halfstrip + int max_wire = 0; // wiregroup + + if (station == 1 && ring == 4) { // ME1/1a + max_strip = 96; + max_wire = 48; + } else if (station == 1 && ring == 1) { // ME1/1b + max_strip = 128; + max_wire = 48; + } else if (station == 1 && ring == 2) { // ME1/2 + max_strip = 160; + max_wire = 64; + } else if (station == 1 && ring == 3) { // ME1/3 + max_strip = 128; + max_wire = 32; + } else if (station == 2 && ring == 1) { // ME2/1 + max_strip = 160; + max_wire = 112; + } else if (station >= 3 && ring == 1) { // ME3/1, ME4/1 + max_strip = 160; + max_wire = 96; + } else if (station >= 2 && ring == 2) { // ME2/2, ME3/2, ME4/2 + max_strip = 160; + max_wire = 64; + } + + return std::make_pair(max_strip, max_wire); + } + + std::pair getMaxPatternAndQuality(int station, int ring) { + int max_pattern = 11; + int max_quality = 16; + + return std::make_pair(max_pattern, max_quality); + } + +} // namespace emtf::phase2::csc diff --git a/L1Trigger/L1TMuonEndCapPhase2/src/Utils/TPUtils.cc b/L1Trigger/L1TMuonEndCapPhase2/src/Utils/TPUtils.cc new file mode 100644 index 0000000000000..dfd4d39dfc17c --- /dev/null +++ b/L1Trigger/L1TMuonEndCapPhase2/src/Utils/TPUtils.cc @@ -0,0 +1,124 @@ +#include + +#include "L1Trigger/L1TMuonEndCapPhase2/interface/Utils/TPUtils.h" + +namespace emtf::phase2::tp { + + // _______________________________________________________________________ + // radians <-> degrees + float degToRad(float deg) { + constexpr float factor = M_PI / 180.; + return deg * factor; + } + + float radToDeg(float rad) { + constexpr float factor = 180. / M_PI; + + return rad * factor; + } + + // _______________________________________________________________________ + // phi range: [-180..180] or [-pi..pi] + float wrapPhiDeg(float deg) { + float twopi = 360.; + float recip = 1.0 / twopi; + + return deg - (std::round(deg * recip) * twopi); + } + + float wrapPhiRad(float rad) { + const float twopi = M_PI * 2.; + const float recip = 1.0 / twopi; + + return rad - (std::round(rad * recip) * twopi); + } + + // _______________________________________________________________________ + // theta + float calcThetaRadFromEta(float eta) { + float theta = std::atan2(1.0, std::sinh(eta)); // cot(theta) = sinh(eta) + + return theta; + } + + float calcThetaDegFromEta(float eta) { + float theta = radToDeg(calcThetaRadFromEta(eta)); + + return theta; + } + + float calcThetaRadFromInt(int theta_int) { + float theta = degToRad(calcThetaDegFromInt(theta_int)); + + return theta; + } + + float calcThetaDegFromInt(int theta_int) { + float theta = static_cast(theta_int); + + theta = theta * (45.0 - 8.5) / 128. + 8.5; + + return theta; + } + + int calcThetaInt(int endcap, float theta) { // theta in deg [0..180], endcap [-1, +1] + theta = (endcap == -1) ? (180. - theta) : theta; + theta = (theta - 8.5) * 128. / (45.0 - 8.5); + + int theta_int = static_cast(std::round(theta)); + + theta_int = (theta_int <= 0) ? 1 : theta_int; // protect against invalid value + + return theta_int; + } + + // _______________________________________________________________________ + // phi + float calcPhiGlobDegFromLoc(int sector, float loc) { // loc in deg, sector [1..6] + float glob = loc + 15. + (60. * (sector - 1)); + + glob = (glob >= 180.) ? (glob - 360.) : glob; + + return glob; + } + + float calcPhiGlobRadFromLoc(int sector, float loc) { // loc in rad, sector [1..6] + float glob = degToRad(calcPhiGlobDegFromLoc(sector, radToDeg(loc))); + + return glob; + } + + float calcPhiLocDegFromInt(int phi_int) { + float loc = static_cast(phi_int); + + loc = (loc / 60.) - 22.; + + return loc; + } + + float calcPhiLocRadFromInt(int phi_int) { + float loc = degToRad(calcPhiLocDegFromInt(phi_int)); + + return loc; + } + + float calcPhiLocDegFromGlob(int sector, float glob) { // glob in deg [-180..180], sector [1..6] + glob = wrapPhiDeg(glob); + + float loc = glob - 15. - (60. * (sector - 1)); + + return loc; + } + + int calcPhiInt(int sector, float glob) { // glob in deg [-180..180], sector [1..6] + float loc = calcPhiLocDegFromGlob(sector, glob); + + loc = ((loc + 22.) < 0.) ? (loc + 360.) : loc; + loc = (loc + 22.) * 60.; + + int phi_int = static_cast(std::round(loc)); + + return phi_int; + } + +} // namespace emtf::phase2::tp