CMS 3D CMS Logo

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