CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_6_1_1/src/L1Trigger/CSCTriggerPrimitives/src/CSCCathodeLCTProcessor.cc

Go to the documentation of this file.
00001 //-----------------------------------------------------------------------------
00002 //
00003 //   Class: CSCCathodeLCTProcessor
00004 //
00005 //   Description: 
00006 //     This class simulates the functionality of the cathode LCT card.  It is
00007 //     run by the MotherBoard and returns up to two CathodeLCTs. It can be
00008 //     run either in a test mode, where it is passed arrays of halfstrip
00009 //     and distrip times, or in normal mode where it determines
00010 //     the time and comparator information from the comparator digis.
00011 //
00012 //     Additional comments by Jason Mumford 01/31/01 (mumford@physics.ucla.edu)
00013 //     Removed the card boundaries.  Changed the Pretrigger to emulate
00014 //     the hardware electronic logic.  Also changed the keylayer to be the 4th
00015 //     layer in a chamber instead of the 3rd layer from the interaction region.
00016 //     The code is a more realistic simulation of hardware LCT logic now.
00017 //
00018 //   Author List: Benn Tannenbaum (1999), Jason Mumford (2001-2), Slava Valuev.
00019 //                Porting from ORCA by S. Valuev (Slava.Valuev@cern.ch),
00020 //                May 2006.
00021 //
00022 //   $Id: CSCCathodeLCTProcessor.cc,v 1.48 2012/12/05 21:14:22 khotilov Exp $
00023 //
00024 //   Modifications: 
00025 //
00026 //-----------------------------------------------------------------------------
00027 
00028 #include <L1Trigger/CSCTriggerPrimitives/src/CSCCathodeLCTProcessor.h>
00029 #include <L1Trigger/CSCCommonTrigger/interface/CSCTriggerGeometry.h>
00030 #include <DataFormats/MuonDetId/interface/CSCTriggerNumbering.h>
00031 
00032 #include <FWCore/MessageLogger/interface/MessageLogger.h>
00033 #include <algorithm>
00034 #include <iomanip>
00035 #include <iostream>
00036 #include <set>
00037 
00038 //-----------------
00039 // Static variables
00040 //-----------------
00041 
00042 // This is the strip pattern that we use for pretrigger.
00043 // pre_hit_pattern[0][i] = layer. pre_hit_pattern[1][i] = key_strip offset.
00044 const int CSCCathodeLCTProcessor::pre_hit_pattern[2][NUM_PATTERN_STRIPS] = {
00045   { 999,  0,  0,  0,  999,
00046     999,  1,  1,  1,  999,
00047     999,  2,  2,  2,  999,
00048               3,                // layer
00049     999,  4,  4,  4,  999,
00050     999,  5,  5,  5,  999},
00051   //-------------------------------------------
00052   { 999, -1,  0,  1,  999,
00053     999, -1,  0,  1,  999,
00054     999, -1,  0,  1,  999,
00055               0,                // offset
00056     999, -1,  0,  1,  999,
00057     999, -1,  0,  1,  999}
00058 };
00059 
00060 // The old set of half-strip/di-strip patterns used prior to 2007.
00061 // For the given pattern, set the unused parts of the pattern to 999.
00062 // Pattern[i][NUM_PATTERN_STRIPS] contains pt bend value. JM
00063 // bend of 0 is left/straight and bend of 1 is right bht 21 June 2001
00064 // note that the left/right-ness of this is exactly opposite of what one would
00065 // expect naively (at least it was for me). The only way to make sure you've
00066 // got the patterns you want is to use the printPatterns() method to dump
00067 // them. BHT 21 June 2001
00068 const int CSCCathodeLCTProcessor::pattern[CSCConstants::NUM_CLCT_PATTERNS_PRE_TMB07][NUM_PATTERN_STRIPS+1] = {
00069   { 999, 999, 999, 999, 999,
00070     999, 999, 999, 999, 999,
00071     999, 999, 999, 999, 999,
00072               999,            // dummy (reserved)
00073     999, 999, 999, 999, 999,
00074     999, 999, 999, 999, 999, 0},
00075   //-------------------------------------------------------------
00076   { 999, 999, 999,   0, 999,
00077     999, 999, 999,   1, 999,
00078     999, 999,   2,   2, 999,
00079                 3,            // right bending pattern (large)
00080     999,   4,   4, 999, 999,
00081     999,   5, 999, 999, 999, 1},
00082   //-------------------------------------------------------------
00083   { 999,   0, 999, 999, 999,
00084     999,   1, 999, 999, 999,
00085     999,   2,   2, 999, 999,
00086                 3,            // left bending pattern (large)
00087     999, 999,   4,   4, 999,
00088     999, 999, 999,   5, 999, 0},
00089   //-------------------------------------------------------------
00090   { 999, 999,   0, 999, 999,
00091     999, 999,   1, 999, 999,
00092     999, 999,   2, 999, 999,
00093                 3,            // right bending pattern (medium)
00094     999,   4, 999, 999, 999,
00095     999,   5, 999, 999, 999, 1},
00096   //-------------------------------------------------------------
00097   { 999, 999,   0, 999, 999,
00098     999, 999,   1, 999, 999,
00099     999, 999,   2, 999, 999,
00100                 3,            // left bending pattern (medium)
00101     999, 999, 999,   4, 999,
00102     999, 999, 999,   5, 999, 0},
00103   //-------------------------------------------------------------
00104   { 999, 999, 999,   0, 999,
00105     999, 999, 999,   1, 999,
00106     999, 999,   2,   2, 999,
00107                 3,            // right bending pattern (small)
00108     999, 999,   4, 999, 999,
00109     999, 999,   5, 999, 999, 1},
00110   //-------------------------------------------------------------
00111   { 999,   0, 999, 999, 999,
00112     999,   1, 999, 999, 999,
00113     999,   2,   2, 999, 999,
00114                 3,            // left bending pattern (small)
00115     999, 999,   4, 999, 999,
00116     999, 999,   5, 999, 999, 0},
00117   //-------------------------------------------------------------
00118   { 999, 999,   0, 999, 999,
00119     999, 999,   1, 999, 999,
00120     999, 999,   2, 999, 999,
00121                 3,            // straight through pattern
00122     999, 999,   4, 999, 999,
00123     999, 999,   5, 999, 999, 1}
00124 };
00125 
00126 // New set of halfstrip patterns for 2007 version of the algorithm.
00127 // For the given pattern, set the unused parts of the pattern to 999.
00128 // Pattern[i][NUM_PATTERN_HALFSTRIPS] contains bend direction.
00129 // Bend of 0 is right/straight and bend of 1 is left.
00130 // Pattern[i][NUM_PATTERN_HALFSTRIPS+1] contains pattern maximum width
00131 const int CSCCathodeLCTProcessor::pattern2007_offset[NUM_PATTERN_HALFSTRIPS] =
00132   {  -5,  -4,  -3,  -2,  -1,   0,   1,   2,   3,   4,   5,
00133                     -2,  -1,   0,   1,   2,
00134                                0,
00135                     -2,  -1,   0,   1,   2,
00136           -4,  -3,  -2,  -1,   0,   1,   2,   3,   4,
00137      -5,  -4,  -3,  -2,  -1,   0,   1,   2,   3,   4,   5 };
00138 
00139 const int CSCCathodeLCTProcessor::pattern2007[CSCConstants::NUM_CLCT_PATTERNS][NUM_PATTERN_HALFSTRIPS+2] = {
00140   { 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999,
00141                    999, 999, 999, 999, 999,
00142                              999,             // pid=0: no pattern found
00143                    999, 999, 999, 999, 999,
00144          999, 999, 999, 999, 999, 999, 999, 999, 999,
00145     999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, -1, 0},
00146   //-------------------------------------------------------------
00147   {   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
00148                      1,   1,   1,   1,   1,
00149                                2,             // pid=1: layer-OR trigger
00150                      3,   3,   3,   3,   3,
00151            4,   4,   4,   4,   4,   4,   4,   4,   4,
00152       5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5, -1, 11},
00153   //-------------------------------------------------------------
00154   { 999, 999, 999, 999, 999, 999, 999, 999,   0,   0,   0,
00155                    999, 999, 999,   1,   1,
00156                                2,             // pid=2: right-bending (large)
00157                      3,   3,   3, 999, 999,
00158            4,   4,   4, 999, 999, 999, 999, 999, 999,
00159       5,   5,   5, 999, 999, 999, 999, 999, 999, 999, 999,  0, 11},
00160   //-------------------------------------------------------------
00161   {   0,   0,   0, 999, 999, 999, 999, 999, 999, 999, 999,
00162                      1,   1, 999, 999, 999,
00163                                2,             // pid=3: left-bending (large)
00164                    999, 999,   3,   3,   3,
00165          999, 999, 999, 999, 999, 999,   4,   4,   4,
00166     999, 999, 999, 999, 999, 999, 999, 999,   5,   5,   5,  1, 11},
00167   //-------------------------------------------------------------
00168   { 999, 999, 999, 999, 999, 999, 999,   0,   0,   0, 999,
00169                    999, 999, 999,   1,   1,
00170                                2,             // pid=4: right-bending (medium)
00171                      3,   3, 999, 999, 999,
00172            4,   4,   4, 999, 999, 999, 999, 999, 999,
00173     999,   5,   5,   5, 999, 999, 999, 999, 999, 999, 999,  0, 9},
00174   //-------------------------------------------------------------
00175   { 999,   0,   0,   0, 999, 999, 999, 999, 999, 999, 999,
00176                      1,   1, 999, 999, 999,
00177                                2,             // pid=5: left-bending (medium)
00178                    999, 999, 999,   3,   3,
00179          999, 999, 999, 999, 999, 999,   4,   4,   4,
00180     999, 999, 999, 999, 999, 999, 999,   5,   5,   5, 999,  1, 9},
00181   //-------------------------------------------------------------
00182   { 999, 999, 999, 999, 999, 999,   0,   0,   0, 999, 999,
00183                    999, 999,   1,   1, 999,
00184                                2,             // pid=6: right-bending (medium)
00185                    999,   3,   3, 999, 999,
00186          999, 999,   4,   4, 999, 999, 999, 999, 999,
00187     999, 999,   5,   5,   5, 999, 999, 999, 999, 999, 999,  0, 7},
00188   //-------------------------------------------------------------
00189   { 999, 999,   0,   0,   0, 999, 999, 999, 999, 999, 999,
00190                    999,   1,   1, 999, 999,
00191                                2,             // pid=7: left-bending (medium)
00192                    999, 999,   3,   3, 999,
00193          999, 999, 999, 999, 999,   4,   4, 999, 999,
00194     999, 999, 999, 999, 999, 999,   5,   5,   5, 999, 999,  1, 7},
00195   //-------------------------------------------------------------
00196   { 999, 999, 999, 999, 999,   0,   0,   0, 999, 999, 999,
00197                    999, 999,   1,   1, 999,
00198                                2,             // pid=8: right-bending (small)
00199                    999,   3,   3, 999, 999,
00200          999, 999,   4,   4,   4, 999, 999, 999, 999,
00201     999, 999, 999,   5,   5,   5, 999, 999, 999, 999, 999,  0, 5},
00202   //-------------------------------------------------------------
00203   { 999, 999, 999,   0,   0,   0, 999, 999, 999, 999, 999,
00204                    999,   1,   1, 999, 999,
00205                                2,             // pid=9: left-bending (small)
00206                    999, 999,   3,   3, 999,
00207          999, 999, 999, 999,   4,   4,   4, 999, 999,
00208     999, 999, 999, 999, 999,   5,   5,   5, 999, 999, 999,  1, 5},
00209   //-------------------------------------------------------------
00210   { 999, 999, 999, 999,   0,   0,   0, 999, 999, 999, 999,
00211                    999, 999,   1, 999, 999,
00212                                2,             // pid=A: straight-through
00213                    999, 999,   3, 999, 999,
00214          999, 999, 999,   4,   4,   4, 999, 999, 999,
00215     999, 999, 999, 999,   5,   5,   5, 999, 999, 999, 999,  0, 3}
00216                                               // pid's=B-F are not yet defined
00217 };
00218 
00219 // Default values of configuration parameters.
00220 const unsigned int CSCCathodeLCTProcessor::def_fifo_tbins   = 12;
00221 const unsigned int CSCCathodeLCTProcessor::def_fifo_pretrig =  7;
00222 const unsigned int CSCCathodeLCTProcessor::def_hit_persist  =  6;
00223 const unsigned int CSCCathodeLCTProcessor::def_drift_delay  =  2;
00224 const unsigned int CSCCathodeLCTProcessor::def_nplanes_hit_pretrig =  2;
00225 const unsigned int CSCCathodeLCTProcessor::def_nplanes_hit_pattern =  4;
00226 const unsigned int CSCCathodeLCTProcessor::def_pid_thresh_pretrig  =  2;
00227 const unsigned int CSCCathodeLCTProcessor::def_min_separation      = 10;
00228 const unsigned int CSCCathodeLCTProcessor::def_tmb_l1a_window_size =  7;
00229 
00230 // Number of di-strips/half-strips per CFEB.
00231 const int CSCCathodeLCTProcessor::cfeb_strips[2] = { 8, 32};
00232 
00233 //----------------
00234 // Constructors --
00235 //----------------
00236 
00237 CSCCathodeLCTProcessor::CSCCathodeLCTProcessor(unsigned endcap,
00238                                                unsigned station,
00239                                                unsigned sector,
00240                                                unsigned subsector,
00241                                                unsigned chamber,
00242                                                const edm::ParameterSet& conf,
00243                                                const edm::ParameterSet& comm,
00244                                                const edm::ParameterSet& ctmb) :
00245                      theEndcap(endcap), theStation(station), theSector(sector),
00246                      theSubsector(subsector), theTrigChamber(chamber) {
00247   static bool config_dumped = false;
00248 
00249   // CLCT configuration parameters.
00250   fifo_tbins   = conf.getParameter<unsigned int>("clctFifoTbins");
00251   hit_persist  = conf.getParameter<unsigned int>("clctHitPersist");
00252   drift_delay  = conf.getParameter<unsigned int>("clctDriftDelay");
00253   nplanes_hit_pretrig =
00254     conf.getParameter<unsigned int>("clctNplanesHitPretrig");
00255   nplanes_hit_pattern =
00256     conf.getParameter<unsigned int>("clctNplanesHitPattern");
00257 
00258   // Not used yet.
00259   fifo_pretrig = conf.getParameter<unsigned int>("clctFifoPretrig");
00260 
00261   // Defines pre-2007 version of the CLCT algorithm used in test beams and
00262   // MTCC.
00263   isMTCC       = comm.getParameter<bool>("isMTCC");
00264 
00265   // TMB07 firmware used since 2007: switch and config. parameters.
00266   isTMB07      = comm.getParameter<bool>("isTMB07");
00267 
00268   // Flag for SLHC studies
00269   isSLHC       = comm.getUntrackedParameter<bool>("isSLHC",false);
00270 
00271   // special configuration parameters for ME11 treatment
00272   smartME1aME1b = comm.getUntrackedParameter<bool>("smartME1aME1b",false);
00273   disableME1a = comm.getUntrackedParameter<bool>("disableME1a",false);
00274   gangedME1a = comm.getUntrackedParameter<bool>("gangedME1a",true);
00275 
00276   if (isSLHC && !smartME1aME1b) edm::LogError("L1CSCTPEmulatorConfigError")
00277     << "+++ SLHC upgrade configuration is used (isSLHC=True) but smartME1aME1b=False!\n"
00278     << "Only smartME1aME1b algorithm is so far supported for upgrade! +++\n";
00279 
00280   if (isTMB07) {
00281     pid_thresh_pretrig =
00282       conf.getParameter<unsigned int>("clctPidThreshPretrig");
00283     min_separation    =
00284       conf.getParameter<unsigned int>("clctMinSeparation");
00285 
00286     start_bx_shift = conf.getUntrackedParameter<int>("clctStartBxShift",0);
00287   }
00288 
00289   if (smartME1aME1b) {
00290     // use of localized dead-time zones
00291     use_dead_time_zoning = 
00292       conf.getUntrackedParameter<bool>("useDeadTimeZoning",true);
00293     clct_state_machine_zone = 
00294       conf.getUntrackedParameter<unsigned int>("clctStateMachineZone",8);
00295     dynamic_state_machine_zone = 
00296       conf.getUntrackedParameter<bool>("useDynamicStateMachineZone",true);
00297 
00298     // how far away may trigger happen from pretrigger
00299     pretrig_trig_zone = 
00300       conf.getUntrackedParameter<unsigned int>("clctPretriggerTriggerZone",5);
00301 
00302     // whether to calculate bx as corrected_bx instead of pretrigger one
00303     use_corrected_bx = conf.getUntrackedParameter<bool>("clctUseCorrectedBx",false);
00304   }
00305   
00306   // Motherboard parameters: common for all configurations.
00307   tmb_l1a_window_size = // Common to CLCT and TMB
00308     ctmb.getParameter<unsigned int>("tmbL1aWindowSize");
00309 
00310   // separate handle for early time bins
00311   early_tbins = ctmb.getUntrackedParameter<int>("tmbEarlyTbins",-1);
00312   static int fpga_latency = 3;
00313   if (early_tbins<0) early_tbins  = fifo_pretrig - fpga_latency;
00314 
00315   // wether to readout only the earliest two LCTs in readout window
00316   readout_earliest_2 = ctmb.getUntrackedParameter<bool>("tmbReadoutEarliest2",0);
00317 
00318   // Verbosity level, set to 0 (no print) by default.
00319   infoV        = conf.getUntrackedParameter<int>("verbosity", 0);
00320 
00321   // Check and print configuration parameters.
00322   checkConfigParameters();
00323   if ((infoV > 0 || isSLHC) && !config_dumped) {
00324     //std::cerr<<"**** CLCT constructor parameters dump ****"<<std::endl;
00325     dumpConfigParams();
00326     config_dumped = true;
00327   }
00328 
00329   numStrips = 0; // Will be set later.
00330   // Provisional, but should be OK for all stations except ME1.
00331   for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
00332     if ((i_layer+1)%2 == 0) stagger[i_layer] = 0;
00333     else                    stagger[i_layer] = 1;
00334   }
00335 
00336   theRing = CSCTriggerNumbering::ringFromTriggerLabels(theStation, theTrigChamber);
00337 
00338   theChamber = CSCTriggerNumbering::chamberFromTriggerLabels(theSector, theSubsector,
00339                                                              theStation, theTrigChamber);
00340 
00341   // trigger numbering doesn't distinguish between ME1a and ME1b chambers:
00342   isME11 = (theStation == 1 && theRing == 1);
00343 
00344   //if (theStation==1 && theRing==2) infoV = 3;
00345 
00347   //if (theStation == 2 && theSector == 1 &&
00348   //    theRing == 1 &&
00349   //    theChamber == 1) {
00351   //  testPatterns();
00353   //  testLCTs();
00355   //  printPatterns();
00356   //}
00357 }
00358 
00359 CSCCathodeLCTProcessor::CSCCathodeLCTProcessor() :
00360                      theEndcap(1), theStation(1), theSector(1),
00361                      theSubsector(1), theTrigChamber(1) {
00362   // constructor for debugging.
00363   static bool config_dumped = false;
00364 
00365   // CLCT configuration parameters.
00366   setDefaultConfigParameters();
00367   infoV =  2;
00368   isMTCC  = false;
00369   isTMB07 = true;
00370 
00371   smartME1aME1b = false;
00372   disableME1a = false;
00373   gangedME1a = true;
00374 
00375   early_tbins = 4;
00376 
00377   start_bx_shift = 0;
00378   use_dead_time_zoning = 1;
00379   clct_state_machine_zone = 8;
00380   
00381   // Check and print configuration parameters.
00382   checkConfigParameters();
00383   if (!config_dumped) {
00384     //std::cerr<<"**** CLCT default constructor parameters dump ****"<<std::endl;
00385     dumpConfigParams();
00386     config_dumped = true;
00387   }
00388 
00389   numStrips = CSCConstants::MAX_NUM_STRIPS;
00390   // Should be OK for all stations except ME1.
00391   for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
00392     if ((i_layer+1)%2 == 0) stagger[i_layer] = 0;
00393     else                    stagger[i_layer] = 1;
00394   }
00395   
00396   theRing = CSCTriggerNumbering::ringFromTriggerLabels(theStation, theTrigChamber);
00397   isME11 = (theStation == 1 && theRing == 1);
00398 }
00399 
00400 void CSCCathodeLCTProcessor::setDefaultConfigParameters() {
00401   // Set default values for configuration parameters.
00402   fifo_tbins   = def_fifo_tbins;
00403   fifo_pretrig = def_fifo_pretrig;
00404   hit_persist  = def_hit_persist;
00405   drift_delay  = def_drift_delay;
00406   nplanes_hit_pretrig = def_nplanes_hit_pretrig;
00407   nplanes_hit_pattern = def_nplanes_hit_pattern;
00408 
00409   isMTCC = false;
00410 
00411   // New TMB07 parameters.
00412   isTMB07 = true;
00413   if (isTMB07) {
00414     pid_thresh_pretrig = def_pid_thresh_pretrig;
00415     min_separation     = def_min_separation;
00416   }
00417 
00418   tmb_l1a_window_size = def_tmb_l1a_window_size;
00419 }
00420 
00421 // Set configuration parameters obtained via EventSetup mechanism.
00422 void CSCCathodeLCTProcessor::setConfigParameters(const CSCDBL1TPParameters* conf) {
00423   static bool config_dumped = false;
00424 
00425   fifo_tbins   = conf->clctFifoTbins();
00426   fifo_pretrig = conf->clctFifoPretrig();
00427   hit_persist  = conf->clctHitPersist();
00428   drift_delay  = conf->clctDriftDelay();
00429   nplanes_hit_pretrig = conf->clctNplanesHitPretrig();
00430   nplanes_hit_pattern = conf->clctNplanesHitPattern();
00431 
00432   // TMB07 parameters.
00433   if (isTMB07) {
00434     pid_thresh_pretrig = conf->clctPidThreshPretrig();
00435     min_separation     = conf->clctMinSeparation();
00436   }
00437 
00438   // Check and print configuration parameters.
00439   checkConfigParameters();
00440   if (!config_dumped) {
00441     //std::cerr<<"**** CLCT setConfigParams parameters dump ****"<<std::endl;
00442     dumpConfigParams();
00443     config_dumped = true;
00444   }
00445 }
00446 
00447 void CSCCathodeLCTProcessor::checkConfigParameters() {
00448   // Make sure that the parameter values are within the allowed range.
00449 
00450   // Max expected values.
00451   static const unsigned int max_fifo_tbins   = 1 << 5;
00452   static const unsigned int max_fifo_pretrig = 1 << 5;
00453   static const unsigned int max_hit_persist  = 1 << 4;
00454   static const unsigned int max_drift_delay  = 1 << 2;
00455   static const unsigned int max_nplanes_hit_pretrig = 1 << 3;
00456   static const unsigned int max_nplanes_hit_pattern = 1 << 3;
00457   static const unsigned int max_pid_thresh_pretrig  = 1 << 4;
00458   static const unsigned int max_min_separation = CSCConstants::NUM_HALF_STRIPS;
00459   static const unsigned int max_tmb_l1a_window_size = 1 << 4;
00460 
00461   // Checks.
00462   if (fifo_tbins >= max_fifo_tbins) {
00463     if (infoV >= 0) edm::LogError("L1CSCTPEmulatorConfigError")
00464       << "+++ Value of fifo_tbins, " << fifo_tbins
00465       << ", exceeds max allowed, " << max_fifo_tbins-1 << " +++\n"
00466       << "+++ Try to proceed with the default value, fifo_tbins="
00467       << def_fifo_tbins << " +++\n";
00468     fifo_tbins = def_fifo_tbins;
00469   }
00470   if (fifo_pretrig >= max_fifo_pretrig) {
00471     if (infoV >= 0) edm::LogError("L1CSCTPEmulatorConfigError")
00472       << "+++ Value of fifo_pretrig, " << fifo_pretrig
00473       << ", exceeds max allowed, " << max_fifo_pretrig-1 << " +++\n"
00474       << "+++ Try to proceed with the default value, fifo_pretrig="
00475       << def_fifo_pretrig << " +++\n";
00476     fifo_pretrig = def_fifo_pretrig;
00477   }
00478   if (hit_persist >= max_hit_persist) {
00479     if (infoV >= 0) edm::LogError("L1CSCTPEmulatorConfigError")
00480       << "+++ Value of hit_persist, " << hit_persist
00481       << ", exceeds max allowed, " << max_hit_persist-1 << " +++\n"
00482       << "+++ Try to proceed with the default value, hit_persist="
00483       << def_hit_persist << " +++\n";
00484     hit_persist = def_hit_persist;
00485   }
00486   if (drift_delay >= max_drift_delay) {
00487     if (infoV >= 0) edm::LogError("L1CSCTPEmulatorConfigError")
00488       << "+++ Value of drift_delay, " << drift_delay
00489       << ", exceeds max allowed, " << max_drift_delay-1 << " +++\n"
00490       << "+++ Try to proceed with the default value, drift_delay="
00491       << def_drift_delay << " +++\n";
00492     drift_delay = def_drift_delay;
00493   }
00494   if (nplanes_hit_pretrig >= max_nplanes_hit_pretrig) {
00495     if (infoV >= 0) edm::LogError("L1CSCTPEmulatorConfigError")
00496       << "+++ Value of nplanes_hit_pretrig, " << nplanes_hit_pretrig
00497       << ", exceeds max allowed, " << max_nplanes_hit_pretrig-1 << " +++\n"
00498       << "+++ Try to proceed with the default value, nplanes_hit_pretrig="
00499       << def_nplanes_hit_pretrig << " +++\n";
00500     nplanes_hit_pretrig = def_nplanes_hit_pretrig;
00501   }
00502   if (nplanes_hit_pattern >= max_nplanes_hit_pattern) {
00503     if (infoV >= 0) edm::LogError("L1CSCTPEmulatorConfigError")
00504       << "+++ Value of nplanes_hit_pattern, " << nplanes_hit_pattern
00505       << ", exceeds max allowed, " << max_nplanes_hit_pattern-1 << " +++\n"
00506       << "+++ Try to proceed with the default value, nplanes_hit_pattern="
00507       << def_nplanes_hit_pattern << " +++\n";
00508     nplanes_hit_pattern = def_nplanes_hit_pattern;
00509   }
00510 
00511   if (isTMB07) {
00512     if (pid_thresh_pretrig >= max_pid_thresh_pretrig) {
00513       if (infoV >= 0) edm::LogError("L1CSCTPEmulatorConfigError")
00514         << "+++ Value of pid_thresh_pretrig, " << pid_thresh_pretrig
00515         << ", exceeds max allowed, " << max_pid_thresh_pretrig-1 << " +++\n"
00516         << "+++ Try to proceed with the default value, pid_thresh_pretrig="
00517         << def_pid_thresh_pretrig << " +++\n";
00518       pid_thresh_pretrig = def_pid_thresh_pretrig;
00519     }
00520     if (min_separation >= max_min_separation) {
00521       if (infoV >= 0) edm::LogError("L1CSCTPEmulatorConfigError")
00522         << "+++ Value of min_separation, " << min_separation
00523         << ", exceeds max allowed, " << max_min_separation-1 << " +++\n"
00524         << "+++ Try to proceed with the default value, min_separation="
00525         << def_min_separation << " +++\n";
00526       min_separation = def_min_separation;
00527     }
00528   }
00529   
00530   if (tmb_l1a_window_size >= max_tmb_l1a_window_size) {
00531     if (infoV > 0) edm::LogError("L1CSCTPEmulatorConfigError")
00532       << "+++ Value of tmb_l1a_window_size, " << tmb_l1a_window_size
00533       << ", exceeds max allowed, " << max_tmb_l1a_window_size-1 << " +++\n"
00534       << "+++ Try to proceed with the default value, tmb_l1a_window_size="
00535       << def_tmb_l1a_window_size << " +++\n";
00536     tmb_l1a_window_size = def_tmb_l1a_window_size;
00537   }
00538 }
00539 
00540 void CSCCathodeLCTProcessor::clear() {
00541   thePreTriggerBXs.clear();
00542   for (int bx = 0; bx < MAX_CLCT_BINS; bx++) {
00543     bestCLCT[bx].clear();
00544     secondCLCT[bx].clear();
00545   }
00546 }
00547 
00548 std::vector<CSCCLCTDigi>
00549 CSCCathodeLCTProcessor::run(const CSCComparatorDigiCollection* compdc) {
00550   // This is the version of the run() function that is called when running
00551   // over the entire detector.  It gets the comparator & timing info from the
00552   // comparator digis and then passes them on to another run() function.
00553 
00554   // clear(); // redundant; called by L1MuCSCMotherboard.
00555 
00556   static bool config_dumped = false;
00557   if ((infoV > 0 || isSLHC) && !config_dumped) {
00558     //std::cerr<<"**** CLCT run parameters dump ****"<<std::endl;
00559     dumpConfigParams();
00560     config_dumped = true;
00561   }
00562 
00563   // Get the number of strips and stagger of layers for the given chamber.
00564   // Do it only once per chamber.
00565   if (numStrips == 0) {
00566     CSCTriggerGeomManager* theGeom = CSCTriggerGeometry::get();
00567     CSCChamber* chamber = theGeom->chamber(theEndcap, theStation, theSector,
00568                                               theSubsector, theTrigChamber);
00569     if (chamber) {
00570       numStrips = chamber->layer(1)->geometry()->numberOfStrips();
00571       // ME1/a is known to the readout hardware as strips 65-80 of ME1/1.
00572       // Still need to decide whether we do any special adjustments to
00573       // reconstruct LCTs in this region (3:1 ganged strips); for now, we
00574       // simply allow for hits in ME1/a and apply standard reconstruction
00575       // to them.
00576       // For SLHC ME1/1 is set to have 4 CFEBs in ME1/b and 3 CFEBs in ME1/a
00577       if (isME11) {
00578         if (!smartME1aME1b && !disableME1a && theRing == 1 ) numStrips = 80;
00579         if (!smartME1aME1b &&  disableME1a && theRing == 1 ) numStrips = 64;
00580         if ( smartME1aME1b && !disableME1a && theRing == 1 ) numStrips = 64;
00581         if ( smartME1aME1b && !disableME1a && theRing == 4 ) {
00582           if (gangedME1a) numStrips = 16;
00583           else numStrips = 48;
00584         }
00585       }
00586 
00587       if (numStrips > CSCConstants::MAX_NUM_STRIPS) {
00588         if (infoV >= 0) edm::LogError("L1CSCTPEmulatorSetupError")
00589           << "+++ Number of strips, " << numStrips
00590           << " found in ME" << ((theEndcap == 1) ? "+" : "-")
00591           << theStation << "/" << theRing << "/" << theChamber
00592           << " (sector " << theSector << " subsector " << theSubsector
00593           << " trig id. " << theTrigChamber << ")"
00594           << " exceeds max expected, " << CSCConstants::MAX_NUM_STRIPS
00595           << " +++\n" 
00596           << "+++ CSC geometry looks garbled; no emulation possible +++\n";
00597         numStrips = -1;
00598       }
00599       // The strips for a given layer may be offset from the adjacent layers.
00600       // This was done in order to improve resolution.  We need to find the
00601       // 'staggering' for each layer and make necessary conversions in our
00602       // arrays.  -JM
00603       // In the TMB-07 firmware, half-strips in odd layers (layers are
00604       // counted as ly0-ly5) are shifted by -1 half-strip, whereas in
00605       // the previous firmware versions half-strips in even layers
00606       // were shifted by +1 half-strip.  This difference is due to a
00607       // change from ly3 to ly2 in the choice of the key layer, and
00608       // the intention to keep half-strips in the key layer unchanged.
00609       // In the emulator, we use the old way for both cases, to avoid
00610       // negative half-strip numbers.  This will necessitate a
00611       // subtraction of 1 half-strip for TMB-07 later on. -SV.
00612       for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
00613         stagger[i_layer] =
00614           (chamber->layer(i_layer+1)->geometry()->stagger() + 1) / 2;
00615       }
00616     }
00617     else {
00618       if (infoV >= 0) edm::LogError("L1CSCTPEmulatorConfigError")
00619         << " ME" << ((theEndcap == 1) ? "+" : "-")
00620         << theStation << "/" << theRing << "/" << theChamber
00621         << " (sector " << theSector << " subsector " << theSubsector
00622         << " trig id. " << theTrigChamber << ")"
00623         << " is not defined in current geometry! +++\n"
00624         << "+++ CSC geometry looks garbled; no emulation possible +++\n";
00625       numStrips = -1;
00626     }
00627   }
00628 
00629   if (numStrips < 0) {
00630     if (infoV >= 0) edm::LogError("L1CSCTPEmulatorConfigError")
00631       << " ME" << ((theEndcap == 1) ? "+" : "-")
00632       << theStation << "/" << theRing << "/" << theChamber
00633       << " (sector " << theSector << " subsector " << theSubsector
00634       << " trig id. " << theTrigChamber << "):"
00635       << " numStrips = " << numStrips << "; CLCT emulation skipped! +++";
00636     std::vector<CSCCLCTDigi> emptyV;
00637     return emptyV;
00638   }
00639 
00640   // Get comparator digis in this chamber.
00641   bool noDigis = getDigis(compdc);
00642 
00643   if (!noDigis) {
00644     // Get halfstrip (and possibly distrip) times from comparator digis.
00645     std::vector<int>
00646       halfstrip[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS];
00647     std::vector<int>
00648       distrip[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS];
00649     if (isTMB07) { // TMB07 (latest) version: halfstrips only.
00650       readComparatorDigis(halfstrip);
00651     }
00652     else { // Earlier versions: halfstrips and distrips.
00653       readComparatorDigis(halfstrip, distrip);
00654     }
00655 
00656     // Pass arrays of halfstrips and distrips on to another run() doing the
00657     // LCT search.
00658     // If the number of layers containing digis is smaller than that
00659     // required to trigger, quit right away.  (If LCT-based digi suppression
00660     // is implemented one day, this condition will have to be changed
00661     // to the number of planes required to pre-trigger.)
00662     unsigned int layersHit = 0;
00663     for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
00664       for (int i_hstrip = 0; i_hstrip < CSCConstants::NUM_HALF_STRIPS;
00665            i_hstrip++) {
00666         if (!halfstrip[i_layer][i_hstrip].empty()) {layersHit++; break;}
00667       }
00668     }
00669     // Run the algorithm only if the probability for the pre-trigger
00670     // to fire is not null.  (Pre-trigger decisions are used for the
00671     // strip read-out conditions in DigiToRaw.)
00672     if (layersHit >= nplanes_hit_pretrig) run(halfstrip, distrip);
00673   }
00674 
00675   // Return vector of CLCTs.
00676   std::vector<CSCCLCTDigi> tmpV = getCLCTs();
00677   return tmpV;
00678 }
00679 
00680 void CSCCathodeLCTProcessor::run(
00681   const std::vector<int> halfstrip[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS],
00682   const std::vector<int> distrip[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS]) {
00683   // This version of the run() function can either be called in a standalone
00684   // test, being passed the halfstrip and distrip times, or called by the 
00685   // run() function above.  It uses the findLCTs() method to find vectors
00686   // of LCT candidates. These candidates are sorted and the best two per bx
00687   // are returned.
00688   std::vector<CSCCLCTDigi> LCTlist;
00689 
00690   if (isTMB07) {
00691     // Upgrade version for ME11 with better dead-time handling
00692     if (isSLHC && smartME1aME1b && isME11 && use_dead_time_zoning) LCTlist = findLCTsSLHC(halfstrip);
00693     // TMB07 version of the CLCT algorithm.
00694     else LCTlist = findLCTs(halfstrip);
00695   }
00696   else if (isMTCC) { // MTCC version.
00697     LCTlist = findLCTs(halfstrip, distrip);
00698   }
00699   else { // Idealized algorithm of many years ago.
00700     std::vector<CSCCLCTDigi> halfStripLCTs = findLCTs(halfstrip, 1);
00701     std::vector<CSCCLCTDigi> diStripLCTs   = findLCTs(distrip,   0);
00702     // Put all the candidates into a single vector and sort them.
00703     for (unsigned int i = 0; i < halfStripLCTs.size(); i++)
00704       LCTlist.push_back(halfStripLCTs[i]);
00705     for (unsigned int i = 0; i < diStripLCTs.size(); i++)
00706       LCTlist.push_back(diStripLCTs[i]);
00707   }
00708 
00709   // LCT sorting.
00710   if (LCTlist.size() > 1)
00711     sort(LCTlist.begin(), LCTlist.end(), std::greater<CSCCLCTDigi>());
00712 
00713   // Take the best two candidates per bx.
00714   for (std::vector<CSCCLCTDigi>::const_iterator plct = LCTlist.begin();
00715        plct != LCTlist.end(); plct++) {
00716     int bx = plct->getBX();
00717     if (bx >= MAX_CLCT_BINS) {
00718       if (infoV > 0) edm::LogWarning("L1CSCTPEmulatorOutOfTimeCLCT")
00719         << "+++ Bx of CLCT candidate, " << bx << ", exceeds max allowed, "
00720         << MAX_CLCT_BINS-1 << "; skipping it... +++\n";
00721       continue;
00722     }
00723 
00724     if (!bestCLCT[bx].isValid()) bestCLCT[bx] = *plct;
00725     else if (!secondCLCT[bx].isValid()) {
00726       // Ignore CLCT if it is the same as the best (i.e. if the same
00727       // CLCT was found in both half- and di-strip pattern search).
00728       // This can never happen in the test beam and MTCC
00729       // implementations.
00730       if (!isMTCC && !isTMB07 && *plct == bestCLCT[bx]) continue;
00731       secondCLCT[bx] = *plct;
00732     }
00733   }
00734 
00735   for (int bx = 0; bx < MAX_CLCT_BINS; bx++) {
00736     if (bestCLCT[bx].isValid()) {
00737       bestCLCT[bx].setTrknmb(1);
00738       if (infoV > 0) LogDebug("CSCCathodeLCTProcessor")
00739         << bestCLCT[bx] << " found in ME" << ((theEndcap == 1) ? "+" : "-")
00740         << theStation << "/" << theRing << "/" << theChamber
00741         << " (sector " << theSector << " subsector " << theSubsector
00742         << " trig id. " << theTrigChamber << ")" << "\n";
00743     }
00744     if (secondCLCT[bx].isValid()) {
00745       secondCLCT[bx].setTrknmb(2);
00746       if (infoV > 0) LogDebug("CSCCathodeLCTProcessor")
00747         << secondCLCT[bx] << " found in ME" << ((theEndcap == 1) ? "+" : "-")
00748         << theStation << "/" << theRing << "/" << theChamber
00749         << " (sector " << theSector << " subsector " << theSubsector
00750         << " trig id. " << theTrigChamber << ")" << "\n";
00751     }
00752   }
00753   // Now that we have our best CLCTs, they get correlated with the best
00754   // ALCTs and then get sent to the MotherBoard.  -JM
00755 }
00756 
00757 bool CSCCathodeLCTProcessor::getDigis(const CSCComparatorDigiCollection* compdc) {
00758   bool noDigis = true;
00759 
00760   // Loop over layers and save comparator digis on each one into digiV[layer].
00761   for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
00762     digiV[i_layer].clear();
00763     
00764     CSCDetId detid(theEndcap, theStation, theRing, theChamber, i_layer+1);
00765     getDigis(compdc, detid);
00766 
00767     // If this is ME1/1, fetch digis in corresponding ME1/A (ring=4) as well.
00768     if (theStation == 1 && theRing == 1 && !disableME1a && !smartME1aME1b) {
00769       CSCDetId detid_me1a(theEndcap, theStation, 4, theChamber, i_layer+1);
00770       getDigis(compdc, detid_me1a);
00771     }
00772 
00773     if (!digiV[i_layer].empty()) {
00774       noDigis = false;
00775       if (infoV > 1) {
00776         LogTrace("CSCCathodeLCTProcessor")
00777           << "found " << digiV[i_layer].size()
00778           << " comparator digi(s) in layer " << i_layer << " of ME"
00779           << ((theEndcap == 1) ? "+" : "-") << theStation << "/" << theRing
00780           << "/" << theChamber << " (trig. sector " << theSector
00781           << " subsector " << theSubsector << " id " << theTrigChamber << ")";
00782       }
00783     }
00784   }
00785 
00786   return noDigis;
00787 }
00788 
00789 void CSCCathodeLCTProcessor::getDigis(const CSCComparatorDigiCollection* compdc,
00790                                       const CSCDetId& id) {
00791   bool me1a = (id.station() == 1) && (id.ring() == 4);
00792   const CSCComparatorDigiCollection::Range rcompd = compdc->get(id);
00793   for (CSCComparatorDigiCollection::const_iterator digiIt = rcompd.first;
00794        digiIt != rcompd.second; ++digiIt) {
00795     if (me1a && digiIt->getStrip() <= 16 && !disableME1a && !smartME1aME1b) {
00796       // Move ME1/A comparators from CFEB=0 to CFEB=4 if this has not
00797       // been done already.
00798       CSCComparatorDigi digi_corr(digiIt->getStrip()+64,
00799                                   digiIt->getComparator(),
00800                                   digiIt->getTimeBinWord());
00801       digiV[id.layer()-1].push_back(digi_corr);
00802     }
00803     else {
00804       digiV[id.layer()-1].push_back(*digiIt);
00805     }
00806   }
00807 }
00808 
00809 void CSCCathodeLCTProcessor::readComparatorDigis(
00810         std::vector<int> halfstrip[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS]) {
00811   // Single-argument version for TMB07 (halfstrip-only) firmware.
00812   // Takes the comparator & time info and stuffs it into halfstrip vector.
00813   // Multiple hits on the same strip are allowed.
00814 
00815   for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
00816     int i_digi = 0; // digi counter, for dumps.
00817     for (std::vector<CSCComparatorDigi>::iterator pld = digiV[i_layer].begin();
00818          pld != digiV[i_layer].end(); pld++, i_digi++) {
00819       // Dump raw digi info.
00820       if (infoV > 1) {
00821         std::ostringstream strstrm;
00822         strstrm << "Comparator digi: comparator = " << pld->getComparator()
00823                 << " strip #" << pld->getStrip()
00824                 << " time bins on:";
00825         std::vector<int> bx_times = pld->getTimeBinsOn();
00826         for (unsigned int tbin = 0; tbin < bx_times.size(); tbin++)
00827           strstrm << " " << bx_times[tbin];
00828         LogTrace("CSCCathodeLCTProcessor") << strstrm.str();
00829       }
00830 
00831       // Get comparator: 0/1 for left/right halfstrip for each comparator
00832       // that fired.
00833       int thisComparator = pld->getComparator();
00834       if (thisComparator != 0 && thisComparator != 1) {
00835         if (infoV >= 0) edm::LogWarning("L1CSCTPEmulatorWrongInput")
00836           << "+++ Found comparator digi with wrong comparator value = "
00837           << thisComparator << "; skipping it... +++\n";
00838         continue;
00839       }
00840 
00841       // Get strip number.
00842       int thisStrip = pld->getStrip() - 1; // count from 0
00843       if (thisStrip < 0 || thisStrip >= numStrips) {
00844         if (infoV >= 0) edm::LogWarning("L1CSCTPEmulatorWrongInput")
00845           << "+++ Found comparator digi with wrong strip number = "
00846           << thisStrip
00847           << " (max strips = " << numStrips << "); skipping it... +++\n";
00848         continue;
00849       }
00850       // 2*strip: convert strip to 1/2 strip
00851       // comp   : comparator output
00852       // stagger: stagger for this layer
00853       int thisHalfstrip = 2*thisStrip + thisComparator + stagger[i_layer];
00854       if (thisHalfstrip >= 2*numStrips + 1) {
00855         if (infoV >= 0) edm::LogWarning("L1CSCTPEmulatorWrongInput")
00856           << "+++ Found wrong halfstrip number = " << thisHalfstrip
00857           << "; skipping this digi... +++\n";
00858         continue;
00859       }
00860 
00861       // Get bx times on this digi and check that they are within the bounds.
00862       std::vector<int> bx_times = pld->getTimeBinsOn();
00863       for (unsigned int i = 0; i < bx_times.size(); i++) {
00864         // Total number of time bins in DAQ readout is given by fifo_tbins,
00865         // which thus determines the maximum length of time interval.
00866         //
00867         // In TMB07 version, better data-emulator agreement is
00868         // achieved when hits in the first 2 time bins are excluded.
00869         // As of May 2009, the reasons for this are not fully
00870         // understood yet (the work is on-going).
00871         if (bx_times[i] > 1 && bx_times[i] < static_cast<int>(fifo_tbins)) {
00872 
00873           if (i == 0 || (i > 0 && bx_times[i]-bx_times[i-1] >=
00874                          static_cast<int>(hit_persist))) {
00875             // A later hit on the same strip is ignored during the
00876             // number of clocks defined by the "hit_persist" parameter
00877             // (i.e., 6 bx's by default).
00878             if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
00879               << "Comp digi: layer " << i_layer+1
00880               << " digi #"           << i_digi+1
00881               << " strip "           << thisStrip
00882               << " halfstrip "       << thisHalfstrip
00883               << " distrip "         << thisStrip/2 + // [0-39]
00884                              ((thisStrip%2 == 1 && thisComparator == 1 && stagger[i_layer] == 1) ? 1 : 0)
00885               << " time "            << bx_times[i]
00886               << " comparator "      << thisComparator
00887               << " stagger "         << stagger[i_layer];
00888             halfstrip[i_layer][thisHalfstrip].push_back(bx_times[i]);
00889           }
00890           else if (i > 0) {
00891             if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
00892               << " Skipping comparator digi: strip = " << thisStrip
00893               << ", layer = " << i_layer+1 << ", bx = " << bx_times[i]
00894               << ", bx of previous hit = " << bx_times[i-1];
00895           }
00896         }
00897         else {
00898           if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
00899             << "+++ Skipping comparator digi: strip = " << thisStrip
00900             << ", layer = " << i_layer+1 << ", bx = " << bx_times[i] << " +++";
00901         }
00902       }
00903     }
00904   }
00905 }
00906 
00907 void CSCCathodeLCTProcessor::readComparatorDigis(
00908   std::vector<int> halfstrip[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS],
00909   std::vector<int> distrip[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS]) {
00910   // Two-argument version for pre-TMB07 (halfstrip and distrips) firmware.
00911   // Takes the comparator & time info and stuffs it into halfstrip and (and
00912   // possibly distrip) vector.
00913 
00914   int time[CSCConstants::NUM_LAYERS][CSCConstants::MAX_NUM_STRIPS];
00915   int comp[CSCConstants::NUM_LAYERS][CSCConstants::MAX_NUM_STRIPS];
00916   int digiNum[CSCConstants::NUM_LAYERS][CSCConstants::MAX_NUM_STRIPS];
00917   for (int i = 0; i < CSCConstants::NUM_LAYERS; i++){
00918     for (int j = 0; j < CSCConstants::MAX_NUM_STRIPS; j++) {
00919       time[i][j]    = -999;
00920       comp[i][j]    =    0;
00921       digiNum[i][j] = -999;
00922     }
00923   }
00924 
00925   for (int i = 0; i < CSCConstants::NUM_LAYERS; i++) {
00926     std::vector <CSCComparatorDigi> layerDigiV = digiV[i];
00927     for (unsigned int j = 0; j < layerDigiV.size(); j++) {
00928       // Get one digi at a time for the layer.  -Jm
00929       CSCComparatorDigi thisDigi = layerDigiV[j];
00930 
00931       // Dump raw digi info
00932       if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
00933         << "Comparator digi: comparator = " << thisDigi.getComparator()
00934         << " strip #" << thisDigi.getStrip()
00935         << " time bin = " << thisDigi.getTimeBin();
00936 
00937       // Get comparator: 0/1 for left/right halfstrip for each comparator
00938       // that fired.
00939       int thisComparator = thisDigi.getComparator();
00940       if (thisComparator != 0 && thisComparator != 1) {
00941         if (infoV >= 0) edm::LogWarning("L1CSCTPEmulatorWrongInput")
00942           << "+++ Comparator digi with wrong comparator value: digi #" << j
00943           << ", comparator = " << thisComparator << "; skipping it... +++\n";
00944         continue;
00945       }
00946 
00947       // Get strip number.
00948       int thisStrip = thisDigi.getStrip() - 1; // count from 0
00949       if (thisStrip < 0 || thisStrip >= numStrips) {
00950         if (infoV >= 0) edm::LogWarning("L1CSCTPEmulatorWrongInput")
00951           << "+++ Comparator digi with wrong strip number: digi #" << j
00952           << ", strip = " << thisStrip
00953           << ", max strips = " << numStrips << "; skipping it... +++\n";
00954         continue;
00955       }
00956 
00957       // Get Bx of this Digi and check that it is within the bounds
00958       int thisDigiBx = thisDigi.getTimeBin();
00959 
00960       // Total number of time bins in DAQ readout is given by fifo_tbins,
00961       // which thus determines the maximum length of time interval.
00962       if (thisDigiBx >= 0 && thisDigiBx < static_cast<int>(fifo_tbins)) {
00963 
00964         // If there is more than one hit in the same strip, pick one
00965         // which occurred earlier.
00966         // In reality, the second hit on the same distrip is ignored only
00967         // during the number of clocks defined by the "hit_persist" 
00968         // parameter (i.e., 6 bx's by default).  So if one simulates
00969         // a large number of bx's in a crowded environment, this
00970         // approximation here may not be sufficiently good.
00971         if (time[i][thisStrip] == -999 || time[i][thisStrip] > thisDigiBx) {
00972           digiNum[i][thisStrip] = j;
00973           time[i][thisStrip]    = thisDigiBx;
00974           comp[i][thisStrip]    = thisComparator;
00975           if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
00976             << "Comp digi: layer " << i+1
00977             << " digi #"           << j+1
00978             << " strip "           << thisStrip
00979             << " halfstrip "       << 2*thisStrip + comp[i][thisStrip] + stagger[i]
00980             << " distrip "         << thisStrip/2 + // [0-39]
00981               ((thisStrip%2 == 1 && comp[i][thisStrip] == 1 && stagger[i] == 1) ? 1 : 0)
00982             << " time "            <<    time[i][thisStrip]
00983             << " comparator "      <<    comp[i][thisStrip]
00984             << " stagger "         << stagger[i];
00985         }
00986       }
00987       else {
00988         if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
00989           << "+++ Skipping comparator digi: strip = " << thisStrip
00990           << ", layer = " << i+1 << ", bx = " << thisDigiBx << " +++";
00991       }
00992     }
00993   }
00994 
00995   // Take the comparator & time info and stuff it into half- and di-strip
00996   // arrays.
00997   for (int i = 0; i < CSCConstants::NUM_LAYERS; i++) {
00998     // Use the comparator info to setup the halfstrips and distrips.  -BT
00999     // This loop is only for halfstrips.
01000     for (int j = 0; j < CSCConstants::MAX_NUM_STRIPS; j++) {
01001       if (time[i][j] >= 0) {
01002         int i_halfstrip = 2*j + comp[i][j] + stagger[i];
01003         // 2*j    : convert strip to 1/2 strip
01004         // comp   : comparator output
01005         // stagger: stagger for this layer
01006         if (i_halfstrip >= 2*numStrips + 1) {
01007           if (infoV >= 0) edm::LogWarning("L1CSCTPEmulatorWrongInput")
01008             << "+++ Found wrong halfstrip number = " << i_halfstrip
01009             << "; skipping this digi... +++\n";
01010           continue;
01011         }
01012         halfstrip[i][i_halfstrip].push_back(time[i][j]);
01013       }
01014     }
01015 
01016     // There are no di-strips in the 2007 version of the TMB firmware.
01017     if (!isTMB07) {
01018       // This loop is only for distrips.  We have to separate the routines
01019       // because triad and time arrays can be changed by the distripStagger
01020       // routine which could mess up the halfstrips.
01021       static int test_iteration = 0;
01022       for (int j = 0; j < CSCConstants::MAX_NUM_STRIPS; j++){
01023         if (time[i][j] >= 0) {
01024           int i_distrip = j/2;
01025           if (j%2 == 1 && comp[i][j] == 1 && stagger[i] == 1) {
01026             // @@ Needs to be checked.
01027             bool stagger_debug = (infoV > 2);
01028             distripStagger(comp[i], time[i], digiNum[i], j, stagger_debug);
01029           }
01030           // comp[i][j] == 1    : hit on right half-strip.
01031           // stagger[i] == 1    : half-strips are shifted by 1.
01032           // if these conditions are met add 1; otherwise add 0.
01033           // So if there is a hit on the far right half-strip, and the
01034           // half-strips have been staggered to the right, then the di-strip
01035           // would actually correspond to the next highest di-strip.  -JM
01036           if (infoV > 2 && test_iteration == 1) {
01037             testDistripStagger();
01038             test_iteration++;
01039           }
01040           if (i_distrip >= numStrips/2 + 1) {
01041             if (infoV >= 0) edm::LogWarning("L1CSCTPEmulatorWrongInput")
01042               << "+++ Found wrong distrip number = " << i_distrip
01043               << "; skipping this digi... +++\n";
01044             continue;
01045           }
01046           distrip[i][i_distrip].push_back(time[i][j]);
01047         }
01048       }
01049     }
01050   }
01051 }
01052 
01053 void CSCCathodeLCTProcessor::distripStagger(int stag_triad[CSCConstants::MAX_NUM_STRIPS],
01054                                    int stag_time[CSCConstants::MAX_NUM_STRIPS],
01055                                    int stag_digi[CSCConstants::MAX_NUM_STRIPS],
01056                                    int i_strip, bool debug) {
01057   // Author: Jason Mumford (mumford@physics.ucla.edu)
01058   // This routine takes care of the stagger situation where there is a hit
01059   // on the right half-strip of a di-strip.  If there is a stagger, then
01060   // we must associate that distrip with the next distrip. The situation
01061   // gets more complicated if the next distrip also has a hit on its right
01062   // half-strip.  One could imagine a whole chain of these in which case
01063   // we need to go into this routine recursively.  The formula is that
01064   // while this condition is satisfied, we enquire the next distrip,
01065   // until we have a hit on any other halfstrip (or triad!=3).  Then we
01066   // must compare the 2 different bx times and take the smallest one.
01067   // Afterwards, we must cycle out of the routine assigning the bx times
01068   // to the one strip over.
01069 
01070   // Used only for pre-TMB07 firmware.
01071 
01072   if (i_strip >= CSCConstants::MAX_NUM_STRIPS) {
01073     if (debug) edm::LogWarning("L1CSCTPEmulatorWrongInput")
01074       << "+++ Found wrong strip number = " << i_strip
01075       << "; cannot apply distrip staggering... +++\n";
01076     return;
01077   }
01078 
01079   if (debug)
01080     LogDebug("CSCCathodeLCTProcessor")
01081       << " Enter distripStagger: i_strip = " << i_strip
01082       << " stag_triad[i_strip] = "   << stag_triad[i_strip]
01083       << " stag_time[i_strip] =  "   << stag_time[i_strip]
01084       << " stag_triad[i_strip+2] = " << stag_triad[i_strip+2]
01085       << " stag_time[i_strip+2] = "  << stag_time[i_strip+2];
01086 
01087   // So if the next distrip has a stagger hit, go into the routine again
01088   // for the next distrip.
01089   if (i_strip+2 < CSCConstants::MAX_NUM_STRIPS && stag_triad[i_strip+2] == 1)
01090     distripStagger(stag_triad, stag_time, stag_digi, i_strip+2);
01091 
01092   // When we have reached a distrip that does not have a staggered hit,
01093   // if it has a hit, we compare the bx times of the
01094   // staggered distrip with the non-staggered distrip and we take the
01095   // smallest of the two and assign it to the shifted distrip time.
01096   if (stag_time[i_strip+2] >= 0) {
01097     if (stag_time[i_strip] < stag_time[i_strip+2]) {
01098       stag_time[i_strip+2] = stag_time[i_strip];
01099       stag_digi[i_strip+2] = stag_digi[i_strip];
01100     }
01101   }
01102   // If the next distrip did not have a hit, then we merely assign the
01103   // shifted time to the time associated with the staggered distrip.
01104   else {
01105     stag_time[i_strip+2] = stag_time[i_strip];
01106     stag_digi[i_strip+2] = stag_digi[i_strip];
01107   }
01108 
01109   // Then to prevent previous staggers from being overwritten, we assign
01110   // the unshifted time to -999, and then mark the triads that were shifted
01111   // so that we don't go into the routine ever again (such as when making
01112   // the next loop over strips).
01113   stag_time[i_strip]  = -999;
01114   stag_triad[i_strip] =    4;
01115   stag_digi[i_strip]  = -999;
01116 
01117   if (debug)
01118     LogDebug("CSCCathodeLCTProcessor")
01119       << " Exit  distripStagger: i_strip = " << i_strip
01120       << " stag_triad[i_strip] = "   << stag_triad[i_strip]
01121       << " stag_time[i_strip] = "    << stag_time[i_strip]
01122       << " stag_triad[i_strip+2] = " << stag_triad[i_strip+2]
01123       << " stag_time[i_strip+2] = "  << stag_time[i_strip+2];
01124 }
01125 
01126 // --------------------------------------------------------------------------
01127 // The code below is a description of the idealized CLCT algorithm which
01128 // was used in Monte Carlo studies since early ORCA days and until
01129 // CMSSW_2_0_0 (March 2008) but was never realized in the firmware.
01130 //
01131 // Starting with CMSSW_3_1_0, it may no longer give the same results as
01132 // before since old versions of overloaded < > == operators in CLCTDigi
01133 // class were discarded.
01134 // --------------------------------------------------------------------------
01135 // Idealized version for MC studies.
01136 std::vector<CSCCLCTDigi> CSCCathodeLCTProcessor::findLCTs(const std::vector<int> strip[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS], int stripType)
01137 {
01138   int j;
01139   int best_strip = 0;
01140   int first_bx = 999;
01141   const int max_lct_num = 2;
01142   const int adjacent_strips = 2;
01143   // Distrip, halfstrip pattern threshold.
01144   const unsigned int ptrn_thrsh[2] = {nplanes_hit_pattern, nplanes_hit_pattern};
01145   int highest_quality = 0;
01146 
01147   int keystrip_data[CSCConstants::NUM_HALF_STRIPS][7];
01148   int final_lcts[max_lct_num];
01149 
01150   std::vector <CSCCLCTDigi> lctList;
01151 
01152   int nStrips = 0;
01153   if (stripType == 1)      nStrips = 2*numStrips + 1;
01154   else if (stripType == 0) nStrips = numStrips/2 + 1;
01155 
01156   if (infoV > 1) dumpDigis(strip, stripType, nStrips);
01157 
01158   // Send data to a pretrigger so that we don't excessively look at data
01159   // that won't give an LCT. If there is a pretrigger, then get all quality
01160   // and bend for all keystrips.
01161   if (preTrigger(strip, stripType, nStrips, first_bx)){
01162     getKeyStripData(strip, keystrip_data, nStrips, first_bx, best_strip, stripType);
01163 
01164     /* Set all final_lcts to impossible key_strip numbers */
01165     for (j = 0; j < max_lct_num; j++)
01166       final_lcts[j] = -999;
01167 
01168     // Now take the keystrip with the best quality, and do a search over the
01169     // rest of the strips for the next highest quality.  Do the search over a 
01170     // range excluding a certain number of keystrips adjacent to the original
01171     // best key_strip.
01172     final_lcts[0] = best_strip;
01173 
01174     for (int key_strip = 0; key_strip < (nStrips-stripType); key_strip++){
01175       // If indexed strip does not fall within excluded range, then continue
01176       if (abs(best_strip - key_strip) > adjacent_strips){
01177         // Match with highest quality
01178         if (keystrip_data[key_strip][CLCT_QUALITY] > highest_quality){
01179           highest_quality = keystrip_data[key_strip][CLCT_QUALITY];
01180           final_lcts[1] = key_strip;
01181         }
01182       }
01183     }
01184 
01185     for (j = 0; j < max_lct_num; j++){
01186       // Only report LCTs if the number of layers hit is greater than or
01187       // equal to the (variable) valid pattern threshold ptrn_thrsh.
01188       int keystrip = final_lcts[j];
01189       if (keystrip >= 0 &&
01190           keystrip_data[keystrip][CLCT_QUALITY] >= static_cast<int>(ptrn_thrsh[stripType])) {
01191         // assign the stripType here. 1 = halfstrip, 0 = distrip.
01192         keystrip_data[keystrip][CLCT_STRIP_TYPE] = stripType;
01193         // Now make the LCT words for the 2 highest, and store them in a list
01194         int theHalfStrip = (keystrip_data[keystrip][CLCT_STRIP_TYPE] ?
01195                             keystrip_data[keystrip][CLCT_STRIP] :
01196                             4*keystrip_data[keystrip][CLCT_STRIP]);
01197         keystrip_data[keystrip][CLCT_CFEB] = theHalfStrip/32;
01198         int halfstrip_in_cfeb =
01199           theHalfStrip - 32*keystrip_data[keystrip][CLCT_CFEB];
01200 
01201         CSCCLCTDigi thisLCT(1, keystrip_data[keystrip][CLCT_QUALITY],
01202                             keystrip_data[keystrip][CLCT_PATTERN],
01203                             keystrip_data[keystrip][CLCT_STRIP_TYPE],
01204                             keystrip_data[keystrip][CLCT_BEND],
01205                             halfstrip_in_cfeb,
01206                             keystrip_data[keystrip][CLCT_CFEB],
01207                             keystrip_data[keystrip][CLCT_BX]);
01208         if (infoV > 2) {
01209           char stripType =
01210             (keystrip_data[keystrip][CLCT_STRIP_TYPE] == 0) ? 'D' : 'H';
01211           char bend =
01212             (keystrip_data[keystrip][CLCT_BEND] == 0) ? 'L' : 'R';
01213           LogTrace("CSCCathodeLCTProcessor")
01214             << " Raw Find: "
01215             << "Key Strip: "  << std::setw(3)
01216             << keystrip_data[keystrip][CLCT_STRIP]
01217             << " Pattern: "   << std::setw(2)
01218             << keystrip_data[keystrip][CLCT_PATTERN]
01219             << " Bend: "      << std::setw(1) << bend
01220             << " Quality: "   << std::setw(1)
01221             << keystrip_data[keystrip][CLCT_QUALITY]
01222             << " stripType: " << std::setw(1) << stripType
01223             << " BX: "        << std::setw(1)
01224             << keystrip_data[keystrip][CLCT_BX];
01225         }
01226         lctList.push_back(thisLCT);
01227       }
01228     }
01229   }
01230 
01231   return lctList;
01232 } // findLCTs -- idealized version for MC studies.
01233 
01234 
01235 // Idealized version for MC studies.
01236 bool CSCCathodeLCTProcessor::preTrigger(const std::vector<int> strip[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS],
01237                                         const int stripType, const int nStrips,
01238                                         int& first_bx)
01239 {
01240   static const int hs_thresh = nplanes_hit_pretrig;
01241   static const int ds_thresh = nplanes_hit_pretrig;
01242 
01243   unsigned int pulse[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS];
01244   int i_layer, i_strip, this_layer, this_strip;
01245   int hits, layers_hit;
01246   bool hit_layer[CSCConstants::NUM_LAYERS];
01247 
01248   const int pre_trigger_layer_min = (stripType == 1) ? hs_thresh : ds_thresh;
01249 
01250   // Fire half-strip/di-strip one-shots for hit_persist bx's (6 bx's by
01251   // default).
01252   pulseExtension(strip, nStrips, pulse);
01253 
01254   // Now do a loop over different bunch-crossing times.
01255   for (unsigned int bx_time = 0; bx_time < fifo_tbins; bx_time++) {
01256     // For any given bunch-crossing, start at the lowest keystrip and look for
01257     // the number of separate layers in the pattern for that keystrip that have
01258     // pulses at that bunch-crossing time.  Do the same for the next keystrip, 
01259     // etc.  Then do the entire process again for the next bunch-crossing, etc
01260     // until you find a pre-trigger.
01261     for (int key_strip = 0; key_strip < nStrips; key_strip++){
01262       // Clear variables
01263       hits = 0;
01264       layers_hit = 0;
01265       for (i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++)
01266         hit_layer[i_layer] = false;
01267       // Loop over pattern strips and look for hits.
01268       for (i_strip = 0; i_strip < NUM_PATTERN_STRIPS; i_strip++){
01269         this_layer = pre_hit_pattern[0][i_strip];
01270         this_strip = pre_hit_pattern[1][i_strip]+key_strip;
01271         if (this_strip >= 0 && this_strip < nStrips) {
01272           // Perform bit operation to see if pulse is 1 at a certain bx_time.
01273           if (((pulse[this_layer][this_strip] >> bx_time) & 1) == 1) {
01274             hits++;
01275             // Store number of layers hit.
01276             if (hit_layer[this_layer] == false) {
01277               hit_layer[this_layer] = true;
01278               layers_hit++;
01279 
01280               // Look if number of layers hit is greater or equal than some
01281               // pre-defined threshold.
01282               if (layers_hit >= pre_trigger_layer_min) {
01283                 first_bx = bx_time;
01284                 return true;
01285               }
01286             }
01287           }
01288         }
01289       }
01290     }
01291   }
01292   // If the pretrigger was never satisfied, then return false.
01293   return false;
01294 } // preTrigger -- idealized version for MC studies.
01295 
01296 
01297 // Idealized version for MC studies.
01298 void CSCCathodeLCTProcessor::getKeyStripData(const std::vector<int> strip[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS],
01299         int keystrip_data[CSCConstants::NUM_HALF_STRIPS][7],
01300         int nStrips, int first_bx, int& best_strip, int stripType) {
01301   int lct_pattern[NUM_PATTERN_STRIPS];
01302   int key_strip, this_layer, this_strip;
01303   int quality, best_quality;
01304   int bend = 0;
01305   int highest_quality = 0;
01306   bool nullPattern;
01307 
01308   for (key_strip = 0; key_strip < nStrips; key_strip++)
01309     for (int i = 0; i < 7; i++)
01310       keystrip_data[key_strip][i] = 0;
01311 
01312   // Now we need to look at all the keystrips and take the best pattern
01313   // for each.  There are multiple patterns available for each keystrip.
01314 
01315   for (key_strip = 0; key_strip < (nStrips-stripType); key_strip++){
01316     nullPattern = true;
01317     for (int pattern_strip = 0; pattern_strip < NUM_PATTERN_STRIPS; pattern_strip++){
01318       this_layer = pre_hit_pattern[0][pattern_strip];
01319       this_strip = pre_hit_pattern[1][pattern_strip] + key_strip;
01320       // This conditional statement prevents us from looking at strips
01321       // that don't exist along the chamber boundaries.
01322       if ((this_strip >= 0 && this_strip < nStrips) &&
01323           !strip[this_layer][this_strip].empty()) {
01324         if (nullPattern) nullPattern = false;
01325         std::vector<int> bx_times = strip[this_layer][this_strip];
01326         lct_pattern[pattern_strip] = bx_times[0];
01327       }
01328       else
01329         lct_pattern[pattern_strip] = -999;
01330       }
01331     // do the rest only if there is at least one DIGI in the pattern for
01332     // this keystrip
01333     if (nullPattern) continue;
01334 
01335     // Initialize best_quality to zero so that we can look for best pattern
01336     // within a keystrip.
01337     best_quality = 0;
01338 
01339     // Loop over all possible patterns.
01340     // Loop in reverse order, in order to give priority to a straighter
01341     // pattern (larger pattern_num) in case of equal qualities.
01342     // Exclude pattern 0 since it is not defined.
01343     for (int pattern_num = CSCConstants::NUM_CLCT_PATTERNS_PRE_TMB07-1; pattern_num > 0; pattern_num--) {
01344       // Get the pattern quality from lct_pattern.
01345       // TMB latches LCTs drift_delay clocks after pretrigger.
01346       int latch_bx = first_bx + drift_delay;
01347       getPattern(pattern_num, lct_pattern, latch_bx, quality, bend);
01348       if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
01349         << "Key_strip " << key_strip << " quality of pattern_num "
01350         << pattern_num << ": " << quality;
01351       if (quality > best_quality){
01352         // Store the best pattern, quality, etc., for each key_strip.
01353         keystrip_data[key_strip][CLCT_PATTERN] = pattern_num;
01354         keystrip_data[key_strip][CLCT_BEND]    = bend;
01355         keystrip_data[key_strip][CLCT_STRIP]   = key_strip;
01356         keystrip_data[key_strip][CLCT_BX]      = first_bx;
01357         // keystrip_data[key_strip][CLCT_STRIP_TYPE] = stripType; //assign the stripType elsewhere
01358         keystrip_data[key_strip][CLCT_QUALITY] = quality;
01359         if (quality > highest_quality){
01360           // Keep track of which strip had the highest quality.
01361           // highest_quality refers to the overall highest quality for all
01362           // key strips. This is different than best_quality which refers
01363           // to the best quality in a keystrip from different patterns.
01364           best_strip = key_strip;
01365           highest_quality = quality;
01366         }
01367         best_quality = quality;
01368       }
01369     }
01370   }
01371 } // getKeyStripData -- idealized version for MC studies.
01372 
01373 
01374 // Idealized version for MC studies.
01375 void CSCCathodeLCTProcessor::getPattern(int pattern_num,
01376        int strip_value[NUM_PATTERN_STRIPS], int bx_time,
01377        int& quality, int& bend){
01378   // This function takes strip values and bx_time to find out which hits fall
01379   // within a certain pattern.  Quality, and bend are then calculated based on
01380   // which strip pattern and how many layers were hit within the pattern.
01381   int layers_hit = 0;
01382   bool hit_layer[CSCConstants::NUM_LAYERS];
01383 
01384   // Clear hit_layer array to keep track of number of layers hit.
01385   for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++)
01386     hit_layer[i_layer] = false;
01387 
01388   // Loop over all designated patterns.
01389   for (int strip_num = 0; strip_num < NUM_PATTERN_STRIPS; strip_num++){
01390     if (hitIsGood(strip_value[strip_num], bx_time)){
01391       for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++){
01392         // Loop over layer and see if corresponding strip is on same layer
01393         // If so then increment number of hits.
01394         if (i_layer == pattern[pattern_num][strip_num]){
01395           // If layer has no hits, then increment number of layers hit.
01396           if (hit_layer[i_layer] == false){
01397             layers_hit++;
01398             hit_layer[i_layer] = true;
01399           }
01400         }
01401       }
01402     }
01403   }
01404   // Get bend value from pattern.
01405   bend = pattern[pattern_num][NUM_PATTERN_STRIPS];
01406   quality = layers_hit;
01407 } // getPattern -- idealized version for MC studies.
01408 
01409 
01410 // Idealized version for MC studies.
01411 bool CSCCathodeLCTProcessor::hitIsGood(int hitTime, int BX) {
01412   // Find out if hit time is good.  Hit should have occurred no more than
01413   // hit_persist clocks before the latching time.
01414   int dt = BX - hitTime;
01415   if (dt >= 0 && dt <= static_cast<int>(hit_persist)) {return true;}
01416   else {return false;}
01417 } // hitIsGood -- idealized version for MC studies.
01418 
01419 
01420 // --------------------------------------------------------------------------
01421 // The code below is a description of the pre-2007 version of the CLCT
01422 // algorithm.  It was used in numerous CSC test beams and MTCC for
01423 // firmware-emulator comparisons, but due to a number of known limitations
01424 // it was never used in Monte Carlo studies.
01425 //
01426 // Starting with CMSSW_3_1_0, it may no longer give the same results as
01427 // before since old versions of overloaded < > == operators in CLCTDigi
01428 // class were discarded.
01429 // --------------------------------------------------------------------------
01430 // Pre-2007 version.
01431 std::vector <CSCCLCTDigi> CSCCathodeLCTProcessor::findLCTs(
01432  const std::vector<int> halfstrip[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS],
01433  const std::vector<int> distrip[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS]) {
01434   std::vector <CSCCLCTDigi> lctList;
01435   int _bx[2] = {999, 999};
01436   int first_bx = 999;
01437 
01438   const int nhStrips = 2*numStrips + 1;
01439   const int ndStrips = numStrips/2 + 1;
01440 
01441   if (infoV > 1) {
01442     dumpDigis(halfstrip, 1, nhStrips);
01443     dumpDigis(distrip,   0, ndStrips);
01444   }
01445 
01446   // Test beam version of TMB pretrigger and LCT sorting
01447   int h_keyStrip[MAX_CFEBS];       // one key per CFEB
01448   unsigned int h_nhits[MAX_CFEBS]; // number of hits in envelope for each key
01449   int d_keyStrip[MAX_CFEBS];       // one key per CFEB
01450   unsigned int d_nhits[MAX_CFEBS]; // number of hits in envelope for each key
01451   int keystrip_data[2][7];    // 2 possible LCTs per CSC x 7 LCT quantities
01452   unsigned int h_pulse[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS]; // simulate digital one-shot
01453   unsigned int d_pulse[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS]; // simulate digital one-shot
01454   bool pre_trig[2] = {false, false};
01455 
01456   // All half-strip and di-strip pattern envelopes are evaluated
01457   // simultaneously, on every clock cycle.
01458   pre_trig[0] = preTrigger(halfstrip, h_pulse, 1, nhStrips, 0, _bx[0]);
01459   pre_trig[1] = preTrigger(  distrip, d_pulse, 0, ndStrips, 0, _bx[1]);
01460 
01461   // If any of 200 half-strip and di-strip envelopes has enough layers hit in
01462   // it, TMB will pre-trigger.
01463   if (pre_trig[0] || pre_trig[1]) {
01464     first_bx = (_bx[0] < _bx[1]) ? _bx[0] : _bx[1];
01465     if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
01466       << "half bx " << _bx[0] << " di bx " << _bx[1] << " first " << first_bx
01467       << "\n ..... waiting drift delay ..... ";
01468 
01469     // Empirically-found trick allowing to dramatically improve agreement
01470     // with MTCC-II data.
01471     // The trick is to ignore hits in a few first time bins when latching
01472     // hits for priority encode envelopes.  For MTCC-II, we need to ignore
01473     // hits in time bins 0-3 inclusively.
01474     //
01475     // Firmware configuration has been fixed for most of 2007 runs, so
01476     // this trick should NOT be used when emulating 2007 trigger.
01477     /*
01478     int max_bx = 4;
01479     for (int ilayer = 0; ilayer < CSCConstants::NUM_LAYERS; ilayer++) {
01480       for (int istrip = 0; istrip < CSCConstants::NUM_HALF_STRIPS; istrip++) {
01481         for (int bx = 0; bx < max_bx; bx++) {
01482           if (((h_pulse[ilayer][istrip] >> bx) & 1) == 1) {
01483             h_pulse[ilayer][istrip] = 0;
01484           }
01485         }
01486       }
01487       for (int istrip = 0; istrip < CSCConstants::NUM_DI_STRIPS; istrip++) {
01488         for (int bx = 0; bx < max_bx; bx++) {
01489           if (((d_pulse[ilayer][istrip] >> bx) & 1) == 1) {
01490             d_pulse[ilayer][istrip] = 0;
01491           }
01492         }
01493       }
01494     }
01495     */
01496 
01497     // TMB latches LCTs drift_delay clocks after pretrigger.
01498     int latch_bx = first_bx + drift_delay;
01499     latchLCTs(h_pulse, h_keyStrip, h_nhits, 1, CSCConstants::NUM_HALF_STRIPS,
01500               latch_bx);
01501     latchLCTs(d_pulse, d_keyStrip, d_nhits, 0,   CSCConstants::NUM_DI_STRIPS,
01502               latch_bx);
01503 
01504     if (infoV > 1) {
01505       LogTrace("CSCCathodeLCTProcessor")
01506         << "...............................\n"
01507         << "Final halfstrip hits and keys (after drift delay) ...";
01508       for (int icfeb = 0; icfeb < MAX_CFEBS; icfeb++) {
01509         LogTrace("CSCCathodeLCTProcessor")
01510           << "cfeb " << icfeb << " key: " << h_keyStrip[icfeb]
01511           << " hits " << h_nhits[icfeb];
01512       }
01513       LogTrace("CSCCathodeLCTProcessor")
01514         << "Final distrip hits and keys (after drift delay) ...";
01515       for (int icfeb = 0; icfeb < MAX_CFEBS; icfeb++) {
01516         LogTrace("CSCCathodeLCTProcessor")
01517           << "cfeb " << icfeb << " key: " << d_keyStrip[icfeb]
01518           << " hits " << d_nhits[icfeb];
01519       }
01520     }
01521     priorityEncode(h_keyStrip, h_nhits, d_keyStrip, d_nhits, keystrip_data);
01522     getKeyStripData(h_pulse, d_pulse, keystrip_data, first_bx);
01523 
01524     for (int ilct = 0; ilct < 2; ilct++) {
01525       if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
01526         << "found lcts: ilct " << ilct
01527         << "  key strip " << keystrip_data[ilct][CLCT_STRIP];
01528       if (keystrip_data[ilct][CLCT_STRIP] != -1) {
01529         int halfstrip_in_cfeb = 0;
01530         if (keystrip_data[ilct][CLCT_STRIP_TYPE] == 0)
01531           halfstrip_in_cfeb = 4*keystrip_data[ilct][CLCT_STRIP] -
01532                              32*keystrip_data[ilct][CLCT_CFEB];
01533         else
01534           halfstrip_in_cfeb = keystrip_data[ilct][CLCT_STRIP] -
01535                              32*keystrip_data[ilct][CLCT_CFEB];
01536 
01537         CSCCLCTDigi thisLCT(1, keystrip_data[ilct][CLCT_QUALITY],
01538                             keystrip_data[ilct][CLCT_PATTERN],
01539                             keystrip_data[ilct][CLCT_STRIP_TYPE],
01540                             keystrip_data[ilct][CLCT_BEND],
01541                             halfstrip_in_cfeb,
01542                             keystrip_data[ilct][CLCT_CFEB],
01543                             keystrip_data[ilct][CLCT_BX]);
01544         lctList.push_back(thisLCT);
01545       }
01546     }
01547   }
01548 
01549   return lctList;
01550 
01551 } // findLCTs -- pre-2007 version.
01552 
01553 
01554 // Pre-2007 version.
01555 bool CSCCathodeLCTProcessor::preTrigger(
01556    const std::vector<int> strip[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS],
01557    unsigned int pulse[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS],
01558                                         const int stripType, const int nStrips,
01559                                         const int start_bx, int& first_bx) {
01560   if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
01561     << "....................PreTrigger...........................";
01562 
01563   if (start_bx == 0) {
01564     // Fire one-shots for hit_persist bx's (6 bx's by default).
01565     pulseExtension(strip, nStrips, pulse);
01566   }
01567 
01568   bool pre_trig = false;
01569   // Now do a loop over bx times to see (if/when) track goes over threshold
01570   for (unsigned int bx_time = start_bx; bx_time < fifo_tbins; bx_time++) {
01571     // For any given bunch-crossing, start at the lowest keystrip and look for
01572     // the number of separate layers in the pattern for that keystrip that have
01573     // pulses at that bunch-crossing time.  Do the same for the next keystrip, 
01574     // etc.  Then do the entire process again for the next bunch-crossing, etc
01575     // until you find a pre-trigger.
01576     pre_trig = preTrigLookUp(pulse, stripType, nStrips, bx_time);
01577     if (pre_trig) {
01578       first_bx = bx_time; // bx at time of pretrigger
01579       return true;
01580     }
01581   } // end loop over bx times
01582 
01583   if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
01584     << "no pretrigger for strip type " << stripType << ", returning \n";
01585   first_bx = fifo_tbins;
01586   return false;
01587 } // preTrigger -- pre-2007 version.
01588 
01589 
01590 // Pre-2007 version.
01591 bool CSCCathodeLCTProcessor::preTrigLookUp(
01592            const unsigned int pulse[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS],
01593            const int stripType, const int nStrips,
01594            const unsigned int bx_time) {
01595   static const int hs_thresh = nplanes_hit_pretrig;
01596   static const int ds_thresh = nplanes_hit_pretrig;
01597 
01598   bool hit_layer[CSCConstants::NUM_LAYERS];
01599   int key_strip, this_layer, this_strip, layers_hit;
01600 
01601   // Layers hit threshold for pretrigger
01602   const int pre_trigger_layer_min = (stripType == 1) ? hs_thresh : ds_thresh;
01603 
01604   if (stripType != 0 && stripType != 1) {
01605     if (infoV >= 0) edm::LogWarning("L1CSCTPEmulatorWrongInput")
01606       << "+++ preTrigLookUp: stripType = " << stripType
01607       << " does not correspond to half-strip/di-strip patterns! +++\n";
01608     return false;
01609   }
01610 
01611   for (int icfeb = 0; icfeb < MAX_CFEBS; icfeb++) { // loop over cfebs
01612     // Loop over (di-/half-)strips in CFEB.
01613     for (int istrip = 0; istrip < cfeb_strips[stripType]; istrip++) {
01614       // Calculate candidate key.
01615       key_strip = icfeb*cfeb_strips[stripType] + istrip;
01616       layers_hit = 0;
01617       for (int ilayer = 0; ilayer < CSCConstants::NUM_LAYERS; ilayer++)
01618         hit_layer[ilayer] = false;
01619 
01620       // Loop over strips in pretrigger pattern mask and look for hits.
01621       for (int pstrip = 0; pstrip < NUM_PATTERN_STRIPS; pstrip++) {
01622         this_layer = pre_hit_pattern[0][pstrip];
01623         this_strip = pre_hit_pattern[1][pstrip]+key_strip;
01624 
01625         if (this_strip >= 0 && this_strip < nStrips) {
01626           // Determine if "one shot" is high at this bx_time
01627           if (((pulse[this_layer][this_strip] >> bx_time) & 1) == 1) {
01628             if (hit_layer[this_layer] == false) {
01629               hit_layer[this_layer] = true;
01630               layers_hit++;                  // determines number of layers hit
01631               if (layers_hit >= pre_trigger_layer_min) {
01632                 if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
01633                   << "pretrigger at bx: " << bx_time
01634                   << ", cfeb " << icfeb << ", returning";
01635                 return true;
01636               }
01637             }
01638           }
01639         }
01640       } // end loop over strips in pretrigger pattern
01641     } // end loop over candidate key strips in cfeb
01642   } // end loop over cfebs, if pretrigger is found, stop looking and return
01643 
01644   return false;
01645 
01646 } // preTrigLookUp -- pre-2007 version.
01647 
01648 
01649 // Pre-2007 version.
01650 void CSCCathodeLCTProcessor::latchLCTs(
01651            const unsigned int pulse[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS],
01652            int keyStrip[MAX_CFEBS], unsigned int n_hits[MAX_CFEBS],
01653            const int stripType, const int nStrips, const int bx_time) {
01654 
01655   bool hit_layer[CSCConstants::NUM_LAYERS];
01656   int key_strip, this_layer, this_strip;
01657   int layers_hit, prev_hits;
01658 
01659   for (int icfeb = 0; icfeb < MAX_CFEBS; icfeb++) {
01660     keyStrip[icfeb] = -1;
01661     n_hits[icfeb]   =  0;
01662   }
01663 
01664   if (stripType != 0 && stripType != 1) {
01665     if (infoV >= 0) edm::LogWarning("L1CSCTPEmulatorWrongInput")
01666       << "+++ latchLCTs: stripType = " << stripType
01667       << " does not correspond to half-strip/di-strip patterns! +++\n";
01668     return;
01669   }
01670 
01671   for (int icfeb = 0; icfeb < MAX_CFEBS; icfeb++) { // loop over CFEBs
01672     prev_hits = 0;
01673     // Loop over (di-/half-)strips in CFEB.
01674     for (int istrip = 0; istrip < cfeb_strips[stripType]; istrip++) {
01675       // Calculate candidate key.
01676       key_strip = icfeb*cfeb_strips[stripType] + istrip;
01677       layers_hit = 0;
01678       for (int ilayer = 0; ilayer < CSCConstants::NUM_LAYERS; ilayer++)
01679         hit_layer[ilayer] = false;
01680 
01681       // Loop over strips in pretrigger pattern mask and look for hits.
01682       for (int pstrip = 0; pstrip < NUM_PATTERN_STRIPS; pstrip++) {
01683         this_layer = pre_hit_pattern[0][pstrip];
01684         this_strip = pre_hit_pattern[1][pstrip]+key_strip;
01685 
01686         if (this_strip >= 0 && this_strip < nStrips) {
01687           // Determine if "one shot" is high at this bx_time
01688           if (((pulse[this_layer][this_strip] >> bx_time) & 1) == 1) {
01689             if (hit_layer[this_layer] == false) {
01690               hit_layer[this_layer] = true;
01691               layers_hit++;                  // number of layers hit
01692             }
01693           }
01694         }
01695       } // end loop over strips in pretrigger pattern
01696       if (infoV > 1) {
01697         if (layers_hit > 0) LogTrace("CSCCathodeLCTProcessor")
01698           << "cfeb: " << icfeb << "  key_strip: " << key_strip
01699           << "  n_hits: " << layers_hit;
01700       }
01701       // If two or more keys have an equal number of hits, the lower number
01702       // key is taken.  Hence, replace the previous key only if this key has
01703       // more hits.
01704       if (layers_hit > prev_hits) {
01705         prev_hits = layers_hit;
01706         keyStrip[icfeb] = key_strip;  // key with highest hits is LCT key strip
01707         n_hits[icfeb] = layers_hit;   // corresponding hits in envelope
01708       }
01709     }  // end loop over candidate key strips in cfeb
01710   }  // end loop over cfebs
01711 } // latchLCTs -- pre-2007 version.
01712 
01713 
01714 // Pre-2007 version.
01715 void CSCCathodeLCTProcessor::priorityEncode(
01716         const int h_keyStrip[MAX_CFEBS], const unsigned int h_nhits[MAX_CFEBS],
01717         const int d_keyStrip[MAX_CFEBS], const unsigned int d_nhits[MAX_CFEBS],
01718         int keystrip_data[2][7]) {
01719   static const unsigned int hs_thresh = nplanes_hit_pretrig;
01720   //static const unsigned int ds_thresh = nplanes_hit_pretrig;
01721 
01722   int ihits[2]; // hold hits for sorting
01723   int cfebs[2]; // holds CFEB numbers corresponding to highest hits
01724   const int nlcts = 2;
01725   int key_strip[MAX_CFEBS], key_phits[MAX_CFEBS], strip_type[MAX_CFEBS];
01726 
01727   // initialize arrays
01728   for (int ilct = 0; ilct < nlcts; ilct++) {
01729     for (int j = 0; j < 7; j++) keystrip_data[ilct][j] = -1;
01730     ihits[ilct] = 0;
01731     cfebs[ilct] = -1;
01732   }
01733   for (int icfeb = 0; icfeb < MAX_CFEBS; icfeb++) {
01734     key_strip[icfeb]  = -1;
01735     key_phits[icfeb]  = -1;
01736     strip_type[icfeb] = -1;
01737   }
01738 
01739   if (infoV > 1) {
01740     LogTrace("CSCCathodeLCTProcessor")
01741       << ".....................PriorityEncode.......................";
01742     std::ostringstream strstrm;
01743     strstrm << "hkeys:";
01744     for (int icfeb = 0; icfeb < MAX_CFEBS; icfeb++) {
01745       strstrm << std::setw(4) << h_keyStrip[icfeb];
01746     }
01747     strstrm << "\ndkeys:";
01748     for (int icfeb = 0; icfeb < MAX_CFEBS; icfeb++) {
01749       strstrm << std::setw(4) << d_keyStrip[icfeb];
01750     }
01751     LogTrace("CSCCathodeLCTProcessor") << strstrm.str();
01752   }
01753 
01754   // Loop over CFEBs and determine better of half- or di- strip pattern.
01755   // If select halfstrip, promote it by adding an extra bit to its hits.
01756   for (int icfeb = 0; icfeb < MAX_CFEBS; icfeb++) {
01757     if (h_keyStrip[icfeb] != -1 && d_keyStrip[icfeb] != -1) {
01758       if (h_nhits[icfeb] >= hs_thresh) {
01759         key_strip[icfeb] = h_keyStrip[icfeb];
01760         key_phits[icfeb] = h_nhits[icfeb] + 8; // halfstrip promotion
01761         strip_type[icfeb]= 1;
01762       }
01763       // For di-strip envelope there is no requirement that the number of
01764       // layers hit is >= ds_thresh!!!
01765       // else if (d_nhits[icfeb] >= ds_thresh) {
01766       else {
01767         key_strip[icfeb] = d_keyStrip[icfeb];
01768         key_phits[icfeb] = d_nhits[icfeb];
01769         strip_type[icfeb]= 0;
01770       }
01771     }
01772     else if (h_keyStrip[icfeb] != -1) {
01773       if (h_nhits[icfeb] >= hs_thresh) {
01774         key_strip[icfeb] = h_keyStrip[icfeb];
01775         key_phits[icfeb] = h_nhits[icfeb] + 8; // halfstrip promotion
01776         strip_type[icfeb]= 1;
01777       }
01778     }
01779     else if (d_keyStrip[icfeb] != -1) {
01780       // if (d_nhits[icfeb] >= ds_thresh) {
01781         key_strip[icfeb] = d_keyStrip[icfeb];
01782         key_phits[icfeb] = d_nhits[icfeb];
01783         strip_type[icfeb]= 0;
01784       // }
01785     }
01786     if (infoV > 1 && strip_type[icfeb] != -1) {
01787       if (strip_type[icfeb] == 0)
01788         LogTrace("CSCCathodeLCTProcessor")
01789           << "  taking distrip pattern on cfeb " << icfeb;
01790       else if (strip_type[icfeb] == 1)
01791         LogTrace("CSCCathodeLCTProcessor")
01792           << "  taking halfstrip pattern on cfeb " << icfeb;
01793       LogTrace("CSCCathodeLCTProcessor")
01794         << "     cfeb " << icfeb << " key " << key_strip[icfeb]
01795         << " hits " << key_phits[icfeb] << " type " << strip_type[icfeb];
01796     }
01797   }
01798 
01799   // Remove duplicate LCTs at boundaries -- it is possilbe to have key[0]
01800   // be the higher of the two key strips, take this into account, but
01801   // preserve rank of lcts.
01802   int key[MAX_CFEBS];
01803   int loedge, hiedge;
01804 
01805   if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
01806     << "...... Remove Duplicates ......";
01807   for (int icfeb = 0; icfeb < MAX_CFEBS; icfeb++) {
01808     if(strip_type[icfeb] == 0) key[icfeb] = key_strip[icfeb]*4;
01809     else                       key[icfeb] = key_strip[icfeb];
01810   }
01811   for (int icfeb = 0; icfeb < MAX_CFEBS-1; icfeb++) {
01812     if (key[icfeb] >= 0 && key[icfeb+1] >= 0) {
01813       loedge = cfeb_strips[1]*(icfeb*8+7)/8;
01814       hiedge = cfeb_strips[1]*(icfeb*8+9)/8 - 1;
01815       if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
01816         << "  key 1: " << key[icfeb] << "  key 2: " << key[icfeb+1]
01817         << "  low edge:  " << loedge << "  high edge: " << hiedge;
01818       if (key[icfeb] >= loedge && key[icfeb+1] <= hiedge) {
01819         if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
01820           << "Duplicate LCTs found at boundary of CFEB " << icfeb << " ...";
01821         if (key_phits[icfeb+1] > key_phits[icfeb]) {
01822           if (infoV > 1) LogTrace("CSCCathodeLCTProcessor") 
01823             << "   deleting LCT on CFEB " << icfeb;
01824           key_strip[icfeb] = -1;
01825           key_phits[icfeb] = -1;
01826         }
01827         else {
01828           if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
01829             << "   deleting LCT on CFEB " << icfeb+1;
01830           key_strip[icfeb+1] = -1;
01831           key_phits[icfeb+1] = -1;
01832         }
01833       }
01834     }
01835   }
01836 
01837   // Now loop over CFEBs and pick best two lcts based on no. hits in envelope.
01838   // In case of equal quality, select the one on lower-numbered CFEBs.
01839   if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
01840     << "\n...... Select best LCTs  ......";
01841   for (int icfeb = 0; icfeb < MAX_CFEBS; icfeb++) {
01842     if (key_phits[icfeb] > ihits[0]) {
01843       ihits[1] = ihits[0];
01844       cfebs[1] = cfebs[0];
01845       ihits[0] = key_phits[icfeb];
01846       cfebs[0] = icfeb;
01847       if (infoV > 1) {
01848         std::ostringstream strstrm;
01849         for (int icfeb = 0; icfeb < MAX_CFEBS; icfeb++) {
01850           strstrm << std::setw(4) << strip_type[icfeb];
01851         }
01852         LogTrace("CSCCathodeLCTProcessor")
01853           << "strip_type" << strstrm.str()
01854           << "\n best: ihits " << ihits[0] << " cfeb " << cfebs[0]
01855           << " strip_type " << ((cfebs[0] >= 0) ? strip_type[cfebs[0]] : -1)
01856           << "\n next: ihits " << ihits[1] << " cfeb " << cfebs[1]
01857           << " strip_type " << ((cfebs[1] >= 0) ? strip_type[cfebs[1]] : -1);
01858       }
01859     }
01860     else if (key_phits[icfeb] > ihits[1]) {
01861       ihits[1] = key_phits[icfeb];
01862       cfebs[1] = icfeb;
01863       if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
01864         << "\n next: ihits " << ihits[1] << " cfeb " << cfebs[1]
01865         << " strip_type " << ((cfebs[1] >= 0) ? strip_type[cfebs[1]] : -1);
01866     }
01867   }
01868 
01869   // fill lct data array key strip with 2 highest hit lcts (if they exist)
01870   int jlct = 0;
01871   for (int ilct = 0; ilct < nlcts; ilct++) {
01872     if (cfebs[ilct] != -1) {
01873       keystrip_data[jlct][CLCT_CFEB]       = cfebs[ilct];
01874       keystrip_data[jlct][CLCT_STRIP]      = key_strip[cfebs[ilct]];
01875       keystrip_data[jlct][CLCT_STRIP_TYPE] = strip_type[cfebs[ilct]];
01876       if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
01877         << "filling key: " << key_strip[cfebs[ilct]]
01878         << " type: " << strip_type[cfebs[ilct]];
01879       jlct++;
01880     }
01881   }
01882 } // priorityEncode -- pre-2007 version.
01883 
01884 
01885 // Pre-2007 version.
01886 void CSCCathodeLCTProcessor::getKeyStripData(
01887                 const unsigned int h_pulse[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS],
01888                 const unsigned int d_pulse[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS],
01889                 int keystrip_data[2][7], const int first_bx) {
01890 
01891   int lct_pattern[NUM_PATTERN_STRIPS];
01892   int this_layer, this_strip;
01893   unsigned int quality = 0, bend = 0;
01894   unsigned int best_quality, best_pattern;
01895   bool valid[2] = {false,false};
01896 
01897   // Time at which TMB latches LCTs.
01898   int latch_bx = first_bx + drift_delay;
01899 
01900   // Look at keystrips determined from priorityEncode and find their best
01901   // pattern based on number of hits matching that pattern (quality).  Also
01902   // find bend angle.  There are multiple patterns available for each keystrip.
01903 
01904   if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
01905     << "...............getKeyStripData....................";
01906 
01907   for (int ilct = 0; ilct < 2; ilct++) {
01908     if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
01909       << "lct " << ilct << " keystrip " << keystrip_data[ilct][CLCT_STRIP]
01910       << " type " << keystrip_data[ilct][CLCT_STRIP_TYPE];
01911     if (keystrip_data[ilct][CLCT_STRIP] == -1) {// flag set in priorityEncode()
01912       if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
01913         << "no lct at ilct " << ilct;
01914       continue;
01915     }
01916     for (int pattern_strip = 0; pattern_strip < NUM_PATTERN_STRIPS;
01917          pattern_strip++) {
01918       lct_pattern[pattern_strip] = -999;
01919       this_layer = pre_hit_pattern[0][pattern_strip];
01920       this_strip = pre_hit_pattern[1][pattern_strip] +
01921         keystrip_data[ilct][CLCT_STRIP];
01922       // This conditional statement prevents us from looking at strips
01923       // that don't exist along the chamber boundaries.
01924       if (keystrip_data[ilct][CLCT_STRIP_TYPE] == 1) {
01925         if (this_strip >= 0 && this_strip < CSCConstants::NUM_HALF_STRIPS) {
01926           // Now look at one-shots in bx where TMB latches the LCTs
01927           if (((h_pulse[this_layer][this_strip] >> latch_bx) & 1) == 1)
01928             lct_pattern[pattern_strip] = 1;
01929         }
01930       }
01931       else {
01932         if (this_strip >= 0 && this_strip < CSCConstants::NUM_DI_STRIPS) {
01933           // Now look at one-shots in bx where TMB latches the LCTs
01934           if (((d_pulse[this_layer][this_strip] >> latch_bx) & 1) == 1)
01935             lct_pattern[pattern_strip] = 1;
01936         }
01937       }
01938     }
01939 
01940     // Find best pattern and quality associated with key by looping over all 
01941     // possible patterns
01942     best_quality = 0;
01943     best_pattern = 0;
01944 
01945     for (unsigned int pattern_num = 0;
01946          pattern_num < CSCConstants::NUM_CLCT_PATTERNS_PRE_TMB07; pattern_num++) {
01947       getPattern(pattern_num, lct_pattern, quality, bend);
01948       if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
01949           << "pattern " << pattern_num << " quality " << quality
01950           << " bend " << bend;
01951       // Number of layers hit matching a pattern template is compared
01952       // to nplanes_hit_pattern.  The threshold is the same for both half- and
01953       // di-strip patterns.
01954       if (quality >= nplanes_hit_pattern) {
01955         // If the number of matches is the same for two pattern templates,
01956         // the higher pattern-template number is selected.
01957         if ((quality == best_quality && pattern_num > best_pattern) ||
01958             (quality >  best_quality)) {
01959           if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
01960             << "valid = true at quality " << quality
01961             << "  thresh " << nplanes_hit_pattern;
01962           valid[ilct] = true;
01963           keystrip_data[ilct][CLCT_PATTERN]    = pattern_num;
01964           keystrip_data[ilct][CLCT_BEND]       = bend;
01965           keystrip_data[ilct][CLCT_BX]         = first_bx;
01966           //keystrip_data[ilct][CLCT_STRIP_TYPE] = stripType;
01967           keystrip_data[ilct][CLCT_QUALITY]    = quality;
01968           best_quality = quality;
01969           best_pattern = pattern_num;
01970         }
01971       }
01972     }
01973 
01974     if (!valid[ilct]) {
01975       keystrip_data[ilct][CLCT_STRIP] = -1;  // delete lct
01976       if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
01977         << "lct " << ilct << " not over threshold: deleting";
01978     }
01979     else {
01980       if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
01981         << "\n" << "--------- final LCT: " << ilct << " -------------\n"
01982         << " key strip "   << keystrip_data[ilct][CLCT_STRIP]
01983         << " pattern_num " << keystrip_data[ilct][CLCT_PATTERN]
01984         << " quality "     << keystrip_data[ilct][CLCT_QUALITY]
01985         << " bend "        << keystrip_data[ilct][CLCT_BEND]
01986         << " bx "          << keystrip_data[ilct][CLCT_BX]
01987         << " type "        << keystrip_data[ilct][CLCT_STRIP_TYPE] << "\n";
01988     }
01989   } // end loop over lcts
01990 } // getKeyStripData -- pre-2007 version.
01991 
01992 
01993 // Pre-2007 version.
01994 void CSCCathodeLCTProcessor::getPattern(unsigned int pattern_num,
01995                          const int strip_value[NUM_PATTERN_STRIPS],
01996                          unsigned int& quality, unsigned int& bend) {
01997 
01998   // This function takes strip "one-shots" at the correct bx to find out
01999   // which hits fall within a certain pattern.  Quality and bend are then
02000   // calculated based on which strip pattern and how many layers were hit
02001   // within the pattern.
02002 
02003   unsigned int layers_hit = 0;
02004   bool hit_layer[CSCConstants::NUM_LAYERS];
02005 
02006   // Clear hit_layer array to keep track of number of layers hit.
02007   for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++)
02008     hit_layer[i_layer] = false;
02009 
02010   // Loop over all designated patterns.
02011   for (int strip_num = 0; strip_num < NUM_PATTERN_STRIPS; strip_num++){
02012     if (strip_value[strip_num] == 1){
02013       for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++){
02014         // Loop over layer and see if corresponding strip is on same layer
02015         // If so then increment number of hits.
02016         if (i_layer == pattern[pattern_num][strip_num]){
02017           // If layer has no hits, then increment number of layers hit.
02018           if (hit_layer[i_layer] == false){
02019             layers_hit++;
02020             hit_layer[i_layer] = true;
02021           }
02022         }
02023       }
02024     }
02025   }
02026   // Get bend value from pattern.
02027   bend = pattern[pattern_num][NUM_PATTERN_STRIPS];
02028   quality = layers_hit;
02029 
02030 } // getPattern -- pre-2007 version.
02031 
02032 
02033 // --------------------------------------------------------------------------
02034 // The code below is a description of the 2007 version of the CLCT
02035 // algorithm (half-strips only).  It was first used in 2008 CRUZET runs,
02036 // and later in CRAFT.  The algorithm became the default version for
02037 // Monte Carlo studies in March 2008 (CMSSW_2_0_0).
02038 // --------------------------------------------------------------------------
02039 // TMB-07 version.
02040 std::vector<CSCCLCTDigi> CSCCathodeLCTProcessor::findLCTs(const std::vector<int> halfstrip[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS]) {
02041   std::vector<CSCCLCTDigi> lctList;
02042 
02043   // Max. number of half-strips for this chamber.
02044   const int maxHalfStrips = 2*numStrips + 1;
02045 
02046   if (infoV > 1) dumpDigis(halfstrip, 1, maxHalfStrips);
02047 
02048   // Test beam version of TMB pretrigger and LCT sorting
02049   enum {max_lcts = 2};
02050   // 2 possible LCTs per CSC x 7 LCT quantities
02051   int keystrip_data[max_lcts][7] = {{0}};
02052   unsigned int pulse[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS];
02053 
02054   // Fire half-strip one-shots for hit_persist bx's (4 bx's by default).
02055   pulseExtension(halfstrip, maxHalfStrips, pulse);
02056 
02057   unsigned int start_bx = start_bx_shift;
02058   // Stop drift_delay bx's short of fifo_tbins since at later bx's we will
02059   // not have a full set of hits to start pattern search anyway.
02060   unsigned int stop_bx  = fifo_tbins - drift_delay;
02061   // Allow for more than one pass over the hits in the time window.
02062   while (start_bx < stop_bx) {
02063     // All half-strip pattern envelopes are evaluated simultaneously, on every
02064     // clock cycle.
02065     int first_bx = 999;
02066     bool pre_trig = preTrigger(pulse, start_bx, first_bx);
02067 
02068     // If any of half-strip envelopes has enough layers hit in it, TMB
02069     // will pre-trigger.
02070     if (pre_trig) {
02071       thePreTriggerBXs.push_back(first_bx);
02072       if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
02073         << "..... pretrigger at bx = " << first_bx
02074         << "; waiting drift delay .....";
02075 
02076       // TMB latches LCTs drift_delay clocks after pretrigger.
02077       int latch_bx = first_bx + drift_delay;
02078       bool hits_in_time = ptnFinding(pulse, maxHalfStrips, latch_bx);
02079       if (infoV > 1) {
02080         if (hits_in_time) {
02081           for (int hstrip = stagger[CSCConstants::KEY_CLCT_LAYER-1];
02082                hstrip < maxHalfStrips; hstrip++) {
02083             if (nhits[hstrip] > 0) {
02084               LogTrace("CSCCathodeLCTProcessor")
02085                 << " bx = " << std::setw(2) << latch_bx << " --->"
02086                 << " halfstrip = " << std::setw(3) << hstrip
02087                 << " best pid = "  << std::setw(2) << best_pid[hstrip]
02088                 << " nhits = "     << nhits[hstrip];
02089             }
02090           }
02091         }
02092       }
02093       // The pattern finder runs continuously, so another pre-trigger
02094       // could occur already at the next bx.
02095       start_bx = first_bx + 1;
02096 
02097       // Quality for sorting.
02098       int quality[CSCConstants::NUM_HALF_STRIPS];
02099       int best_halfstrip[max_lcts], best_quality[max_lcts];
02100       for (int ilct = 0; ilct < max_lcts; ilct++) {
02101         best_halfstrip[ilct] = -1;
02102         best_quality[ilct]   =  0;
02103       }
02104 
02105       // Calculate quality from pattern id and number of hits, and
02106       // simultaneously select best-quality LCT.
02107       if (hits_in_time) {
02108         for (int hstrip = stagger[CSCConstants::KEY_CLCT_LAYER-1];
02109              hstrip < maxHalfStrips; hstrip++) {
02110           // The bend-direction bit pid[0] is ignored (left and right
02111           // bends have equal quality).
02112           quality[hstrip] = (best_pid[hstrip] & 14) | (nhits[hstrip] << 5);
02113           if (quality[hstrip] > best_quality[0]) {
02114             best_halfstrip[0] = hstrip;
02115             best_quality[0]   = quality[hstrip];
02116           }
02117           if (infoV > 1 && quality[hstrip] > 0) {
02118             LogTrace("CSCCathodeLCTProcessor")
02119               << " 1st CLCT: halfstrip = " << std::setw(3) << hstrip
02120               << " quality = "             << std::setw(3) << quality[hstrip]
02121               << " best halfstrip = " << std::setw(3) << best_halfstrip[0]
02122               << " best quality = "   << std::setw(3) << best_quality[0];
02123           }
02124         }
02125       }
02126 
02127       // If 1st best CLCT is found, look for the 2nd best.
02128       if (best_halfstrip[0] >= 0) {
02129         // Mark keys near best CLCT as busy by setting their quality to
02130         // zero, and repeat the search.
02131         markBusyKeys(best_halfstrip[0], best_pid[best_halfstrip[0]], quality);
02132 
02133         for (int hstrip = stagger[CSCConstants::KEY_CLCT_LAYER-1];
02134            hstrip < maxHalfStrips; hstrip++) {
02135           if (quality[hstrip] > best_quality[1]) {
02136             best_halfstrip[1] = hstrip;
02137             best_quality[1]   = quality[hstrip];
02138           }
02139           if (infoV > 1 && quality[hstrip] > 0) {
02140             LogTrace("CSCCathodeLCTProcessor")
02141               << " 2nd CLCT: halfstrip = " << std::setw(3) << hstrip
02142               << " quality = "             << std::setw(3) << quality[hstrip]
02143               << " best halfstrip = " << std::setw(3) << best_halfstrip[1]
02144               << " best quality = "   << std::setw(3) << best_quality[1];
02145           }
02146         }
02147 
02148         // Pattern finder.
02149         bool ptn_trig = false;
02150         for (int ilct = 0; ilct < max_lcts; ilct++) {
02151           int best_hs = best_halfstrip[ilct];
02152           if (best_hs >= 0 && nhits[best_hs] >= nplanes_hit_pattern) {
02153             ptn_trig = true;
02154             keystrip_data[ilct][CLCT_PATTERN]    = best_pid[best_hs];
02155             keystrip_data[ilct][CLCT_BEND]       =
02156               pattern2007[best_pid[best_hs]][NUM_PATTERN_HALFSTRIPS];
02157             // Remove stagger if any.
02158             keystrip_data[ilct][CLCT_STRIP]      =
02159               best_hs - stagger[CSCConstants::KEY_CLCT_LAYER-1];
02160             keystrip_data[ilct][CLCT_BX]         = first_bx;
02161             keystrip_data[ilct][CLCT_STRIP_TYPE] = 1;           // obsolete
02162             keystrip_data[ilct][CLCT_QUALITY]    = nhits[best_hs];
02163             keystrip_data[ilct][CLCT_CFEB]       =
02164               keystrip_data[ilct][CLCT_STRIP]/cfeb_strips[1];
02165             int halfstrip_in_cfeb = keystrip_data[ilct][CLCT_STRIP] -
02166               cfeb_strips[1]*keystrip_data[ilct][CLCT_CFEB];
02167 
02168             if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
02169               << " Final selection: ilct " << ilct
02170               << " key halfstrip " << keystrip_data[ilct][CLCT_STRIP]
02171               << " quality "       << keystrip_data[ilct][CLCT_QUALITY]
02172               << " pattern "       << keystrip_data[ilct][CLCT_PATTERN]
02173               << " bx "            << keystrip_data[ilct][CLCT_BX];
02174 
02175             CSCCLCTDigi thisLCT(1, keystrip_data[ilct][CLCT_QUALITY],
02176                                 keystrip_data[ilct][CLCT_PATTERN],
02177                                 keystrip_data[ilct][CLCT_STRIP_TYPE],
02178                                 keystrip_data[ilct][CLCT_BEND],
02179                                 halfstrip_in_cfeb,
02180                                 keystrip_data[ilct][CLCT_CFEB],
02181                                 keystrip_data[ilct][CLCT_BX]);
02182             lctList.push_back(thisLCT);
02183           }
02184         }
02185 
02186         if (ptn_trig) {
02187           // Once there was a trigger, CLCT pre-trigger state machine
02188           // checks the number of hits that lie on a pattern template
02189           // at every bx, and waits for it to drop below threshold.
02190           // The search for CLCTs resumes only when the number of hits
02191           // drops below threshold.
02192           start_bx = fifo_tbins;
02193           // Stop checking drift_delay bx's short of fifo_tbins since
02194           // at later bx's we won't have a full set of hits for a
02195           // pattern search anyway.
02196           unsigned int stop_time = fifo_tbins - drift_delay;
02197           for (unsigned int bx = latch_bx + 1; bx < stop_time; bx++) {
02198             bool return_to_idle = true;
02199             bool hits_in_time = ptnFinding(pulse, maxHalfStrips, bx);
02200             if (hits_in_time) {
02201               for (int hstrip = stagger[CSCConstants::KEY_CLCT_LAYER-1];
02202                    hstrip < maxHalfStrips; hstrip++) {
02203                 if (nhits[hstrip] >= nplanes_hit_pattern) {
02204                   if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
02205                     << " State machine busy at bx = " << bx;
02206                   return_to_idle = false;
02207                   break;
02208                 }
02209               }
02210             }
02211             if (return_to_idle) {
02212               if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
02213                 << " State machine returns to idle state at bx = " << bx;
02214               start_bx = bx;
02215               break;
02216             }
02217           }
02218         }
02219       }
02220     }
02221     else {
02222       start_bx = first_bx + 1; // no dead time
02223     }
02224   }
02225 
02226   return lctList;
02227 } // findLCTs -- TMB-07 version.
02228 
02229 
02230 // Common to all versions.
02231 void CSCCathodeLCTProcessor::pulseExtension(
02232  const std::vector<int> time[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS],
02233  const int nStrips,
02234  unsigned int pulse[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS]) {
02235 
02236   static unsigned int bits_in_pulse = 8*sizeof(pulse[0][0]);
02237 
02238   // Clear pulse array.  This array will be used as a bit representation of
02239   // hit times.  For example: if strip[1][2] has a value of 3, then 1 shifted
02240   // left 3 will be bit pattern of pulse[1][2].  This would make the pattern
02241   // look like 0000000000001000.  Then add on additional bits to signify
02242   // the duration of a signal (hit_persist, formerly bx_width) to simulate
02243   // the TMB's drift delay.  So for the same pulse[1][2] with a hit_persist
02244   // of 3 would look like 0000000000111000.  This is similating the digital
02245   // one-shot in the TMB.
02246   for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++)
02247     for (int i_strip = 0; i_strip < nStrips; i_strip++)
02248       pulse[i_layer][i_strip] = 0;
02249 
02250   // Loop over all layers and halfstrips.
02251   for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
02252     for (int i_strip = 0; i_strip < nStrips; i_strip++) {
02253       // If there is a hit, simulate digital one-shot persistence starting
02254       // in the bx of the initial hit.  Fill this into pulse[][].
02255       if (time[i_layer][i_strip].size() > 0) {
02256         std::vector<int> bx_times = time[i_layer][i_strip];
02257         for (unsigned int i = 0; i < bx_times.size(); i++) {
02258           // Check that min and max times are within the allowed range.
02259           if (bx_times[i] < 0 || bx_times[i] + hit_persist >= bits_in_pulse) {
02260             if (infoV > 0) edm::LogWarning("L1CSCTPEmulatorOutOfTimeDigi")
02261               << "+++ BX time of comparator digi (halfstrip = " << i_strip
02262               << " layer = " << i_layer << ") bx = " << bx_times[i]
02263               << " is not within the range (0-" << bits_in_pulse
02264               << "] allowed for pulse extension.  Skip this digi! +++\n";
02265             continue;
02266           }
02267           if (bx_times[i] >= start_bx_shift) {
02268             for (unsigned int bx = bx_times[i]; bx < bx_times[i] + hit_persist; ++bx)
02269               pulse[i_layer][i_strip] = pulse[i_layer][i_strip] | (1 << bx);
02270           }
02271         }
02272       }
02273     }
02274   }
02275 } // pulseExtension.
02276 
02277 
02278 // TMB-07 version.
02279 bool CSCCathodeLCTProcessor::preTrigger(
02280   const unsigned int pulse[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS],
02281                                         const int start_bx, int& first_bx) {
02282   if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
02283     << "....................PreTrigger...........................";
02284 
02285   // Max. number of half-strips for this chamber.
02286   const int nStrips = 2*numStrips + 1;
02287 
02288   bool pre_trig = false;
02289   // Now do a loop over bx times to see (if/when) track goes over threshold
02290   for (unsigned int bx_time = start_bx; bx_time < fifo_tbins; bx_time++) {
02291     // For any given bunch-crossing, start at the lowest keystrip and look for
02292     // the number of separate layers in the pattern for that keystrip that have
02293     // pulses at that bunch-crossing time.  Do the same for the next keystrip, 
02294     // etc.  Then do the entire process again for the next bunch-crossing, etc
02295     // until you find a pre-trigger.
02296     bool hits_in_time = ptnFinding(pulse, nStrips, bx_time);
02297     if (hits_in_time) {
02298       for (int hstrip = stagger[CSCConstants::KEY_CLCT_LAYER-1];
02299            hstrip < nStrips; hstrip++) {
02300         if (infoV > 1) {
02301           if (nhits[hstrip] > 0) {
02302             LogTrace("CSCCathodeLCTProcessor")
02303               << " bx = " << std::setw(2) << bx_time << " --->"
02304               << " halfstrip = " << std::setw(3) << hstrip
02305               << " best pid = "  << std::setw(2) << best_pid[hstrip]
02306               << " nhits = "     << nhits[hstrip];
02307           }
02308         }
02309         ispretrig[hstrip] = 0;
02310         if (nhits[hstrip]    >= nplanes_hit_pretrig &&
02311             best_pid[hstrip] >= pid_thresh_pretrig) {
02312           pre_trig = true;
02313           ispretrig[hstrip] = 1;
02314         }
02315       }
02316 
02317       if (pre_trig) {
02318         first_bx = bx_time; // bx at time of pretrigger
02319         return true;
02320       }
02321     }
02322   } // end loop over bx times
02323 
02324   if (infoV > 1) LogTrace("CSCCathodeLCTProcessor") <<
02325                    "no pretrigger, returning \n";
02326   first_bx = fifo_tbins;
02327   return false;
02328 } // preTrigger -- TMB-07 version.
02329 
02330 
02331 // TMB-07 version.
02332 bool CSCCathodeLCTProcessor::ptnFinding(
02333            const unsigned int pulse[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS],
02334            const int nStrips, const unsigned int bx_time)
02335 {
02336   if (bx_time >= fifo_tbins) return false;
02337 
02338   // This loop is a quick check of a number of layers hit at bx_time: since
02339   // most of the time it is 0, this check helps to speed-up the execution
02340   // substantially.
02341   unsigned int layers_hit = 0;
02342   for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++)
02343   {
02344     for (int i_hstrip = 0; i_hstrip < nStrips; i_hstrip++)
02345     {
02346       if (((pulse[i_layer][i_hstrip] >> bx_time) & 1) == 1)
02347       {
02348         layers_hit++;
02349         break;
02350       }
02351     }
02352   }
02353   if (layers_hit < nplanes_hit_pretrig) return false;
02354 
02355   for (int key_hstrip = 0; key_hstrip < nStrips; key_hstrip++)
02356   {
02357     best_pid[key_hstrip] = 0;
02358     nhits[key_hstrip] = 0;
02359     first_bx_corrected[key_hstrip] = -999;
02360   }
02361 
02362   // Loop over candidate key strips.
02363   bool hit_layer[CSCConstants::NUM_LAYERS];
02364   for (int key_hstrip = stagger[CSCConstants::KEY_CLCT_LAYER - 1]; key_hstrip < nStrips; key_hstrip++)
02365   {
02366     // Loop over patterns and look for hits matching each pattern.
02367     for (unsigned int pid = CSCConstants::NUM_CLCT_PATTERNS - 1; pid >= pid_thresh_pretrig; pid--)
02368     {
02369       layers_hit = 0;
02370       for (int ilayer = 0; ilayer < CSCConstants::NUM_LAYERS; ilayer++)
02371         hit_layer[ilayer] = false;
02372 
02373       double num_pattern_hits=0., times_sum=0.;
02374       std::multiset<int> mset_for_median;
02375       mset_for_median.clear();
02376 
02377       // Loop over halfstrips in trigger pattern mask and calculate the
02378       // "absolute" halfstrip number for each.
02379       for (int strip_num = 0; strip_num < NUM_PATTERN_HALFSTRIPS; strip_num++)
02380       {
02381         int this_layer = pattern2007[pid][strip_num];
02382         if (this_layer >= 0 && this_layer < CSCConstants::NUM_LAYERS)
02383         {
02384           int this_strip = pattern2007_offset[strip_num] + key_hstrip;
02385           if (this_strip >= 0 && this_strip < nStrips) {
02386             if (infoV > 3) LogTrace("CSCCathodeLCTProcessor")
02387               << " In ptnFinding: key_strip = " << key_hstrip
02388               << " pid = " << pid << " strip_num = " << strip_num
02389               << " layer = " << this_layer << " strip = " << this_strip;
02390             // Determine if "one shot" is high at this bx_time
02391             if (((pulse[this_layer][this_strip] >> bx_time) & 1) == 1)
02392             {
02393               if (hit_layer[this_layer] == false)
02394               {
02395                 hit_layer[this_layer] = true;
02396                 layers_hit++;     // determines number of layers hit
02397               }
02398 
02399               // find at what bx did pulse on this halsfstrip&layer have started
02400               // use hit_pesrist constraint on how far back we can go
02401               int first_bx_layer = bx_time;
02402               for (unsigned int dbx = 0; dbx < hit_persist; dbx++)
02403               {
02404                 if (((pulse[this_layer][this_strip] >> (first_bx_layer - 1)) & 1) == 1)
02405                   first_bx_layer--;
02406                 else
02407                   break;
02408               }
02409               times_sum += (double) first_bx_layer;
02410               num_pattern_hits += 1.;
02411               mset_for_median.insert(first_bx_layer);
02412               if (infoV > 2)
02413                 LogTrace("CSCCathodeLCTProcessor") << " 1st bx in layer: " << first_bx_layer << " sum bx: " << times_sum
02414                     << " #pat. hits: " << num_pattern_hits;
02415             }
02416           }
02417         }
02418       } // end loop over strips in pretrigger pattern
02419 
02420       if (layers_hit > nhits[key_hstrip])
02421       {
02422         best_pid[key_hstrip] = pid;
02423         nhits[key_hstrip] = layers_hit;
02424 
02425         // calculate median
02426         const int sz = mset_for_median.size();
02427         if (sz>0){
02428           std::multiset<int>::iterator im = mset_for_median.begin();
02429           if (sz>1) std::advance(im,sz/2-1);
02430           if (sz==1) first_bx_corrected[key_hstrip] = *im;
02431           else if ((sz % 2) == 1) first_bx_corrected[key_hstrip] = *(++im);
02432           else first_bx_corrected[key_hstrip] = ((*im) + (*(++im)))/2;
02433 
02434           if (infoV > 1) {
02435             char bxs[300]="";
02436             for (im = mset_for_median.begin(); im != mset_for_median.end(); im++)
02437               sprintf(bxs,"%s %d", bxs, *im);
02438             LogTrace("CSCCathodeLCTProcessor")
02439               <<"bx="<<bx_time<<" bx_cor="<< first_bx_corrected[key_hstrip]<<"  bxset="<<bxs;
02440           }
02441         }
02442 
02443         // Do not loop over the other (worse) patterns if max. numbers of
02444         // hits is found.
02445         if (nhits[key_hstrip] == CSCConstants::NUM_LAYERS) break;
02446       }
02447     } // end loop over pid
02448   } // end loop over candidate key strips
02449   return true;
02450 } // ptnFinding -- TMB-07 version.
02451 
02452 
02453 // TMB-07 version.
02454 void CSCCathodeLCTProcessor::markBusyKeys(const int best_hstrip,
02455                                           const int best_patid,
02456                                 int quality[CSCConstants::NUM_HALF_STRIPS]) {
02457   int nspan = min_separation;
02458   int pspan = min_separation;
02459 
02460   // if dynamic spacing is enabled, separation is defined by pattern width
02461   //if (dynamic_spacing)
02462   //  nspan = pspan = pattern2007[best_patid][NUM_PATTERN_HALFSTRIPS+1]-1;
02463 
02464   for (int hstrip = best_hstrip-nspan; hstrip <= best_hstrip+pspan; hstrip++) {
02465     if (hstrip >= 0 && hstrip < CSCConstants::NUM_HALF_STRIPS) {
02466       quality[hstrip] = 0;
02467     }
02468   }
02469 } // markBusyKeys -- TMB-07 version.
02470 
02471 
02472 
02473 // --------------------------------------------------------------------------
02474 // The code below is for SLHC studies of the CLCT algorithm (half-strips only).
02475 // --------------------------------------------------------------------------
02476 // SLHC version.
02477 std::vector<CSCCLCTDigi>
02478 CSCCathodeLCTProcessor::findLCTsSLHC(const std::vector<int> halfstrip[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS])
02479 {
02480   std::vector<CSCCLCTDigi> lctList;
02481 
02482   // Max. number of half-strips for this chamber.
02483   const int maxHalfStrips = 2 * numStrips + 1;
02484 
02485   if (infoV > 1) dumpDigis(halfstrip, 1, maxHalfStrips);
02486 
02487   enum { max_lcts = 2 };
02488 
02489   // keeps dead-time zones around key halfstrips of triggered CLCTs
02490   bool busyMap[CSCConstants::NUM_HALF_STRIPS][MAX_CLCT_BINS];
02491   for (int i = 0; i < CSCConstants::NUM_HALF_STRIPS; i++)
02492     for (int j = 0; j < MAX_CLCT_BINS; j++)
02493       busyMap[i][j] = false;
02494 
02495   std::vector<CSCCLCTDigi> lctListBX;
02496 
02497   unsigned int pulse[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS];
02498 
02499   // Fire half-strip one-shots for hit_persist bx's (4 bx's by default).
02500   pulseExtension(halfstrip, maxHalfStrips, pulse);
02501 
02502   unsigned int start_bx = start_bx_shift;
02503   // Stop drift_delay bx's short of fifo_tbins since at later bx's we will
02504   // not have a full set of hits to start pattern search anyway.
02505   unsigned int stop_bx = fifo_tbins - drift_delay;
02506 
02507   // Allow for more than one pass over the hits in the time window.
02508   // Do search in every BX
02509   while (start_bx < stop_bx)
02510   {
02511     lctListBX.clear();
02512 
02513     // All half-strip pattern envelopes are evaluated simultaneously, on every clock cycle.
02514     int first_bx = 999;
02515     bool pre_trig = preTrigger(pulse, start_bx, first_bx);
02516 
02517     // If any of half-strip envelopes has enough layers hit in it, TMB
02518     // will pre-trigger.
02519     if (pre_trig)
02520     {
02521       if (infoV > 1)
02522         LogTrace("CSCCathodeLCTProcessor") << "..... pretrigger at bx = " << first_bx << "; waiting drift delay .....";
02523 
02524       // TMB latches LCTs drift_delay clocks after pretrigger.
02525       int latch_bx = first_bx + drift_delay;
02526       bool hits_in_time = ptnFinding(pulse, maxHalfStrips, latch_bx);
02527       if (infoV > 1)
02528       {
02529         if (hits_in_time)
02530         {
02531           for (int hstrip = stagger[CSCConstants::KEY_CLCT_LAYER - 1]; hstrip < maxHalfStrips; hstrip++)
02532           {
02533             if (nhits[hstrip] > 0)
02534             {
02535               LogTrace("CSCCathodeLCTProcessor") << " bx = " << std::setw(2) << latch_bx << " --->" << " halfstrip = "
02536                   << std::setw(3) << hstrip << " best pid = " << std::setw(2) << best_pid[hstrip] << " nhits = " << nhits[hstrip];
02537             }
02538           }
02539         }
02540       }
02541       // The pattern finder runs continuously, so another pre-trigger
02542       // could occur already at the next bx.
02543       start_bx = first_bx + 1;
02544 
02545       // 2 possible LCTs per CSC x 7 LCT quantities per BX
02546       int keystrip_data[max_lcts][7] = {{0}};
02547 
02548       // Quality for sorting.
02549       int quality[CSCConstants::NUM_HALF_STRIPS];
02550       int best_halfstrip[max_lcts], best_quality[max_lcts];
02551       for (int ilct = 0; ilct < max_lcts; ilct++)
02552       {
02553         best_halfstrip[ilct] = -1;
02554         best_quality[ilct] = 0;
02555       }
02556 
02557       bool pretrig_zone[CSCConstants::NUM_HALF_STRIPS];
02558 
02559       // Calculate quality from pattern id and number of hits, and
02560       // simultaneously select best-quality LCT.
02561       if (hits_in_time)
02562       {
02563         // first, mark half-strip zones around pretriggers
02564         // that happened at the current first_bx
02565         for (int hstrip = 0; hstrip < CSCConstants::NUM_HALF_STRIPS; hstrip++)
02566           pretrig_zone[hstrip] = 0;
02567         for (int hstrip = 0; hstrip < CSCConstants::NUM_HALF_STRIPS; hstrip++)
02568         {
02569           if (ispretrig[hstrip])
02570           {
02571             int min_hs = hstrip - pretrig_trig_zone;
02572             int max_hs = hstrip + pretrig_trig_zone;
02573             if (min_hs < 0)
02574               min_hs = 0;
02575             if (max_hs > CSCConstants::NUM_HALF_STRIPS - 1)
02576               max_hs = CSCConstants::NUM_HALF_STRIPS - 1;
02577             for (int hs = min_hs; hs <= max_hs; hs++)
02578               pretrig_zone[hs] = 1;
02579             if (infoV > 1)
02580               LogTrace("CSCCathodeLCTProcessor") << " marked pretrigger halfstrip zone [" << min_hs << "," << max_hs << "]";
02581           }
02582         }
02583 
02584         for (int hstrip = stagger[CSCConstants::KEY_CLCT_LAYER - 1]; hstrip < maxHalfStrips; hstrip++)
02585         {
02586           // The bend-direction bit pid[0] is ignored (left and right bends have equal quality).
02587           quality[hstrip] = (best_pid[hstrip] & 14) | (nhits[hstrip] << 5);
02588           // do not consider halfstrips:
02589           //   - out of pretrigger-trigger zones
02590           //   - in busy zones from previous trigger
02591           if (quality[hstrip] > best_quality[0] &&
02592               pretrig_zone[hstrip] &&
02593               !busyMap[hstrip][first_bx] )
02594           {
02595             best_halfstrip[0] = hstrip;
02596             best_quality[0] = quality[hstrip];
02597             if (infoV > 1)
02598             {
02599               LogTrace("CSCCathodeLCTProcessor") << " 1st CLCT: halfstrip = " << std::setw(3) << hstrip << " quality = "
02600                   << std::setw(3) << quality[hstrip] << " best halfstrip = " << std::setw(3) << best_halfstrip[0]
02601                   << " best quality = " << std::setw(3) << best_quality[0];
02602             }
02603           }
02604         }
02605       }
02606 
02607       // If 1st best CLCT is found, look for the 2nd best.
02608       if (best_halfstrip[0] >= 0)
02609       {
02610         // Mark keys near best CLCT as busy by setting their quality to zero, and repeat the search.
02611         markBusyKeys(best_halfstrip[0], best_pid[best_halfstrip[0]], quality);
02612 
02613         for (int hstrip = stagger[CSCConstants::KEY_CLCT_LAYER - 1]; hstrip < maxHalfStrips; hstrip++)
02614         {
02615           if (quality[hstrip] > best_quality[1] &&
02616               pretrig_zone[hstrip] &&
02617               !busyMap[hstrip][first_bx] )
02618           {
02619             best_halfstrip[1] = hstrip;
02620             best_quality[1] = quality[hstrip];
02621             if (infoV > 1)
02622             {
02623               LogTrace("CSCCathodeLCTProcessor") << " 2nd CLCT: halfstrip = " << std::setw(3) << hstrip << " quality = "
02624                   << std::setw(3) << quality[hstrip] << " best halfstrip = " << std::setw(3) << best_halfstrip[1]
02625                   << " best quality = " << std::setw(3) << best_quality[1];
02626             }
02627           }
02628         }
02629 
02630         // Pattern finder.
02631         bool ptn_trig = false;
02632         for (int ilct = 0; ilct < max_lcts; ilct++)
02633         {
02634           int best_hs = best_halfstrip[ilct];
02635           if (best_hs >= 0 && nhits[best_hs] >= nplanes_hit_pattern)
02636           {
02637             int bx  = first_bx;
02638             int fbx = first_bx_corrected[best_hs];
02639             if (use_corrected_bx) {
02640               bx  = fbx;
02641               fbx = first_bx;
02642             }
02643             ptn_trig = true;
02644             keystrip_data[ilct][CLCT_PATTERN] = best_pid[best_hs];
02645             keystrip_data[ilct][CLCT_BEND] = pattern2007[best_pid[best_hs]][NUM_PATTERN_HALFSTRIPS];
02646             // Remove stagger if any.
02647             keystrip_data[ilct][CLCT_STRIP] = best_hs - stagger[CSCConstants::KEY_CLCT_LAYER - 1];
02648             keystrip_data[ilct][CLCT_BX] = bx;
02649             keystrip_data[ilct][CLCT_STRIP_TYPE] = 1; // obsolete
02650             keystrip_data[ilct][CLCT_QUALITY] = nhits[best_hs];
02651             keystrip_data[ilct][CLCT_CFEB] = keystrip_data[ilct][CLCT_STRIP] / cfeb_strips[1];
02652             int halfstrip_in_cfeb = keystrip_data[ilct][CLCT_STRIP] - cfeb_strips[1] * keystrip_data[ilct][CLCT_CFEB];
02653 
02654             if (infoV > 1)
02655               LogTrace("CSCCathodeLCTProcessor") << " Final selection: ilct " << ilct << " key halfstrip "
02656                   << keystrip_data[ilct][CLCT_STRIP] << " quality " << keystrip_data[ilct][CLCT_QUALITY] << " pattern "
02657                   << keystrip_data[ilct][CLCT_PATTERN] << " bx " << keystrip_data[ilct][CLCT_BX];
02658 
02659             CSCCLCTDigi thisLCT(1, keystrip_data[ilct][CLCT_QUALITY], keystrip_data[ilct][CLCT_PATTERN],
02660                 keystrip_data[ilct][CLCT_STRIP_TYPE], keystrip_data[ilct][CLCT_BEND], halfstrip_in_cfeb,
02661                 keystrip_data[ilct][CLCT_CFEB], keystrip_data[ilct][CLCT_BX]);
02662             thisLCT.setFullBX(fbx);
02663             lctList.push_back(thisLCT);
02664             lctListBX.push_back(thisLCT);
02665           }
02666         }
02667 
02668         // state-machine
02669         if (ptn_trig)
02670         {
02671           // Once there was a trigger, CLCT pre-trigger state machine checks the number of hits
02672           // that lie on a key halfstrip pattern template at every bx, and waits for it to drop below threshold.
02673           // During that time no CLCTs could be found with its key halfstrip in the area of
02674           // [clct_key-clct_state_machine_zone, clct_key+clct_state_machine_zone]
02675           // starting from first_bx+1.
02676           // The search for CLCTs resumes only when the number of hits on key halfstrip drops below threshold.
02677           for (unsigned int ilct = 0; ilct < lctListBX.size(); ilct++)
02678           {
02679             int key_hstrip = lctListBX[ilct].getKeyStrip() + stagger[CSCConstants::KEY_CLCT_LAYER - 1];
02680 
02681             int delta_hs = clct_state_machine_zone;
02682             if (dynamic_state_machine_zone)
02683               delta_hs = pattern2007[lctListBX[ilct].getPattern()][NUM_PATTERN_HALFSTRIPS + 1] - 1;
02684 
02685             int min_hstrip = key_hstrip - delta_hs;
02686             int max_hstrip = key_hstrip + delta_hs;
02687 
02688             if (min_hstrip < stagger[CSCConstants::KEY_CLCT_LAYER - 1])
02689               min_hstrip = stagger[CSCConstants::KEY_CLCT_LAYER - 1];
02690             if (max_hstrip > maxHalfStrips)
02691               max_hstrip = maxHalfStrips;
02692 
02693             if (infoV > 2)
02694               LogTrace("CSCCathodeLCTProcessor") << " marking post-trigger zone after bx=" << lctListBX[ilct].getBX() << " ["
02695                   << min_hstrip << "," << max_hstrip << "]";
02696 
02697             // Stop checking drift_delay bx's short of fifo_tbins since
02698             // at later bx's we won't have a full set of hits for a
02699             // pattern search anyway.
02700             //int stop_time = fifo_tbins - drift_delay;
02701             // -- no, need to extend busyMap over fifo_tbins - drift_delay
02702             for (size_t bx = first_bx + 1; bx < fifo_tbins; bx++)
02703             {
02704               bool busy_bx = false;
02705               if (bx <= (size_t)latch_bx)
02706                 busy_bx = true; // always busy before drift time
02707               if (!busy_bx)
02708               {
02709                 bool hits_in_time = ptnFinding(pulse, maxHalfStrips, bx);
02710                 if (hits_in_time && nhits[key_hstrip] >= nplanes_hit_pattern)
02711                   busy_bx = true;
02712                 if (infoV > 2)
02713                   LogTrace("CSCCathodeLCTProcessor") << "  at bx=" << bx << " hits_in_time=" << hits_in_time << " nhits="
02714                       << nhits[key_hstrip];
02715               }
02716               if (infoV > 2)
02717                 LogTrace("CSCCathodeLCTProcessor") << "  at bx=" << bx << " busy=" << busy_bx;
02718               if (busy_bx)
02719                 for (int hstrip = min_hstrip; hstrip <= max_hstrip; hstrip++)
02720                   busyMap[hstrip][bx] = true;
02721               else
02722                 break;
02723             }
02724           }
02725         } // if (ptn_trig)
02726       }
02727     }
02728     else
02729     {
02730       start_bx = first_bx + 1; // no dead time
02731     }
02732   }
02733 
02734   return lctList;
02735 } // findLCTs -- SLHC version.
02736 
02737 
02738 // --------------------------------------------------------------------------
02739 // Auxiliary code.
02740 // --------------------------------------------------------------------------
02741 // Dump of configuration parameters.
02742 void CSCCathodeLCTProcessor::dumpConfigParams() const {
02743   std::ostringstream strm;
02744   strm << "\n";
02745   strm << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
02746   strm << "+                  CLCT configuration parameters:                  +\n";
02747   strm << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
02748   strm << " fifo_tbins   [total number of time bins in DAQ readout] = "
02749        << fifo_tbins << "\n";
02750   strm << " fifo_pretrig [start time of cathode raw hits in DAQ readout] = "
02751        << fifo_pretrig << "\n";
02752   strm << " hit_persist  [duration of signal pulse, in 25 ns bins] = "
02753        << hit_persist << "\n";
02754   strm << " drift_delay  [time after pre-trigger before TMB latches LCTs] = "
02755        << drift_delay << "\n";
02756   strm << " nplanes_hit_pretrig [min. number of layers hit for pre-trigger] = "
02757        << nplanes_hit_pretrig << "\n";
02758   strm << " nplanes_hit_pattern [min. number of layers hit for trigger] = "
02759        << nplanes_hit_pattern << "\n";
02760   if (isTMB07) {
02761     strm << " pid_thresh_pretrig [lower threshold on pattern id] = "
02762          << pid_thresh_pretrig << "\n";
02763     strm << " min_separation     [region of busy key strips] = "
02764          << min_separation << "\n";
02765   }
02766   strm << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
02767   LogDebug("CSCCathodeLCTProcessor") << strm.str();
02768   //std::cerr<<strm.str()<<std::endl;
02769 }
02770 
02771 // Reasonably nice dump of digis on half-strips and di-strips.
02772 void CSCCathodeLCTProcessor::dumpDigis(const std::vector<int> strip[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS], const int stripType, const int nStrips) const
02773 {
02774   LogDebug("CSCCathodeLCTProcessor")
02775     << "ME" << ((theEndcap == 1) ? "+" : "-")
02776     << theStation << "/" << theRing << "/" << theChamber
02777     << " strip type " << stripType << " nStrips " << nStrips;
02778 
02779   std::ostringstream strstrm;
02780   for (int i_strip = 0; i_strip < nStrips; i_strip++) {
02781     if (i_strip%10 == 0) {
02782       if (i_strip < 100) strstrm << i_strip/10;
02783       else               strstrm << (i_strip-100)/10;
02784     }
02785     else                 strstrm << " ";
02786     if ((i_strip+1)%cfeb_strips[stripType] == 0) strstrm << " ";
02787   }
02788   strstrm << "\n";
02789   for (int i_strip = 0; i_strip < nStrips; i_strip++) {
02790     strstrm << i_strip%10;
02791     if ((i_strip+1)%cfeb_strips[stripType] == 0) strstrm << " ";
02792   }
02793   for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
02794     strstrm << "\n";
02795     for (int i_strip = 0; i_strip < nStrips; i_strip++) {
02796       if (!strip[i_layer][i_strip].empty()) {
02797         std::vector<int> bx_times = strip[i_layer][i_strip];
02798         // Dump only the first in time.
02799         strstrm << std::hex << bx_times[0] << std::dec;
02800       }
02801       else {
02802         strstrm << "-";
02803       }
02804       if ((i_strip+1)%cfeb_strips[stripType] == 0) strstrm << " ";
02805     }
02806   }
02807   LogTrace("CSCCathodeLCTProcessor") << strstrm.str();
02808 }
02809 
02810 // Returns vector of read-out CLCTs, if any.  Starts with the vector
02811 // of all found CLCTs and selects the ones in the read-out time window.
02812 std::vector<CSCCLCTDigi> CSCCathodeLCTProcessor::readoutCLCTs() {
02813   std::vector<CSCCLCTDigi> tmpV;
02814 
02815   // The start time of the L1A*CLCT coincidence window should be
02816   // related to the fifo_pretrig parameter, but I am not completely
02817   // sure how.  For now, just choose it such that the window is
02818   // centered at bx=7.  This may need further tweaking if the value of
02819   // tmb_l1a_window_size changes.
02820   // static int fpga_latency = 3;
02821   // static int early_tbins  = fifo_pretrig - fpga_latency;
02822   // static int early_tbins = 4;
02823   
02824   // The number of CLCT bins in the read-out is given by the
02825   // tmb_l1a_window_size parameter, but made even by setting the LSB
02826   // of tmb_l1a_window_size to 0.
02827   //
02828   static int lct_bins   = 
02829     (tmb_l1a_window_size%2 == 0) ? tmb_l1a_window_size : tmb_l1a_window_size-1;
02830   static int late_tbins = early_tbins + lct_bins;
02831 
02832   static int ifois = 0;
02833   if (ifois == 0) {
02834     if (infoV >= 0 && early_tbins < 0) {
02835       edm::LogWarning("L1CSCTPEmulatorSuspiciousParameters")
02836         << "+++ early_tbins = " << early_tbins
02837         << "; in-time CLCTs are not getting read-out!!! +++" << "\n";
02838     }
02839 
02840     if (late_tbins > MAX_CLCT_BINS-1) {
02841       if (infoV >= 0) edm::LogWarning("L1CSCTPEmulatorSuspiciousParameters")
02842         << "+++ Allowed range of time bins, [0-" << late_tbins
02843         << "] exceeds max allowed, " << MAX_CLCT_BINS-1 << " +++\n"
02844         << "+++ Set late_tbins to max allowed +++\n";
02845       late_tbins = MAX_CLCT_BINS-1;
02846     }
02847     ifois = 1;
02848   }
02849 
02850   // Start from the vector of all found CLCTs and select those within
02851   // the CLCT*L1A coincidence window.
02852   int bx_readout = -1;
02853   std::vector<CSCCLCTDigi> all_lcts = getCLCTs();
02854   for (std::vector <CSCCLCTDigi>::const_iterator plct = all_lcts.begin();
02855        plct != all_lcts.end(); plct++) {
02856     if (!plct->isValid()) continue;
02857 
02858     int bx = (*plct).getBX();
02859     // Skip CLCTs found too early relative to L1Accept.
02860     if (bx <= early_tbins) {
02861       if (infoV > 1) LogDebug("CSCCathodeLCTProcessor")
02862         << " Do not report CLCT on key halfstrip " << plct->getKeyStrip()
02863         << ": found at bx " << bx << ", whereas the earliest allowed bx is "
02864         << early_tbins+1;
02865       continue;
02866     }
02867 
02868     // Skip CLCTs found too late relative to L1Accept.
02869     if (bx > late_tbins) {
02870       if (infoV > 1) LogDebug("CSCCathodeLCTProcessor")
02871         << " Do not report CLCT on key halfstrip " << plct->getKeyStrip()
02872         << ": found at bx " << bx << ", whereas the latest allowed bx is "
02873         << late_tbins;
02874       continue;
02875     }
02876 
02877     // If (readout_earliest_2) take only CLCTs in the earliest bx in the read-out window:
02878     // in digi->raw step, LCTs have to be packed into the TMB header, and
02879     // currently there is room just for two.
02880     if (readout_earliest_2) {
02881       if (bx_readout == -1 || bx == bx_readout) {
02882         tmpV.push_back(*plct);
02883         if (bx_readout == -1) bx_readout = bx;
02884       }
02885     }
02886     else tmpV.push_back(*plct);
02887   }
02888   return tmpV;
02889 }
02890 
02891 // Returns vector of all found CLCTs, if any.  Used for ALCT-CLCT matching.
02892 std::vector<CSCCLCTDigi> CSCCathodeLCTProcessor::getCLCTs() {
02893   std::vector<CSCCLCTDigi> tmpV;
02894   for (int bx = 0; bx < MAX_CLCT_BINS; bx++) {
02895     if (bestCLCT[bx].isValid())   tmpV.push_back(bestCLCT[bx]);
02896     if (secondCLCT[bx].isValid()) tmpV.push_back(secondCLCT[bx]);
02897   }
02898   return tmpV;
02899 }
02900 
02901 
02902 // --------------------------------------------------------------------------
02903 // Test routines.  Mostly for older versions of the algorithm and outdated.
02904 // --------------------------------------------------------------------------
02905 void CSCCathodeLCTProcessor::testDistripStagger() {
02906   // Author: Jason Mumford (mumford@physics.ucla.edu)
02907   // This routine tests the distripStagger routine.
02908   // @@
02909   bool debug = true;
02910   int test_triad[CSCConstants::NUM_DI_STRIPS], test_time[CSCConstants::NUM_DI_STRIPS];
02911   int test_digi[CSCConstants::NUM_DI_STRIPS];
02912   int distrip = 0;
02913   test_triad[distrip] = 3;    //After routine, I expect 4
02914   test_triad[distrip+1] = 3;  //                        4
02915   test_triad[distrip+2] = 3;  //                        4 
02916   test_triad[distrip+3] = 3;  //                        4
02917   test_triad[distrip+4] = 3;  //                        4
02918   test_triad[distrip+5] = 3;  //                        4
02919   test_triad[distrip+6] = 3;  //                        4
02920   test_triad[distrip+7] = 3;  //                        4
02921   test_triad[distrip+8] = 3;  //                        4
02922   test_triad[distrip+9] = 3;  //                        4
02923   test_triad[distrip+10] = 2;  //                       2
02924 
02925   test_time[distrip] = 4;     //      ""      ""        0
02926   test_time[distrip+1] = 10;  //                        4
02927   test_time[distrip+2] = 2;   //                        10
02928   test_time[distrip+3] = 0;   //                        2
02929   test_time[distrip+4] = 6;   //                        2
02930   test_time[distrip+5] = 8;   //                        2
02931   test_time[distrip+6] = 10;   //                        2
02932   test_time[distrip+7] = 1;   //                        2
02933   test_time[distrip+8] = 8;   //                        2
02934   test_time[distrip+9] = 5;   //                        2
02935   test_time[distrip+10] = 6;   //                        2
02936 
02937   std::cout << "\n ------------------------------------------------- \n";
02938   std::cout << "!!!!!!Testing distripStagger routine!!!!!!" << std::endl;
02939   std::cout << "Values before distripStagger routine:" << std::endl;
02940   for (int i=distrip; i<distrip+11; i++){
02941     test_digi[i] = 999;
02942     std::cout << "test_triad[" << i << "] = " << test_triad[i];
02943     std::cout << "   test_time[" << i << "] = " << test_time[i] << std::endl;
02944   }
02945   distripStagger(test_triad, test_time, test_digi, distrip, debug);
02946   std::cout << "Values after distripStagger routine:" << std::endl;
02947   for (int i=distrip; i<distrip+11; i++){
02948     std::cout << "test_triad[" << i << "] = " << test_triad[i];
02949     std::cout << "   test_time[" << i << "] = " << test_time[i] << std::endl;
02950   }
02951   std::cout << "\n ------------------------------------------------- \n \n";
02952 }
02953 
02954 void CSCCathodeLCTProcessor::testLCTs() {
02955   // test to make sure what goes into an LCT is what comes out.
02956   for (int ptn = 0; ptn < 8; ptn++) {
02957     for (int bend = 0; bend < 2; bend++) {
02958       for (int cfeb = 0; cfeb < MAX_CFEBS; cfeb++) {
02959         for (int key_strip = 0; key_strip < 32; key_strip++) {
02960           for (int bx = 0; bx < 7; bx++) {
02961             for (int stripType = 0; stripType < 2; stripType++) {
02962               for (int quality = 3; quality < 6; quality++) {
02963                 CSCCLCTDigi thisLCT(1, quality, ptn, stripType, bend,
02964                                     key_strip, cfeb, bx);
02965                 if (ptn != thisLCT.getPattern())
02966                   LogTrace("CSCCathodeLCTProcessor")
02967                     << "pattern mismatch: " << ptn << " "
02968                     << thisLCT.getPattern();
02969                 if (bend != thisLCT.getBend())
02970                   LogTrace("CSCCathodeLCTProcessor")
02971                     << "bend mismatch: " << bend << " " << thisLCT.getBend();
02972                 if (cfeb != thisLCT.getCFEB()) 
02973                   LogTrace("CSCCathodeLCTProcessor")
02974                     << "cfeb mismatch: " << cfeb << " " << thisLCT.getCFEB();
02975                 if (key_strip != thisLCT.getKeyStrip())
02976                   LogTrace("CSCCathodeLCTProcessor")
02977                     << "strip mismatch: " << key_strip << " "
02978                     << thisLCT.getKeyStrip();
02979                 if (bx != thisLCT.getBX())
02980                   LogTrace("CSCCathodeLCTProcessor")
02981                     << "bx mismatch: " << bx << " " << thisLCT.getBX();
02982                 if (stripType != thisLCT.getStripType())
02983                   LogTrace("CSCCathodeLCTProcessor")
02984                     << "Strip Type mismatch: " << stripType << " "
02985                     << thisLCT.getStripType();
02986                 if (quality != thisLCT.getQuality())
02987                   LogTrace("CSCCathodeLCTProcessor")
02988                     << "quality mismatch: " << quality << " "
02989                     << thisLCT.getQuality();
02990               }
02991             }
02992           }
02993         }
02994       }
02995     }
02996   }
02997 }
02998 
02999 void CSCCathodeLCTProcessor::printPatterns() {
03000   // @@
03001   std::cout<<" Printing patterns for Cathode LCT"<<std::endl;
03002   std::cout<<"       ";
03003   for (int patternNum = 0; patternNum < CSCConstants::NUM_CLCT_PATTERNS_PRE_TMB07; patternNum++) {
03004     std::cout<<" Pattern "<<patternNum<<" ";
03005   }
03006   std::cout<<std::endl;
03007   std::cout<<" Layer ";
03008   for (int patternNum = 0; patternNum < CSCConstants::NUM_CLCT_PATTERNS_PRE_TMB07; patternNum++) {
03009     std::cout<<"   Bend "<<(pattern[patternNum][NUM_PATTERN_STRIPS]==0 ? "L": "R")<<"  ";
03010   }
03011   std::cout<<std::endl;
03012   for (int layer = 0; layer < CSCConstants::NUM_LAYERS; layer++) {
03013     for (int patternNum = 0; patternNum < CSCConstants::NUM_CLCT_PATTERNS_PRE_TMB07; patternNum++) {
03014       if (patternNum == 0) std::cout<<"   "<<layer<<"       ";
03015       if ((isTMB07  && layer != CSCConstants::KEY_CLCT_LAYER-1) ||
03016           (!isTMB07 && layer != CSCConstants::KEY_CLCT_LAYER_PRE_TMB07-1)) {//that old counting from 1 vs 0 thing.
03017         int minStrip =0;
03018         if ((isTMB07  && layer < CSCConstants::KEY_CLCT_LAYER-1) ||
03019             (!isTMB07 && layer < CSCConstants::KEY_CLCT_LAYER_PRE_TMB07-1)) {
03020           minStrip = 3*layer;
03021         } else {
03022           minStrip = 3*layer - 2;// since on the key layer we only have 1 strip
03023         }
03024         for (int strip = minStrip; strip < minStrip + 3; strip++) {
03025           if (layer == pattern[patternNum][strip]) {
03026             std::cout<<"X";
03027           } else {
03028             std::cout<<"_";
03029           }
03030         }
03031       } else {// on the key layer we always have a hit, right?
03032         std::cout<<" X ";
03033       }
03034       std::cout<<"        ";
03035     }
03036     std::cout<<std::endl;
03037   }
03038 }
03039     
03040 void CSCCathodeLCTProcessor::testPatterns() {
03041 //generate all possible combinations of hits in a given area and see what we find.
03042 // Benn Tannenbaum 21 June 2001
03043   
03044   //there are 16 strips in our uber-pattern, each of which can be on or off.
03045   // 2^16 = 65536
03046   for (int possibleHits = 0; possibleHits < 65536; possibleHits++) {
03047     std::vector<int> stripsHit[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS];
03048     //assign one bit to each strip in an array. I'll start centered around strip 10.
03049     stripsHit[0][ 9].push_back(( possibleHits &     1 ) != 0);     // 2^0
03050     stripsHit[0][10].push_back(( possibleHits &     2 ) != 0);     // 2^1
03051     stripsHit[0][11].push_back(( possibleHits &     4 ) != 0);     // 2^2
03052     stripsHit[1][ 9].push_back(( possibleHits &     8 ) != 0);     // 2^3
03053     stripsHit[1][10].push_back(( possibleHits &    16 ) != 0);     // 2^4
03054     stripsHit[1][11].push_back(( possibleHits &    32 ) != 0);     // 2^5
03055     stripsHit[2][ 9].push_back(( possibleHits &    64 ) != 0);     // 2^6
03056     stripsHit[2][10].push_back(( possibleHits &   128 ) != 0);     // 2^7
03057     stripsHit[2][11].push_back(( possibleHits &   256 ) != 0);     // 2^8
03058     stripsHit[3][10].push_back(( possibleHits &   512 ) != 0);     // 2^9
03059     stripsHit[4][ 9].push_back(( possibleHits &  1024 ) != 0);     // 2^10
03060     stripsHit[4][10].push_back(( possibleHits &  2048 ) != 0);     // 2^11
03061     stripsHit[4][11].push_back(( possibleHits &  4096 ) != 0);     // 2^12
03062     stripsHit[5][ 9].push_back(( possibleHits &  8192 ) != 0);     // 2^13
03063     stripsHit[5][10].push_back(( possibleHits & 16384 ) != 0);     // 2^14
03064     stripsHit[5][11].push_back(( possibleHits & 32768 ) != 0);     // 2^15
03065     int numLayersHit = findNumLayersHit(stripsHit);
03066     std::vector <CSCCLCTDigi> results = findLCTs(stripsHit, 1);
03067 // print out whatever we find-- but only ones where 4 or more layers are hit
03068 // OR ones where we find something
03069 // key: X    a hit there and was used to find pattern
03070 //      x    a hit not involved in pattern
03071 //      _    empty strip
03072 //      o    a hit was there, but no pattern was found
03073     if (numLayersHit > 3 || results.size() > 0) {
03074       std::cout<<"Input "<<possibleHits<<"/"<< 65536 <<" # Found Patterns "<<results.size()<<std::endl<<" ";
03075       for (int layer = 0; layer < CSCConstants::NUM_LAYERS; layer++) {
03076         if ((isTMB07  && layer != CSCConstants::KEY_CLCT_LAYER - 1) || 
03077             (!isTMB07 && layer != CSCConstants::KEY_CLCT_LAYER_PRE_TMB07 - 1)) {
03078           for (int strip = 9; strip < 12; strip++) {
03079             if (!stripsHit[layer][strip].empty()) {
03080               if (results.size() > 0) {
03081                 int thePatternStrip = strip - (results[0].getKeyStrip() - 2) + 3*layer;
03082                 if ((isTMB07 && layer>=CSCConstants::KEY_CLCT_LAYER) ||
03083                     (!isTMB07 && layer>=CSCConstants::KEY_CLCT_LAYER_PRE_TMB07))
03084                   thePatternStrip -= 2;
03085 
03086                 if (pattern[results[0].getPattern()][thePatternStrip] == layer)
03087                 {
03088                   std::cout<<"X";
03089                 } else {
03090                   std::cout<<"x";
03091                 }
03092               } else {
03093                 std::cout<<"o";
03094               }
03095             } else {
03096               std::cout<<"_";
03097             }
03098           }
03099           std::cout<<"   ";
03100           for (unsigned int output = 0; output < results.size(); output++) {
03101             int minStrip;
03102             if ((isTMB07 && layer < CSCConstants::KEY_CLCT_LAYER-1) ||
03103                 (!isTMB07 && layer < CSCConstants::KEY_CLCT_LAYER_PRE_TMB07-1))  {
03104               minStrip = 3*layer;
03105             } else {
03106               minStrip = 3*layer - 2;// since on the key layer we only have 1 strip
03107             }
03108             for (int strip = minStrip; strip < minStrip + 3; strip++) {
03109               if (layer == pattern[results[output].getPattern()][strip]) {
03110                 std::cout<<"X";
03111               } else {
03112                 std::cout<<"_";
03113               }
03114             }
03115             std::cout<<"  ";
03116           }
03117         } else {
03118           if (!stripsHit[layer][10].empty()) {
03119             std::cout<<" X ";
03120           } else {
03121             std::cout<<" _ ";
03122           }
03123           for (unsigned int output = 0; output < results.size(); output++)
03124             std::cout<<"    X   ";
03125         }
03126         if (layer < static_cast<int>(results.size()) ) {
03127           std::cout<<results[layer];
03128           std::cout<<" ";
03129         } else {
03130           std::cout<<" "<<std::endl<<" ";
03131         }
03132       }
03133     }
03134   }
03135 }
03136 
03137 int CSCCathodeLCTProcessor::findNumLayersHit(std::vector<int> 
03138           stripsHit[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS]) {
03139   int number = 0;
03140   for (int layer = 0; layer < CSCConstants::NUM_LAYERS; layer++) {
03141     if ((!stripsHit[layer][ 9].empty()) || 
03142         (!stripsHit[layer][10].empty()) ||
03143         (!stripsHit[layer][11].empty()) ) number++;
03144   }
03145   return number;
03146 }