Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:21:03

0001 #include <iostream>
0002 
0003 #include "FWCore/Framework/interface/Event.h"
0004 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0005 
0006 #include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFConstants.h"
0007 #include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFContext.h"
0008 #include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFTypes.h"
0009 #include "L1Trigger/L1TMuonEndCapPhase2/interface/Algo/HitmapLayer.h"
0010 #include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/CSCTPConverter.h"
0011 #include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/CSCTPSelector.h"
0012 #include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/RPCTPConverter.h"
0013 #include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/RPCTPSelector.h"
0014 #include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/GEMTPConverter.h"
0015 #include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/GEMTPSelector.h"
0016 #include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/ME0TPConverter.h"
0017 #include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/ME0TPSelector.h"
0018 #include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/GE0TPConverter.h"
0019 #include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/GE0TPSelector.h"
0020 #include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/TPConverters.h"
0021 #include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/TPSelectors.h"
0022 #include "L1Trigger/L1TMuonEndCapPhase2/interface/DAQ/TPrimitives.h"
0023 #include "L1Trigger/L1TMuonEndCapPhase2/interface/Utils/DebugUtils.h"
0024 #include "L1Trigger/L1TMuonEndCapPhase2/interface/Utils/CSCUtils.h"
0025 
0026 #include "L1Trigger/L1TMuonEndCapPhase2/interface/SectorProcessor.h"
0027 
0028 using namespace emtf::phase2;
0029 
0030 SectorProcessor::SectorProcessor(const EMTFContext& context, const int& endcap, const int& sector)
0031     : context_(context), endcap_(endcap), sector_(sector), event_(nullptr), bx_(nullptr) {
0032   // ===========================================================================
0033   // Register Selectors/Converters
0034   // ===========================================================================
0035   if (this->context_.config_.csc_en_) {
0036     tp_selectors_[L1TMuon::kCSC] = std::make_unique<CSCTPSelector>(context_, endcap_, sector_);
0037     tp_converters_[L1TMuon::kCSC] = std::make_unique<CSCTPConverter>(context_, endcap_, sector_);
0038   }
0039 
0040   if (this->context_.config_.rpc_en_) {
0041     tp_selectors_[L1TMuon::kRPC] = std::make_unique<RPCTPSelector>(context_, endcap_, sector_);
0042     tp_converters_[L1TMuon::kRPC] = std::make_unique<RPCTPConverter>(context_, endcap_, sector_);
0043   }
0044 
0045   if (this->context_.config_.gem_en_) {
0046     tp_selectors_[L1TMuon::kGEM] = std::make_unique<GEMTPSelector>(context_, endcap_, sector_);
0047     tp_converters_[L1TMuon::kGEM] = std::make_unique<GEMTPConverter>(context_, endcap_, sector_);
0048   }
0049 
0050   if (this->context_.config_.me0_en_) {
0051     tp_selectors_[L1TMuon::kME0] = std::make_unique<ME0TPSelector>(context_, endcap_, sector_);
0052     tp_converters_[L1TMuon::kME0] = std::make_unique<ME0TPConverter>(context_, endcap_, sector_);
0053   }
0054 
0055   if (this->context_.config_.ge0_en_) {
0056     tp_selectors_[L1TMuon::kME0] = std::make_unique<GE0TPSelector>(context_, endcap_, sector_);
0057     tp_converters_[L1TMuon::kME0] = std::make_unique<GE0TPConverter>(context_, endcap_, sector_);
0058   }
0059 }
0060 
0061 SectorProcessor::~SectorProcessor() {
0062   // Do Nothing
0063 }
0064 
0065 void SectorProcessor::configureEvent(const edm::Event& event) {
0066   // Event
0067   event_ = &event;
0068   bx_ = nullptr;
0069 
0070   // Reset Window Hits
0071   bx_window_hits_.clear();
0072   bx_ilink_tpc_maps_.clear();
0073 }
0074 
0075 void SectorProcessor::configureBx(const int& bx) {
0076   // BX
0077   bx_ = &bx;
0078 
0079   // Reset BX Maps
0080   bx_ilink_tpc_maps_.clear();
0081 
0082   // Remove BX TPCollections that aren't in the bx window
0083   // Note that the first entry in bx_window_hits is the earliest BX
0084   const auto min_bx = this->context_.config_.min_bx_;
0085   const auto delay_bx = this->context_.config_.bx_window_ - 1;
0086   const auto pop_after_bx = min_bx + delay_bx;
0087 
0088   if (pop_after_bx < bx) {
0089     bx_window_hits_.erase(bx_window_hits_.begin());
0090   }
0091 }
0092 
0093 void SectorProcessor::select(const TriggerPrimitive& tp, const TPInfo& tp_info) {
0094   // Get TPSelector
0095   auto tp_subsystem = tp.subsystem();
0096 
0097   auto tp_selectors_it = tp_selectors_.find(tp_subsystem);
0098 
0099   // Short-Circuit: Operation not supported
0100   if (tp_selectors_it == tp_selectors_.end()) {
0101     edm::LogWarning("L1TEMTFpp") << "TPCollector has been implemented, "
0102                                  << "but there is no TPSelector for " << tp_subsystem;
0103     return;
0104   }
0105 
0106   // Select TP that belongs to this Sector Processor
0107   auto& bx_ilink_tpc_map = bx_ilink_tpc_maps_[tp_subsystem];  // reference to subsystem trigger primitive collection
0108 
0109   tp_selectors_it->second->select(tp, tp_info, bx_ilink_tpc_map);
0110 }
0111 
0112 void SectorProcessor::process(EMTFHitCollection& out_hits,
0113                               EMTFTrackCollection& out_tracks,
0114                               EMTFInputCollection& out_inputs) {
0115   // ===========================================================================
0116   // Merge subsystem selections
0117   // ===========================================================================
0118   ILinkTPCMap bx_ilink_tpc_map;
0119 
0120   for (auto& [subsystem, ilink_tpc_map] : bx_ilink_tpc_maps_) {
0121     copyTP(ilink_tpc_map, bx_ilink_tpc_map);
0122   }
0123 
0124   // Free memory
0125   bx_ilink_tpc_maps_.clear();
0126 
0127   // ===========================================================================
0128   // Convert trigger primitives to EMTF Hits
0129   // ===========================================================================
0130 
0131   // Convert tp into hits
0132   EMTFHitCollection bx_hits;
0133 
0134   convertTP(out_hits.size(), bx_ilink_tpc_map, bx_hits);
0135 
0136   // Append to bx window hits
0137   bx_window_hits_.push_back(bx_hits);
0138 
0139   // Free memory
0140   bx_ilink_tpc_map.clear();
0141 
0142   // Record hits
0143   out_hits.insert(out_hits.end(), bx_hits.begin(), bx_hits.end());
0144 
0145   // ===========================================================================
0146   // Current Algorithm only supports BX=0
0147   // ===========================================================================
0148 
0149   if ((*bx_) != 0) {
0150     return;
0151   }
0152 
0153   // ===========================================================================
0154   // Convert EMTF Hits to Segments
0155   // ===========================================================================
0156 
0157   // Init Segment to Hit Map
0158   std::map<int, int> seg_to_hit;
0159 
0160   // Convert bx window hits into segments
0161   segment_collection_t segments;
0162 
0163   populateSegments(bx_window_hits_, seg_to_hit, segments);
0164 
0165   // Build Tracks
0166   buildTracks(seg_to_hit, segments, false, out_tracks);  // With prompt setup
0167   buildTracks(seg_to_hit, segments, true, out_tracks);   // With displaced setup
0168 
0169   // ===========================================================================
0170   // Record segments/hits used in track building
0171   // ===========================================================================
0172   if (!seg_to_hit.empty()) {
0173     EMTFInput::hits_t hit_id_col;
0174     EMTFInput::segs_t seg_id_col;
0175 
0176     for (const auto& [seg_id, hit_id] : seg_to_hit) {
0177       seg_id_col.push_back(seg_id);
0178       hit_id_col.push_back(hit_id);
0179     }
0180 
0181     EMTFInput emtf_input;
0182 
0183     const int endcap_pm = (endcap_ == 2) ? -1 : endcap_;  // 1: +endcap, -1: -endcap
0184 
0185     emtf_input.setEndcap(endcap_pm);
0186     emtf_input.setSector(sector_);
0187     emtf_input.setBx(*bx_);
0188     emtf_input.setHits(hit_id_col);
0189     emtf_input.setSegs(seg_id_col);
0190 
0191     out_inputs.push_back(emtf_input);
0192   }
0193 }
0194 
0195 void SectorProcessor::copyTP(const ILinkTPCMap& source, ILinkTPCMap& target) const {
0196   typedef typename ILinkTPCMap::iterator Iterator_t;
0197   typedef typename ILinkTPCMap::mapped_type Collection_t;
0198 
0199   for (auto& source_kv : source) {
0200     std::pair<Iterator_t, bool> ins_res = target.insert(source_kv);
0201 
0202     // Short-Circuit: Insertion succeeded, move on
0203     if (ins_res.second) {
0204       continue;
0205     }
0206 
0207     // Merge into target collection
0208     const Collection_t& source_col = source_kv.second;
0209     Collection_t& target_col = ins_res.first->second;
0210 
0211     target_col.insert(target_col.end(), source_col.begin(), source_col.end());
0212   }
0213 }
0214 
0215 void SectorProcessor::convertTP(const int& initial_hit_id, const ILinkTPCMap& ilink_tpc_map, EMTFHitCollection& hits) {
0216   EMTFHitCollection substitutes;
0217 
0218   for (const auto& [ilink, ilink_tpc] : ilink_tpc_map) {  // loop input link trigger primitive collections
0219 
0220     unsigned int cnt_segments = 0;  // Enumerates each segment in the same chamber
0221 
0222     for (const auto& tp_entry : ilink_tpc) {  // loop trigger primitives
0223 
0224       // Unpack Entry
0225       const auto& tp = tp_entry.tp_;  // const reference
0226       auto tp_info = tp_entry.info_;  // copy info
0227 
0228       // Unpack trigger primitive
0229       auto tp_subsystem = tp.subsystem();
0230 
0231       // Get Converter
0232       auto tp_converters_it = tp_converters_.find(tp_subsystem);
0233 
0234       // Short-Circuit: Operation not supported
0235       if (tp_converters_it == tp_converters_.end()) {
0236         edm::LogWarning("L1TEMTFpp") << "TPCollector & TPSelector have been implemented, "
0237                                      << "but there is no TPConverter for " << tp_subsystem;
0238         continue;
0239       }
0240 
0241       // Set Segment Id
0242       tp_info.segment_id = cnt_segments++;  // Save and increase segment count
0243 
0244       // Convert
0245       EMTFHit hit;
0246 
0247       tp_converters_it->second->convert(tp, tp_info, hit);
0248 
0249       // Append to hit collections
0250       if (tp_info.flag_substitute) {
0251         substitutes.push_back(hit);
0252       } else {
0253         hits.push_back(hit);
0254       }
0255     }
0256   }
0257 
0258   // Substitutes are placed at the end of the hit collection
0259   hits.insert(hits.end(), std::make_move_iterator(substitutes.begin()), std::make_move_iterator(substitutes.end()));
0260 
0261   // Assign Hit Ids
0262   unsigned int cnt_hits = initial_hit_id;
0263 
0264   for (auto& hit : hits) {
0265     hit.setId(cnt_hits++);
0266   }
0267 }
0268 
0269 void SectorProcessor::populateSegments(const std::vector<EMTFHitCollection>& bx_window_hits,
0270                                        std::map<int, int>& seg_to_hit,
0271                                        segment_collection_t& segments) {
0272   // Initialize
0273   for (unsigned int seg_id = 0; seg_id < v3::kNumSegments; ++seg_id) {
0274     segments[seg_id].phi = 0;
0275     segments[seg_id].bend = 0;
0276     segments[seg_id].theta1 = 0;
0277     segments[seg_id].theta2 = 0;
0278     segments[seg_id].qual1 = 0;
0279     segments[seg_id].qual2 = 0;
0280     segments[seg_id].time = 0;
0281     segments[seg_id].zones = 0;
0282     segments[seg_id].tzones = 0;
0283     segments[seg_id].cscfr = 0;
0284     segments[seg_id].layer = 0;
0285     segments[seg_id].bx = 0;
0286     segments[seg_id].valid = 0;
0287   }
0288 
0289   // Populate
0290   auto bx_window_hits_rit = bx_window_hits.rbegin();
0291   auto bx_window_hits_rend = bx_window_hits.rend();
0292 
0293   std::map<int, unsigned int> next_ch_seg;
0294 
0295   for (; bx_window_hits_rit != bx_window_hits_rend;
0296        ++bx_window_hits_rit) {  // Begin loop from latest BX Collection to oldest BX Hit Collection
0297 
0298     const auto& bx_hits = *bx_window_hits_rit;
0299     std::map<int, unsigned int> bx_last_ch_seg;
0300 
0301     for (const auto& hit : bx_hits) {  // Begin loop hits in BX
0302       // Unpack Hit
0303       const auto& hit_chamber = hit.emtfChamber();
0304       const auto& hit_segment = hit.emtfSegment();
0305       const auto& hit_valid = hit.flagValid();
0306 
0307       emtf_assert(hit_valid);  // segment must be valid
0308 
0309       // Get Channel Segment Count
0310       unsigned int ch_seg = next_ch_seg[hit_chamber] + hit_segment;
0311 
0312       // Short-Circuit: Accept at most 2 segments
0313       if (!(ch_seg < v3::kChamberSegments)) {
0314         continue;
0315       }
0316 
0317       // Calculate Host
0318       const auto& hit_host = hit.emtfHost();
0319 
0320       // Calculate Relative BX
0321       // Note: Uses Hit BX relative to Sector Processor BX
0322       const auto& hit_bx = hit.bx();
0323       const int hit_rel_bx = (hit_bx - *bx_);
0324 
0325       // Short-Circuit: Only use Relative BX=0 Segments
0326       if (hit_rel_bx != 0) {
0327         continue;
0328       }
0329 
0330       // Calculate Timezone
0331       const auto hit_timezones = context_.timezone_lut_.getTimezones(hit_host, hit_rel_bx);
0332 
0333       // Calculate algo seg
0334       const unsigned int seg_id = hit_chamber * v3::kChamberSegments + ch_seg;
0335 
0336       emtf_assert(seg_id < v3::kNumSegments);
0337 
0338       seg_to_hit[seg_id] = hit.id();
0339 
0340       // Populate segment
0341       segments[seg_id].phi = hit.emtfPhi();
0342       segments[seg_id].bend = hit.emtfBend();
0343       segments[seg_id].theta1 = hit.emtfTheta1();
0344       segments[seg_id].theta2 = hit.emtfTheta2();
0345       segments[seg_id].qual1 = hit.emtfQual1();
0346       segments[seg_id].qual2 = hit.emtfQual2();
0347       segments[seg_id].time = hit.emtfTime();
0348       segments[seg_id].zones = hit.emtfZones();
0349       segments[seg_id].tzones = hit_timezones;
0350       segments[seg_id].cscfr = hit.cscFR();
0351       segments[seg_id].layer = hit.layer();
0352       segments[seg_id].bx = hit.bx();
0353       segments[seg_id].valid = hit.flagValid();
0354 
0355       // Debug Info
0356       if (this->context_.config_.verbosity_ > 1) {
0357         edm::LogInfo("L1TEMTFpp") << std::endl
0358                                   << "Event: " << event_->id() << " Endcap: " << endcap_ << " Sector: " << sector_
0359                                   << " BX: " << (*bx_) << " Hit iLink: " << hit_chamber << " Hit iSeg: " << ch_seg
0360                                   << " Hit Host " << hit_host << " Hit Rel BX " << (hit_bx - *bx_) << " Hit Timezones "
0361                                   << hit_timezones << std::endl;
0362 
0363         edm::LogInfo("L1TEMTFpp") << " id " << seg_id << " phi " << segments[seg_id].phi << " bend "
0364                                   << segments[seg_id].bend << " theta1 " << segments[seg_id].theta1 << " theta2 "
0365                                   << segments[seg_id].theta2 << " qual1 " << segments[seg_id].qual1 << " qual2 "
0366                                   << segments[seg_id].qual2 << " time " << segments[seg_id].time << " zones "
0367                                   << segments[seg_id].zones << " timezones " << segments[seg_id].tzones << " cscfr "
0368                                   << segments[seg_id].cscfr << " layer " << segments[seg_id].layer << " bx "
0369                                   << segments[seg_id].bx << " valid " << segments[seg_id].valid << std::endl;
0370       }
0371 
0372       // Update bx chamber last segment
0373       bx_last_ch_seg[hit_chamber] = ch_seg;
0374     }  // End loop hits from BX
0375 
0376     for (auto& [chamber, ch_seg] : bx_last_ch_seg) {
0377       next_ch_seg[chamber] = ch_seg + 1;
0378     }
0379 
0380     bx_last_ch_seg.clear();
0381   }  // End loop from latest BX Collection to oldest BX Hit Collection
0382 }
0383 
0384 void SectorProcessor::buildTracks(const std::map<int, int>& seg_to_hit,
0385                                   const segment_collection_t& segments,
0386                                   const bool& displaced_en,
0387                                   EMTFTrackCollection& out_tracks) {
0388   // Apply Hitmap Building Layer: Convert segments into hitmaps
0389   std::vector<hitmap_t> zone_hitmaps;
0390 
0391   context_.hitmap_building_layer_.apply(segments, zone_hitmaps);
0392 
0393   // Apply Pattern Matching Layer: Match patterns to hitmaps to create roads
0394   std::vector<road_collection_t> zone_roads;
0395 
0396   context_.pattern_matching_layer_.apply(zone_hitmaps, displaced_en, zone_roads);
0397 
0398   // Apply Road Sorting Layer: Find the best roads
0399   std::vector<road_t> best_roads;
0400 
0401   context_.road_sorting_layer_.apply(v3::kNumTracks, zone_roads, best_roads);
0402 
0403   // Apply Track Building Layer: Match segments to the best roads to create tracks
0404   std::vector<track_t> tracks;
0405 
0406   context_.track_building_layer_.apply(segments, best_roads, displaced_en, tracks);
0407 
0408   // Apply Duplicate Removal Layer: Removes tracks that share a segment, keeping the one that has the highest quality
0409   context_.duplicate_removal_layer_.apply(tracks);
0410 
0411   // Apply Parameter Assigment Layer: Run NN on tracks
0412   context_.parameter_assignment_layer_.apply(displaced_en, tracks);
0413 
0414   // Apply Output Layer
0415   EMTFTrackCollection bx_tracks;
0416 
0417   context_.output_layer_.apply(endcap_, sector_, *bx_, seg_to_hit, tracks, displaced_en, bx_tracks);
0418 
0419   // Record tracks
0420   out_tracks.insert(out_tracks.end(), bx_tracks.begin(), bx_tracks.end());
0421 }