Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-09-07 04:36:44

0001 #include "L1Trigger/CSCTriggerPrimitives/interface/CSCUpgradeCathodeLCTProcessor.h"
0002 
0003 #include <iomanip>
0004 
0005 CSCUpgradeCathodeLCTProcessor::CSCUpgradeCathodeLCTProcessor(unsigned endcap,
0006                                                              unsigned station,
0007                                                              unsigned sector,
0008                                                              unsigned subsector,
0009                                                              unsigned chamber,
0010                                                              CSCBaseboard::Parameters& conf)
0011     : CSCCathodeLCTProcessor(endcap, station, sector, subsector, chamber, conf) {
0012   if (!runPhase2_)
0013     edm::LogError("CSCUpgradeCathodeLCTProcessor|ConfigError")
0014         << "+++ Upgrade CSCUpgradeCathodeLCTProcessor constructed while runPhase2_ is not set! +++\n";
0015 
0016   // use of localized dead-time zones
0017   use_dead_time_zoning_ = conf.clctParams().getParameter<bool>("useDeadTimeZoning");
0018   clct_state_machine_zone_ = conf.clctParams().getParameter<unsigned int>("clctStateMachineZone");
0019 
0020   // how far away may trigger happen from pretrigger
0021   pretrig_trig_zone_ = conf.clctParams().getParameter<unsigned int>("clctPretriggerTriggerZone");
0022 }
0023 
0024 // --------------------------------------------------------------------------
0025 // The code below is for Phase2 studies of the CLCT algorithm
0026 // --------------------------------------------------------------------------
0027 
0028 // Phase2 version, add the feature of localized dead time zone for pretrigger
0029 bool CSCUpgradeCathodeLCTProcessor::preTrigger(const int start_bx, int& first_bx) {
0030   if (runPhase2_ and !use_dead_time_zoning_) {
0031     return CSCCathodeLCTProcessor::preTrigger(start_bx, first_bx);
0032   }
0033 
0034   if (infoV > 1)
0035     LogTrace("CSCUpgradeCathodeLCTProcessor")
0036         << "....................PreTrigger, Phase2 version with localized dead time zone...........................";
0037 
0038   int nPreTriggers = 0;
0039 
0040   bool pre_trig = false;
0041 
0042   // Now do a loop over bx times to see (if/when) track goes over threshold
0043   for (unsigned int bx_time = start_bx; bx_time < fifo_tbins; bx_time++) {
0044     // For any given bunch-crossing, start at the lowest keystrip and look for
0045     // the number of separate layers in the pattern for that keystrip that have
0046     // pulses at that bunch-crossing time.  Do the same for the next keystrip,
0047     // etc.  Then do the entire process again for the next bunch-crossing, etc
0048     // until you find a pre-trigger.
0049     std::map<int, std::map<int, CSCCLCTDigi::ComparatorContainer> > hits_in_patterns;
0050     hits_in_patterns.clear();
0051 
0052     bool hits_in_time = patternFinding(bx_time, hits_in_patterns);
0053     if (hits_in_time) {
0054       for (int hstrip = stagger[CSCConstants::KEY_CLCT_LAYER - 1]; hstrip < numHalfStrips_; hstrip++) {
0055         if (infoV > 1) {
0056           if (nhits[hstrip] > 0) {
0057             LogTrace("CSCUpgradeCathodeLCTProcessor")
0058                 << " bx = " << std::setw(2) << bx_time << " --->"
0059                 << " halfstrip = " << std::setw(3) << hstrip << " best pid = " << std::setw(2) << best_pid[hstrip]
0060                 << " nhits = " << nhits[hstrip];
0061           }
0062         }
0063         // note that ispretrig_ is initialized in findLCT function
0064         if (nhits[hstrip] >= nplanes_hit_pretrig && best_pid[hstrip] >= pid_thresh_pretrig &&
0065             !busyMap_[hstrip][bx_time]) {
0066           pre_trig = true;
0067           ispretrig_[hstrip] = true;
0068 
0069           // write each pre-trigger to output
0070           nPreTriggers++;
0071           thePreTriggerDigis.push_back(constructPreCLCT(bx_time, hstrip, nPreTriggers));
0072         }
0073         // busy zone, keep pretriggering, ignore this
0074         else if (nhits[hstrip] >= nplanes_hit_pretrig && best_pid[hstrip] >= pid_thresh_pretrig) {
0075           ispretrig_[hstrip] = true;
0076           if (infoV > 1)
0077             LogTrace("CSCUpgradeCathodeLCTProcessor")
0078                 << " halfstrip " << std::setw(3) << hstrip << " in dead zone and is pretriggerred";
0079         }
0080         // no pretrigger on this halfstrip, release dead zone
0081         else if (nhits[hstrip] < nplanes_hit_pretrig || best_pid[hstrip] < pid_thresh_pretrig) {
0082           ispretrig_[hstrip] = false;
0083         }
0084       }  // find all pretriggers
0085 
0086       // update dead zone
0087       markBusyZone(bx_time);
0088 
0089       if (pre_trig) {
0090         first_bx = bx_time;  // bx at time of pretrigger
0091         return true;
0092       }
0093     } else {
0094       // no pattern found, remove all dead zone
0095       clearPreTriggers();
0096     }
0097   }  // end loop over bx times
0098 
0099   if (infoV > 1)
0100     LogTrace("CSCUpgradeCathodeLCTProcessor") << "no pretrigger, returning \n";
0101   first_bx = fifo_tbins;
0102   return false;
0103 }  // preTrigger -- Phase2 version.
0104 
0105 // Phase2 version.
0106 std::vector<CSCCLCTDigi> CSCUpgradeCathodeLCTProcessor::findLCTs(
0107     const std::vector<int> halfstrip[CSCConstants::NUM_LAYERS][CSCConstants::MAX_NUM_HALF_STRIPS_RUN2_TRIGGER],
0108     const CSCL1TPLookupTableCCLUT* lookupTable) {
0109   // run the original algorithm in case we do not use dead time zoning
0110   if (runPhase2_ and !use_dead_time_zoning_) {
0111     return CSCCathodeLCTProcessor::findLCTs(halfstrip, lookupTable);
0112   }
0113 
0114   std::vector<CSCCLCTDigi> lctList;
0115 
0116   // initialize the ispretrig_ before doing pretriggering
0117   clearPreTriggers();
0118 
0119   if (infoV > 1)
0120     dumpDigis(halfstrip);
0121 
0122   // keeps dead-time zones around key halfstrips of triggered CLCTs
0123   for (int i = 0; i < CSCConstants::MAX_NUM_HALF_STRIPS_RUN2_TRIGGER; i++) {
0124     for (int j = 0; j < CSCConstants::MAX_CLCT_TBINS; j++) {
0125       busyMap_[i][j] = false;
0126     }
0127   }
0128 
0129   // Fire half-strip one-shots for hit_persist bx's (4 bx's by default).
0130   pulseExtension(halfstrip);
0131 
0132   unsigned int start_bx = start_bx_shift;
0133   // Stop drift_delay bx's short of fifo_tbins since at later bx's we will
0134   // not have a full set of hits to start pattern search anyway.
0135   unsigned int stop_bx = fifo_tbins - drift_delay;
0136 
0137   // Allow for more than one pass over the hits in the time window.
0138   // Do search in every BX
0139   while (start_bx < stop_bx) {
0140     // temp CLCT objects
0141     CSCCLCTDigi tempBestCLCT;
0142     CSCCLCTDigi tempSecondCLCT;
0143 
0144     // All half-strip pattern envelopes are evaluated simultaneously, on every clock cycle.
0145     int first_bx = 999;
0146 
0147     // Check for a pre-trigger. If so, find the first BX when the pre-trigger occurred
0148     bool pre_trig = CSCUpgradeCathodeLCTProcessor::preTrigger(start_bx, first_bx);
0149 
0150     // If any of half-strip envelopes has enough layers hit in it, TMB
0151     // will pre-trigger.
0152     if (pre_trig) {
0153       if (infoV > 1)
0154         LogTrace("CSCUpgradeCathodeLCTProcessor")
0155             << "..... pretrigger at bx = " << first_bx << "; waiting drift delay .....";
0156 
0157       // TMB latches LCTs drift_delay clocks after pretrigger.
0158       int latch_bx = first_bx + drift_delay;
0159 
0160       // temporary container to keep track of the hits in the CLCT
0161       std::map<int, std::map<int, CSCCLCTDigi::ComparatorContainer> > hits_in_patterns;
0162       hits_in_patterns.clear();
0163 
0164       // We check if there is at least one key half strip for which at least
0165       // one pattern id has at least the minimum number of hits
0166       bool hits_in_time = patternFinding(latch_bx, hits_in_patterns);
0167       if (infoV > 1) {
0168         if (hits_in_time) {
0169           for (int hstrip = stagger[CSCConstants::KEY_CLCT_LAYER - 1]; hstrip < numHalfStrips_; hstrip++) {
0170             if (nhits[hstrip] > 0) {
0171               LogTrace("CSCUpgradeCathodeLCTProcessor")
0172                   << " bx = " << std::setw(2) << latch_bx << " --->"
0173                   << " halfstrip = " << std::setw(3) << hstrip << " best pid = " << std::setw(2) << best_pid[hstrip]
0174                   << " nhits = " << nhits[hstrip];
0175             }
0176           }
0177         }
0178       }
0179 
0180       // Quality for sorting.
0181       int quality[CSCConstants::MAX_NUM_HALF_STRIPS_RUN2_TRIGGER];
0182       int best_halfstrip[CSCConstants::MAX_CLCTS_PER_PROCESSOR], best_quality[CSCConstants::MAX_CLCTS_PER_PROCESSOR];
0183       for (int ilct = 0; ilct < CSCConstants::MAX_CLCTS_PER_PROCESSOR; ilct++) {
0184         best_halfstrip[ilct] = -1;
0185         best_quality[ilct] = 0;
0186       }
0187 
0188       bool pretrig_zone[CSCConstants::MAX_NUM_HALF_STRIPS_RUN2_TRIGGER];
0189 
0190       // Calculate quality from pattern id and number of hits, and
0191       // simultaneously select best-quality CLCT.
0192       if (hits_in_time) {
0193         // first, mark half-strip zones around pretriggers
0194         // that happened at the current first_bx
0195         markPreTriggerZone(first_bx, pretrig_zone);
0196 
0197         for (int hstrip = stagger[CSCConstants::KEY_CLCT_LAYER - 1]; hstrip < numHalfStrips_; hstrip++) {
0198           /* The bend-direction bit pid[0] is ignored (left and right bends have equal quality).
0199            This works both for the Run-2 patterns
0200            - PID 2,3: 2 & 14 == 2, 3 & 14 == 2
0201            - PID 4,5: 4 & 14 == 4, 3 & 14 == 4
0202            - PID 6,7: 6 & 14 == 6, 3 & 14 == 6
0203            - PID 8,9: 8 & 14 == 8, 3 & 14 == 8
0204            - PID 10: 10 & 14 == 10
0205            It also works for the Run-3 patterns:
0206            - PID 0,1: 0 & 14 == 0, 1 & 14 == 0
0207            - PID 2,3: 2 & 14 == 2, 3 & 14 == 2
0208            - PID  4:  4 & 14 == 4
0209           */
0210           quality[hstrip] = (best_pid[hstrip] & 14) | (nhits[hstrip] << 5);
0211           // do not consider halfstrips:
0212           // - out of pretrigger-trigger zones
0213           // - in busy zones from previous trigger
0214           if (quality[hstrip] > best_quality[0] && pretrig_zone[hstrip] && !busyMap_[hstrip][first_bx]) {
0215             best_halfstrip[0] = hstrip;
0216             best_quality[0] = quality[hstrip];
0217             // temporary alias
0218             const int best_hs(best_halfstrip[0]);
0219             const int best_pat(best_pid[best_hs]);
0220             // construct a CLCT if the trigger condition has been met
0221             if (best_hs >= 0 && nhits[best_hs] >= nplanes_hit_pattern) {
0222               // overwrite the current best CLCT
0223               tempBestCLCT = constructCLCT(first_bx, best_hs, hits_in_patterns[best_hs][best_pat], lookupTable);
0224             }
0225           }
0226         }
0227       }
0228 
0229       // If 1st best CLCT is found, look for the 2nd best.
0230       if (best_halfstrip[0] >= 0) {
0231         // Get the half-strip of the best CLCT in this BX that was put into the list.
0232         // You do need to re-add the any stagger, because the busy keys are based on
0233         // the pulse array which takes into account strip stagger!!!
0234         const unsigned halfStripBestCLCT(tempBestCLCT.getKeyStrip() + stagger[CSCConstants::KEY_CLCT_LAYER - 1]);
0235 
0236         // Mark keys near best CLCT as busy by setting their quality to
0237         // zero, and repeat the search.
0238         //markBusyKeys(best_halfstrip[0], best_pid[best_halfstrip[0]], quality);
0239         markBusyKeys(halfStripBestCLCT, best_pid[halfStripBestCLCT], quality);
0240 
0241         for (int hstrip = stagger[CSCConstants::KEY_CLCT_LAYER - 1]; hstrip < numHalfStrips_; hstrip++) {
0242           // we don't have to recalculate the quality for each half-strip
0243           if (quality[hstrip] > best_quality[1] && pretrig_zone[hstrip] && !busyMap_[hstrip][first_bx]) {
0244             best_halfstrip[1] = hstrip;
0245             best_quality[1] = quality[hstrip];
0246             // temporary alias
0247             const int best_hs(best_halfstrip[1]);
0248             const int best_pat(best_pid[best_hs]);
0249             // construct a CLCT if the trigger condition has been met
0250             if (best_hs >= 0 && nhits[best_hs] >= nplanes_hit_pattern) {
0251               // overwrite the current second best CLCT
0252               tempSecondCLCT = constructCLCT(first_bx, best_hs, hits_in_patterns[best_hs][best_pat], lookupTable);
0253             }
0254           }
0255         }
0256 
0257         // Sort bestCLCT and secondALCT by quality
0258         // if qualities are the same, sort by run-2 or run-3 pattern
0259         // if qualities and patterns are the same, sort by half strip number
0260         bool changeOrder = false;
0261 
0262         unsigned qualityBest = 0, qualitySecond = 0;
0263         unsigned patternBest = 0, patternSecond = 0;
0264         unsigned halfStripBest = 0, halfStripSecond = 0;
0265 
0266         if (tempBestCLCT.isValid() and tempSecondCLCT.isValid()) {
0267           qualityBest = tempBestCLCT.getQuality();
0268           qualitySecond = tempSecondCLCT.getQuality();
0269           if (!run3_) {
0270             patternBest = tempBestCLCT.getPattern();
0271             patternSecond = tempSecondCLCT.getPattern();
0272           } else {
0273             patternBest = tempBestCLCT.getRun3Pattern();
0274             patternSecond = tempSecondCLCT.getRun3Pattern();
0275           }
0276           halfStripBest = tempBestCLCT.getKeyStrip();
0277           halfStripSecond = tempSecondCLCT.getKeyStrip();
0278 
0279           if (qualitySecond > qualityBest)
0280             changeOrder = true;
0281           else if ((qualitySecond == qualityBest) and (int(patternSecond / 2) > int(patternBest / 2)))
0282             changeOrder = true;
0283           else if ((qualitySecond == qualityBest) and (int(patternSecond / 2) == int(patternBest / 2)) and
0284                    (halfStripSecond < halfStripBest))
0285             changeOrder = true;
0286         }
0287 
0288         CSCCLCTDigi tempCLCT;
0289         if (changeOrder) {
0290           tempCLCT = tempBestCLCT;
0291           tempBestCLCT = tempSecondCLCT;
0292           tempSecondCLCT = tempCLCT;
0293         }
0294 
0295         // add the CLCTs to the collection
0296         if (tempBestCLCT.isValid()) {
0297           lctList.push_back(tempBestCLCT);
0298         }
0299         if (tempSecondCLCT.isValid()) {
0300           lctList.push_back(tempSecondCLCT);
0301         }
0302       }  //find CLCT, end of best_halfstrip[0] >= 0
0303     }  //pre_trig
0304     // The pattern finder runs continuously, so another pre-trigger
0305     // could occur already at the next bx.
0306     start_bx = first_bx + 1;
0307   }
0308   return lctList;
0309 }  // findLCTs -- Phase2 version.
0310 
0311 void CSCUpgradeCathodeLCTProcessor::markPreTriggerZone(
0312     int bx, bool pretrig_zone[CSCConstants::MAX_NUM_HALF_STRIPS_RUN2_TRIGGER]) const {
0313   // first reset the pretrigger zone (no pretriggers anywhere in this BX
0314   for (int hstrip = 0; hstrip < CSCConstants::MAX_NUM_HALF_STRIPS_RUN2_TRIGGER; hstrip++) {
0315     pretrig_zone[hstrip] = false;
0316   }
0317   // then set the pretrigger zone according to the ispretrig_ array
0318   for (int hstrip = 0; hstrip < CSCConstants::MAX_NUM_HALF_STRIPS_RUN2_TRIGGER; hstrip++) {
0319     if (ispretrig_[hstrip] && !busyMap_[hstrip][bx]) {
0320       int min_hs = hstrip - pretrig_trig_zone_;
0321       int max_hs = hstrip + pretrig_trig_zone_;
0322       // set the minimum strip
0323       if (min_hs < 0)
0324         min_hs = 0;
0325       // set the maximum strip
0326       if (max_hs > CSCConstants::MAX_NUM_HALF_STRIPS_RUN2_TRIGGER - 1)
0327         max_hs = CSCConstants::MAX_NUM_HALF_STRIPS_RUN2_TRIGGER - 1;
0328       // mark the pre-trigger zone
0329       for (int hs = min_hs; hs <= max_hs; hs++)
0330         pretrig_zone[hs] = true;
0331       if (infoV > 1)
0332         LogTrace("CSCUpgradeCathodeLCTProcessor")
0333             << " marked pretrigger halfstrip zone [" << min_hs << "," << max_hs << "]";
0334     }
0335   }
0336 }
0337 
0338 void CSCUpgradeCathodeLCTProcessor::markBusyZone(const int bx) {
0339   for (int hstrip = stagger[CSCConstants::KEY_CLCT_LAYER - 1]; hstrip < numHalfStrips_; hstrip++) {
0340     // check if this halfstrip has a pretrigger
0341     if (ispretrig_[hstrip]) {
0342       // only fixed localized dead time zone is implemented in firmware
0343       int min_hstrip = hstrip - clct_state_machine_zone_;
0344       int max_hstrip = hstrip + clct_state_machine_zone_;
0345       // set the minimum strip
0346       if (min_hstrip < stagger[CSCConstants::KEY_CLCT_LAYER - 1])
0347         min_hstrip = stagger[CSCConstants::KEY_CLCT_LAYER - 1];
0348       // set the maximum strip
0349       if (max_hstrip >= numHalfStrips_)
0350         max_hstrip = numHalfStrips_ - 1;
0351       // mask the busy half-strips for 1 BX after the pretrigger
0352       for (int hs = min_hstrip; hs <= max_hstrip; hs++)
0353         busyMap_[hs][bx + 1] = true;
0354       if (infoV > 1)
0355         LogTrace("CSCUpgradeCathodeLCTProcessor")
0356             << " marked zone around pretriggerred halfstrip " << hstrip << " as dead zone for pretriggering at bx"
0357             << bx + 1 << " halfstrip: [" << min_hstrip << "," << max_hstrip << "]";
0358     }
0359   }
0360 }