CMS 3D CMS Logo

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

Generated on Tue Jun 9 17:39:58 2009 for CMSSW by  doxygen 1.5.4