CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_3_0/src/L1Trigger/CSCTriggerPrimitives/src/CSCAnodeLCTProcessor.cc

Go to the documentation of this file.
00001 //-----------------------------------------------------------------------------
00002 //
00003 //   Class: CSCAnodeLCTProcessor
00004 //
00005 //   Description: 
00006 //     This is the simulation for the Anode LCT Processor for the Level-1
00007 //     Trigger.  This processor consists of several stages:
00008 //
00009 //       1. Pulse extension of signals coming from wires.
00010 //       2. Pretrigger for each key-wire.
00011 //       3. Pattern detector if a pretrigger is found for the given key-wire.
00012 //       4. Ghost Cancellation Logic (GCL).
00013 //       5. Best track search and promotion.
00014 //       6. Second best track search and promotion.
00015 //
00016 //     The inputs to the ALCT Processor are wire digis.
00017 //     The output is up to two ALCT digi words.
00018 //
00019 //   Author List: Benn Tannenbaum (1999), Jason Mumford (2002), Slava Valuev.
00020 //                Porting from ORCA by S. Valuev (Slava.Valuev@cern.ch),
00021 //                May 2006.
00022 //
00023 //   $Date: 2010/08/04 14:50:11 $
00024 //   $Revision: 1.42 $
00025 //
00026 //   Modifications: 
00027 //
00028 //-----------------------------------------------------------------------------
00029 
00030 #include <L1Trigger/CSCTriggerPrimitives/src/CSCAnodeLCTProcessor.h>
00031 #include <L1Trigger/CSCCommonTrigger/interface/CSCTriggerGeometry.h>
00032 #include <DataFormats/MuonDetId/interface/CSCTriggerNumbering.h>
00033 
00034 #include <FWCore/MessageLogger/interface/MessageLogger.h>
00035 
00036 //-----------------
00037 // Static variables
00038 //-----------------
00039 
00040 /* This is the pattern envelope, which is used to define the collision
00041    patterns A and B.
00042    pattern_envelope[0][i]=layer;
00043    pattern_envelope[1+MEposition][i]=key_wire offset. */
00044 const int CSCAnodeLCTProcessor::pattern_envelope[CSCConstants::NUM_ALCT_PATTERNS][NUM_PATTERN_WIRES] = {
00045   //Layer
00046   { 0,  0,  0,
00047         1,  1,
00048             2,
00049             3,  3,
00050             4,  4,  4,
00051             5,  5,  5},
00052 
00053   //Keywire offset for ME1 and ME2
00054   {-2, -1,  0,
00055        -1,  0,
00056             0,
00057             0,  1,
00058             0,  1,  2,
00059             0,  1,  2},
00060 
00061   //Keywire offset for ME3 and ME4
00062   {2,  1,  0,
00063        1,  0,
00064            0,
00065            0, -1,
00066            0, -1, -2,
00067            0, -1, -2}
00068 };
00069 
00070 // These mask the pattern envelope to give the desired accelerator pattern
00071 // and collision patterns A and B.  These masks were meant to be the default
00072 // ones in early 200X, but were never implemented because of limited FPGA
00073 // resources.
00074 const int CSCAnodeLCTProcessor::pattern_mask_slim[CSCConstants::NUM_ALCT_PATTERNS][NUM_PATTERN_WIRES] = {
00075   // Accelerator pattern
00076   {0,  0,  1,
00077        0,  1,
00078            1,
00079            1,  0,
00080            1,  0,  0,
00081            1,  0,  0},
00082 
00083   // Collision pattern A
00084   {0,  1,  0,
00085        1,  1,
00086            1,
00087            1,  0,
00088            0,  1,  0,
00089            0,  1,  0},
00090 
00091   // Collision pattern B
00092   {1,  1,  0,
00093        1,  1,
00094            1,
00095            1,  1,
00096            0,  1,  1,
00097            0,  0,  1}
00098 };
00099 
00100 // Since the test beams in 2003, both collision patterns are "completely
00101 // open".  This is our current default.
00102 const int CSCAnodeLCTProcessor::pattern_mask_open[CSCConstants::NUM_ALCT_PATTERNS][NUM_PATTERN_WIRES] = {
00103   // Accelerator pattern
00104   {0,  0,  1,
00105        0,  1,
00106            1,
00107            1,  0,
00108            1,  0,  0,
00109            1,  0,  0},
00110 
00111   // Collision pattern A
00112   {1,  1,  1,
00113        1,  1,
00114            1,
00115            1,  1,
00116            1,  1,  1,
00117            1,  1,  1},
00118 
00119   // Collision pattern B
00120   {1,  1,  1,
00121        1,  1,
00122            1,
00123            1,  1,
00124            1,  1,  1,
00125            1,  1,  1}
00126 };
00127 
00128 // Default values of configuration parameters.
00129 const unsigned int CSCAnodeLCTProcessor::def_fifo_tbins   = 16;
00130 const unsigned int CSCAnodeLCTProcessor::def_fifo_pretrig = 10;
00131 const unsigned int CSCAnodeLCTProcessor::def_drift_delay  =  2;
00132 const unsigned int CSCAnodeLCTProcessor::def_nplanes_hit_pretrig =  2;
00133 const unsigned int CSCAnodeLCTProcessor::def_nplanes_hit_pattern =  4;
00134 const unsigned int CSCAnodeLCTProcessor::def_nplanes_hit_accel_pretrig =  2;
00135 const unsigned int CSCAnodeLCTProcessor::def_nplanes_hit_accel_pattern =  4;
00136 const unsigned int CSCAnodeLCTProcessor::def_trig_mode        =  2;  // 3?
00137 const unsigned int CSCAnodeLCTProcessor::def_accel_mode       =  0;  // 1?
00138 const unsigned int CSCAnodeLCTProcessor::def_l1a_window_width =  7;  // 5?
00139 
00140 //----------------
00141 // Constructors --
00142 //----------------
00143 
00144 CSCAnodeLCTProcessor::CSCAnodeLCTProcessor(unsigned endcap, unsigned station,
00145                                            unsigned sector, unsigned subsector,
00146                                            unsigned chamber,
00147                                            const edm::ParameterSet& conf,
00148                                            const edm::ParameterSet& comm) : 
00149                      theEndcap(endcap), theStation(station), theSector(sector),
00150                      theSubsector(subsector), theTrigChamber(chamber) {
00151   static bool config_dumped = false;
00152 
00153   // ALCT configuration parameters.
00154   fifo_tbins   = conf.getParameter<unsigned int>("alctFifoTbins");
00155   fifo_pretrig = conf.getParameter<unsigned int>("alctFifoPretrig");
00156   drift_delay  = conf.getParameter<unsigned int>("alctDriftDelay");
00157   nplanes_hit_pretrig =
00158     conf.getParameter<unsigned int>("alctNplanesHitPretrig");
00159   nplanes_hit_pattern =
00160     conf.getParameter<unsigned int>("alctNplanesHitPattern");
00161   nplanes_hit_accel_pretrig =
00162     conf.getParameter<unsigned int>("alctNplanesHitAccelPretrig");
00163   nplanes_hit_accel_pattern =
00164     conf.getParameter<unsigned int>("alctNplanesHitAccelPattern");
00165   trig_mode        = conf.getParameter<unsigned int>("alctTrigMode");
00166   accel_mode       = conf.getParameter<unsigned int>("alctAccelMode");
00167   l1a_window_width = conf.getParameter<unsigned int>("alctL1aWindowWidth");
00168 
00169   // Verbosity level, set to 0 (no print) by default.
00170   infoV        = conf.getUntrackedParameter<int>("verbosity", 0);
00171 
00172   // Other parameters.
00173   // Use open pattern instead of more restrictive (slim) ones.
00174   isMTCC       = comm.getParameter<bool>("isMTCC");
00175   // Use TMB07 flag for DAQ-2006 firmware version (implemented in late 2007).
00176   isTMB07      = comm.getParameter<bool>("isTMB07");
00177 
00178   // Check and print configuration parameters.
00179   checkConfigParameters();
00180   if (infoV > 0 && !config_dumped) {
00181     dumpConfigParams();
00182     config_dumped = true;
00183   }
00184 
00185   numWireGroups = 0;  // Will be set later.
00186   MESelection   = (theStation < 3) ? 0 : 1;
00187 
00188   // Load appropriate pattern mask.
00189   for (int i_patt = 0; i_patt < CSCConstants::NUM_ALCT_PATTERNS; i_patt++) {
00190     for (int i_wire = 0; i_wire < NUM_PATTERN_WIRES; i_wire++) {
00191       if (isMTCC || isTMB07) {
00192         pattern_mask[i_patt][i_wire] = pattern_mask_open[i_patt][i_wire];
00193       }
00194       else {
00195         pattern_mask[i_patt][i_wire] = pattern_mask_slim[i_patt][i_wire];
00196       }
00197     }
00198   }
00199 }
00200 
00201 CSCAnodeLCTProcessor::CSCAnodeLCTProcessor() :
00202                      theEndcap(1), theStation(1), theSector(1),
00203                      theSubsector(1), theTrigChamber(1) {
00204   // Used for debugging. -JM
00205   static bool config_dumped = false;
00206 
00207   // ALCT parameters.
00208   setDefaultConfigParameters();
00209   infoV = 2;
00210   isMTCC  = false;
00211   isTMB07 = true;
00212 
00213   // Check and print configuration parameters.
00214   checkConfigParameters();
00215   if (!config_dumped) {
00216     dumpConfigParams();
00217     config_dumped = true;
00218   }
00219 
00220   numWireGroups = CSCConstants::MAX_NUM_WIRES;
00221   MESelection   = (theStation < 3) ? 0 : 1;
00222 
00223   // Load default pattern mask.
00224   for (int i_patt = 0; i_patt < CSCConstants::NUM_ALCT_PATTERNS; i_patt++) {
00225     for (int i_wire = 0; i_wire < NUM_PATTERN_WIRES; i_wire++) {
00226       pattern_mask[i_patt][i_wire] = pattern_mask_open[i_patt][i_wire];
00227     }
00228   }
00229 }
00230 
00231 void CSCAnodeLCTProcessor::setDefaultConfigParameters() {
00232   // Set default values for configuration parameters.
00233   fifo_tbins   = def_fifo_tbins;
00234   fifo_pretrig = def_fifo_pretrig;
00235   drift_delay  = def_drift_delay;
00236   nplanes_hit_pretrig = def_nplanes_hit_pretrig;
00237   nplanes_hit_pattern = def_nplanes_hit_pattern;
00238   nplanes_hit_accel_pretrig = def_nplanes_hit_accel_pretrig;
00239   nplanes_hit_accel_pattern = def_nplanes_hit_accel_pattern;
00240   trig_mode        = def_trig_mode;
00241   accel_mode       = def_accel_mode;
00242   l1a_window_width = def_l1a_window_width;
00243 }
00244 
00245 // Set configuration parameters obtained via EventSetup mechanism.
00246 void CSCAnodeLCTProcessor::setConfigParameters(const CSCDBL1TPParameters* conf) {
00247   static bool config_dumped = false;
00248 
00249   fifo_tbins   = conf->alctFifoTbins();
00250   fifo_pretrig = conf->alctFifoPretrig();
00251   drift_delay  = conf->alctDriftDelay();
00252   nplanes_hit_pretrig = conf->alctNplanesHitPretrig();
00253   nplanes_hit_pattern = conf->alctNplanesHitPattern();
00254   nplanes_hit_accel_pretrig = conf->alctNplanesHitAccelPretrig();
00255   nplanes_hit_accel_pattern = conf->alctNplanesHitAccelPattern();
00256   trig_mode        = conf->alctTrigMode();
00257   accel_mode       = conf->alctAccelMode();
00258   l1a_window_width = conf->alctL1aWindowWidth();
00259 
00260   // Check and print configuration parameters.
00261   checkConfigParameters();
00262   if (!config_dumped) {
00263     dumpConfigParams();
00264     config_dumped = true;
00265   }
00266 }
00267 
00268 void CSCAnodeLCTProcessor::checkConfigParameters() {
00269   // Make sure that the parameter values are within the allowed range.
00270 
00271   // Max expected values.
00272   static const unsigned int max_fifo_tbins   = 1 << 5;
00273   static const unsigned int max_fifo_pretrig = 1 << 5;
00274   static const unsigned int max_drift_delay  = 1 << 2;
00275   static const unsigned int max_nplanes_hit_pretrig = 1 << 3;
00276   static const unsigned int max_nplanes_hit_pattern = 1 << 3;
00277   static const unsigned int max_nplanes_hit_accel_pretrig = 1 << 3;
00278   static const unsigned int max_nplanes_hit_accel_pattern = 1 << 3;
00279   static const unsigned int max_trig_mode        = 1 << 2;
00280   static const unsigned int max_accel_mode       = 1 << 2;
00281   static const unsigned int max_l1a_window_width = MAX_ALCT_BINS; // 4 bits
00282 
00283   // Checks.
00284   if (fifo_tbins >= max_fifo_tbins) {
00285     if (infoV >= 0) edm::LogError("L1CSCTPEmulatorConfigError")
00286       << "+++ Value of fifo_tbins, " << fifo_tbins
00287       << ", exceeds max allowed, " << max_fifo_tbins-1 << " +++\n"
00288       << "+++ Try to proceed with the default value, fifo_tbins="
00289       << def_fifo_tbins << " +++\n";
00290     fifo_tbins = def_fifo_tbins;
00291   }
00292   if (fifo_pretrig >= max_fifo_pretrig) {
00293     if (infoV >= 0) edm::LogError("L1CSCTPEmulatorConfigError")
00294       << "+++ Value of fifo_pretrig, " << fifo_pretrig
00295       << ", exceeds max allowed, " << max_fifo_pretrig-1 << " +++\n"
00296       << "+++ Try to proceed with the default value, fifo_pretrig="
00297       << def_fifo_pretrig << " +++\n";
00298     fifo_pretrig = def_fifo_pretrig;
00299   }
00300   if (drift_delay >= max_drift_delay) {
00301     if (infoV >= 0) edm::LogError("L1CSCTPEmulatorConfigError")
00302       << "+++ Value of drift_delay, " << drift_delay
00303       << ", exceeds max allowed, " << max_drift_delay-1 << " +++\n"
00304       << "+++ Try to proceed with the default value, drift_delay="
00305       << def_drift_delay << " +++\n";
00306     drift_delay = def_drift_delay;
00307   }
00308   if (nplanes_hit_pretrig >= max_nplanes_hit_pretrig) {
00309     if (infoV >= 0) edm::LogError("L1CSCTPEmulatorConfigError")
00310       << "+++ Value of nplanes_hit_pretrig, " << nplanes_hit_pretrig
00311       << ", exceeds max allowed, " << max_nplanes_hit_pretrig-1 << " +++\n"
00312       << "+++ Try to proceed with the default value, nplanes_hit_pretrig="
00313       << nplanes_hit_pretrig << " +++\n";
00314     nplanes_hit_pretrig = def_nplanes_hit_pretrig;
00315   }
00316   if (nplanes_hit_pattern >= max_nplanes_hit_pattern) {
00317     if (infoV >= 0) edm::LogError("L1CSCTPEmulatorConfigError")
00318       << "+++ Value of nplanes_hit_pattern, " << nplanes_hit_pattern
00319       << ", exceeds max allowed, " << max_nplanes_hit_pattern-1 << " +++\n"
00320       << "+++ Try to proceed with the default value, nplanes_hit_pattern="
00321       << nplanes_hit_pattern << " +++\n";
00322     nplanes_hit_pattern = def_nplanes_hit_pattern;
00323   }
00324   if (nplanes_hit_accel_pretrig >= max_nplanes_hit_accel_pretrig) {
00325     if (infoV >= 0) edm::LogError("L1CSCTPEmulatorConfigError")
00326       << "+++ Value of nplanes_hit_accel_pretrig, "
00327       << nplanes_hit_accel_pretrig << ", exceeds max allowed, "
00328       << max_nplanes_hit_accel_pretrig-1 << " +++\n"
00329       << "+++ Try to proceed with the default value, "
00330       << "nplanes_hit_accel_pretrig=" << nplanes_hit_accel_pretrig << " +++\n";
00331     nplanes_hit_accel_pretrig = def_nplanes_hit_accel_pretrig;
00332   }
00333   if (nplanes_hit_accel_pattern >= max_nplanes_hit_accel_pattern) {
00334     if (infoV >= 0) edm::LogError("L1CSCTPEmulatorConfigError")
00335       << "+++ Value of nplanes_hit_accel_pattern, "
00336       << nplanes_hit_accel_pattern << ", exceeds max allowed, "
00337       << max_nplanes_hit_accel_pattern-1 << " +++\n"
00338       << "+++ Try to proceed with the default value, "
00339       << "nplanes_hit_accel_pattern=" << nplanes_hit_accel_pattern << " +++\n";
00340     nplanes_hit_accel_pattern = def_nplanes_hit_accel_pattern;
00341   }
00342   if (trig_mode >= max_trig_mode) {
00343     if (infoV >= 0) edm::LogError("L1CSCTPEmulatorConfigError")
00344       << "+++ Value of trig_mode, " << trig_mode
00345       << ", exceeds max allowed, " << max_trig_mode-1 << " +++\n"
00346       << "+++ Try to proceed with the default value, trig_mode="
00347       << trig_mode << " +++\n";
00348     trig_mode = def_trig_mode;
00349   }
00350   if (accel_mode >= max_accel_mode) {
00351     if (infoV >= 0) edm::LogError("L1CSCTPEmulatorConfigError")
00352       << "+++ Value of accel_mode, " << accel_mode
00353       << ", exceeds max allowed, " << max_accel_mode-1 << " +++\n"
00354       << "+++ Try to proceed with the default value, accel_mode="
00355       << accel_mode << " +++\n";
00356     accel_mode = def_accel_mode;
00357   }
00358   if (l1a_window_width >= max_l1a_window_width) {
00359     if (infoV >= 0) edm::LogError("L1CSCTPEmulatorConfigError")
00360       << "+++ Value of l1a_window_width, " << l1a_window_width
00361       << ", exceeds max allowed, " << max_l1a_window_width-1 << " +++\n"
00362       << "+++ Try to proceed with the default value, l1a_window_width="
00363       << l1a_window_width << " +++\n";
00364     l1a_window_width = def_l1a_window_width;
00365   }
00366 }
00367 
00368 void CSCAnodeLCTProcessor::clear() {
00369   for (int bx = 0; bx < MAX_ALCT_BINS; bx++) {
00370     bestALCT[bx].clear();
00371     secondALCT[bx].clear();
00372   }
00373 }
00374 
00375 void CSCAnodeLCTProcessor::clear(const int wire, const int pattern) {
00376   /* Clear the data off of selected pattern */
00377   if (pattern == 0) quality[wire][0] = -999;
00378   else {
00379     quality[wire][1] = -999;
00380     quality[wire][2] = -999;
00381   }
00382 }
00383 
00384 std::vector<CSCALCTDigi>
00385 CSCAnodeLCTProcessor::run(const CSCWireDigiCollection* wiredc) {
00386   // This is the main routine for normal running.  It gets wire times
00387   // from the wire digis and then passes them on to another run() function.
00388 
00389   // clear(); // redundant; called by L1MuCSCMotherboard.
00390 
00391   // Get the number of wire groups for the given chamber.  Do it only once
00392   // per chamber.
00393   if (numWireGroups == 0) {
00394     CSCTriggerGeomManager* theGeom = CSCTriggerGeometry::get();
00395     CSCChamber* theChamber = theGeom->chamber(theEndcap, theStation, theSector,
00396                                               theSubsector, theTrigChamber);
00397     if (theChamber) {
00398       numWireGroups = theChamber->layer(1)->geometry()->numberOfWireGroups();
00399       if (numWireGroups > CSCConstants::MAX_NUM_WIRES) {
00400         if (infoV >= 0) edm::LogError("L1CSCTPEmulatorSetupError")
00401           << "+++ Number of wire groups, " << numWireGroups
00402           << " found in ME" << ((theEndcap == 1) ? "+" : "-")
00403           << theStation << "/"
00404           << CSCTriggerNumbering::ringFromTriggerLabels(theStation,
00405                                                         theTrigChamber) << "/"
00406           << CSCTriggerNumbering::chamberFromTriggerLabels(theSector,
00407                               theSubsector, theStation, theTrigChamber)
00408           << " (sector " << theSector << " subsector " << theSubsector
00409           << " trig id. " << theTrigChamber << ")"
00410           << " exceeds max expected, " << CSCConstants::MAX_NUM_WIRES
00411           << " +++\n" 
00412           << "+++ CSC geometry looks garbled; no emulation possible +++\n";
00413         numWireGroups = -1;
00414       }
00415     }
00416     else {
00417       if (infoV >= 0) edm::LogError("L1CSCTPEmulatorSetupError")
00418         << "+++ ME" << ((theEndcap == 1) ? "+" : "-") << theStation << "/"
00419         << CSCTriggerNumbering::ringFromTriggerLabels(theStation,
00420                                                       theTrigChamber) << "/"
00421         << CSCTriggerNumbering::chamberFromTriggerLabels(theSector,
00422                             theSubsector, theStation, theTrigChamber)
00423         << " (sector " << theSector << " subsector " << theSubsector
00424         << " trig id. " << theTrigChamber << ")"
00425         << " is not defined in current geometry! +++\n"
00426         << "+++ CSC geometry looks garbled; no emulation possible +++\n";
00427       numWireGroups = -1;
00428     }
00429   }
00430 
00431   if (numWireGroups < 0) {
00432     if (infoV >= 0) edm::LogError("L1CSCTPEmulatorSetupError")
00433       << "+++ ME" << ((theEndcap == 1) ? "+" : "-") << theStation << "/"
00434       << CSCTriggerNumbering::ringFromTriggerLabels(theStation,
00435                                                     theTrigChamber) << "/"
00436       << CSCTriggerNumbering::chamberFromTriggerLabels(theSector,
00437                           theSubsector, theStation, theTrigChamber)
00438       << " (sector " << theSector << " subsector " << theSubsector
00439       << " trig id. " << theTrigChamber << "):"
00440       << " numWireGroups = " << numWireGroups
00441       << "; ALCT emulation skipped! +++";
00442     std::vector<CSCALCTDigi> emptyV;
00443     return emptyV;
00444   }
00445 
00446   // Get wire digis in this chamber from wire digi collection.
00447   bool noDigis = getDigis(wiredc);
00448 
00449   if (!noDigis) {
00450     // First get wire times from the wire digis.
00451     std::vector<int>
00452       wire[CSCConstants::NUM_LAYERS][CSCConstants::MAX_NUM_WIRES];
00453     readWireDigis(wire);
00454 
00455     // Pass an array of wire times on to another run() doing the LCT search.
00456     // If the number of layers containing digis is smaller than that
00457     // required to trigger, quit right away.
00458     const unsigned int min_layers =
00459       (nplanes_hit_accel_pattern == 0) ? nplanes_hit_pattern :
00460       ((nplanes_hit_pattern <= nplanes_hit_accel_pattern)
00461        ? nplanes_hit_pattern : nplanes_hit_accel_pattern);
00462 
00463     unsigned int layersHit = 0;
00464     for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
00465       for (int i_wire = 0; i_wire < numWireGroups; i_wire++) {
00466         if (!wire[i_layer][i_wire].empty()) {layersHit++; break;}
00467       }
00468     }
00469     if (layersHit >= min_layers) run(wire);
00470   }
00471 
00472   // Return vector of all found ALCTs.
00473   std::vector<CSCALCTDigi> tmpV = getALCTs();
00474   return tmpV;
00475 }
00476 
00477 void CSCAnodeLCTProcessor::run(const std::vector<int> wire[CSCConstants::NUM_LAYERS][CSCConstants::MAX_NUM_WIRES]) {
00478   // This version of the run() function can either be called in a standalone
00479   // test, being passed the time array, or called by the run() function above.
00480   // It gets wire times from an input array and then loops over the keywires.
00481   // All found LCT candidates are sorted and the best two are retained.
00482 
00483   bool trigger = false;
00484 
00485   // Check if there are any in-time hits and do the pulse extension.
00486   bool chamber_empty = pulseExtension(wire);
00487 
00488   // Only do the rest of the processing if chamber is not empty.
00489   // Stop drift_delay bx's short of fifo_tbins since at later bx's we will
00490   // not have a full set of hits to start pattern search anyway.
00491   unsigned int stop_bx = fifo_tbins - drift_delay;
00492   if (!chamber_empty) {
00493     for (int i_wire = 0; i_wire < numWireGroups; i_wire++) {
00494       unsigned int start_bx = 0;
00495       // Allow for more than one pass over the hits in the time window.
00496       while (start_bx < stop_bx) {
00497         if (preTrigger(i_wire, start_bx)) {
00498           if (infoV > 2) showPatterns(i_wire);
00499           if (patternDetection(i_wire)) {
00500             trigger = true;
00501             break;
00502           }
00503           else {
00504             // Assume that the earliest time when another pre-trigger can
00505             // occur in case pattern detection failed is bx_pretrigger+6:
00506             // this seems to match the data.
00507             start_bx = first_bx[i_wire] + drift_delay + 4;
00508           }
00509         }
00510         else {
00511           break;
00512         }
00513       }
00514     }
00515   }
00516 
00517   // Do the rest only if there is at least one trigger candidate.
00518   if (trigger) {
00519     ghostCancellationLogic();
00520     lctSearch();
00521   }
00522 }
00523 
00524 bool CSCAnodeLCTProcessor::getDigis(const CSCWireDigiCollection* wiredc) {
00525   // Routine for getting digis and filling digiV vector.
00526   bool noDigis = true;
00527   int  theRing    = CSCTriggerNumbering::ringFromTriggerLabels(theStation,
00528                                                                theTrigChamber);
00529   int  theChamber = CSCTriggerNumbering::chamberFromTriggerLabels(theSector,
00530                                      theSubsector, theStation, theTrigChamber);
00531 
00532   // Loop over layers and save wire digis on each one into digiV[layer].
00533   for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
00534     digiV[i_layer].clear();
00535 
00536     CSCDetId detid(theEndcap, theStation, theRing, theChamber, i_layer+1);
00537     getDigis(wiredc, detid);
00538 
00539     // If this is ME1/1, fetch digis in corresponding ME1/A (ring=4) as well.
00540     if (theStation == 1 && theRing == 1) {
00541       CSCDetId detid_me1a(theEndcap, theStation, 4, theChamber, i_layer+1);
00542       getDigis(wiredc, detid_me1a);
00543     }
00544 
00545     if (!digiV[i_layer].empty()) {
00546       noDigis = false;
00547       if (infoV > 1) {
00548         LogTrace("CSCAnodeLCTProcessor")
00549           << "found " << digiV[i_layer].size()
00550           << " wire digi(s) in layer " << i_layer << " of ME"
00551           << ((theEndcap == 1) ? "+" : "-") << theStation << "/" << theRing
00552           << "/" << theChamber << " (trig. sector " << theSector
00553           << " subsector " << theSubsector << " id " << theTrigChamber << ")";
00554         for (std::vector<CSCWireDigi>::iterator pld = digiV[i_layer].begin();
00555              pld != digiV[i_layer].end(); pld++) {
00556           LogTrace("CSCAnodeLCTProcessor") << "   " << (*pld);
00557         }
00558       }
00559     }
00560   }
00561 
00562   return noDigis;
00563 }
00564 
00565 void CSCAnodeLCTProcessor::getDigis(const CSCWireDigiCollection* wiredc,
00566                                     const CSCDetId& id) {
00567   const CSCWireDigiCollection::Range rwired = wiredc->get(id);
00568   for (CSCWireDigiCollection::const_iterator digiIt = rwired.first;
00569        digiIt != rwired.second; ++digiIt) {
00570     digiV[id.layer()-1].push_back(*digiIt);
00571   }
00572 }
00573 
00574 void CSCAnodeLCTProcessor::readWireDigis(std::vector<int> wire[CSCConstants::NUM_LAYERS][CSCConstants::MAX_NUM_WIRES]) {
00575   /* Gets wire times from the wire digis and fills wire[][] vector */
00576 
00577   // Loop over all 6 layers.
00578   for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
00579     // Loop over all digis in the layer and find the wireGroup and bx
00580     // time for each.
00581     for (std::vector<CSCWireDigi>::iterator pld = digiV[i_layer].begin();
00582          pld != digiV[i_layer].end(); pld++) {
00583       int i_wire  = pld->getWireGroup()-1;
00584       std::vector<int> bx_times = pld->getTimeBinsOn();
00585 
00586       // Check that the wires and times are appropriate.
00587       if (i_wire < 0 || i_wire >= numWireGroups) {
00588         if (infoV >= 0) edm::LogWarning("L1CSCTPEmulatorWrongInput")
00589           << "+++ Found wire digi with wrong wire number = " << i_wire
00590           << " (max wires = " << numWireGroups << "); skipping it... +++\n";
00591         continue;
00592       }
00593       // Accept digis in expected time window.  Total number of time
00594       // bins in DAQ readout is given by fifo_tbins, which thus
00595       // determines the maximum length of time interval.  Anode raw
00596       // hits in DAQ readout start (fifo_pretrig - 6) clocks before
00597       // L1Accept.  If times earlier than L1Accept were recorded, we
00598       // use them since they can modify the ALCTs found later, via
00599       // ghost-cancellation logic.
00600       int last_time = -999;
00601       if (bx_times.size() == fifo_tbins) {
00602         wire[i_layer][i_wire].push_back(0);     
00603         wire[i_layer][i_wire].push_back(6);
00604       }
00605       else {
00606         for (unsigned int i = 0; i < bx_times.size(); i++) {
00607           // Find rising edge change
00608           if (i > 0 && bx_times[i] == (bx_times[i-1]+1)) continue;
00609           if (bx_times[i] < static_cast<int>(fifo_tbins)) {
00610             if (infoV > 2) LogTrace("CSCAnodeLCTProcessor")
00611                              << "Digi on layer " << i_layer << " wire " << i_wire
00612                              << " at time " << bx_times[i];
00613 
00614             // Finally save times of hit wires.  One shot module will
00615             // not restart if a new pulse comes before the expiration
00616             // of the 6-bx period.
00617             if (last_time < 0 || ((bx_times[i]-last_time) >= 6) ) {
00618               wire[i_layer][i_wire].push_back(bx_times[i]);
00619               last_time = bx_times[i];
00620             }
00621           }
00622           else {
00623             if (infoV > 1) LogTrace("CSCAnodeLCTProcessor")
00624                              << "+++ Skipping wire digi: wire = " << i_wire
00625                              << " layer = " << i_layer << ", bx = " << bx_times[i] << " +++";
00626           }
00627         }
00628       }
00629     }
00630   }
00631 }
00632 
00633 bool CSCAnodeLCTProcessor::pulseExtension(const std::vector<int> wire[CSCConstants::NUM_LAYERS][CSCConstants::MAX_NUM_WIRES]){
00634   /* A pulse array will be used as a bit representation of hit times.
00635      For example: if a keywire has a bx_time of 3, then 1 shifted
00636      left 3 will be bit pattern 0000000000001000.  Bits are then added to
00637      signify the duration of a signal (hit_persist, formerly bx_width).  So
00638      for the pulse with a hit_persist of 6 will look like 0000000111111000. */
00639 
00640   bool chamber_empty = true;
00641   int i_wire, i_layer, digi_num;
00642   static unsigned int hit_persist = 6;
00643   static unsigned int bits_in_pulse = 8*sizeof(pulse[0][0]);
00644 
00645   for (i_wire = 0; i_wire < numWireGroups; i_wire++) {
00646     for (i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
00647       pulse[i_layer][i_wire] = 0;
00648     }
00649     first_bx[i_wire] = -999;
00650     for (int j = 0; j < 3; j++) quality[i_wire][j] = -999;
00651   }
00652 
00653   for (i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++){
00654     digi_num = 0;
00655     for (i_wire = 0; i_wire < numWireGroups; i_wire++) {
00656       if (wire[i_layer][i_wire].size() > 0) {
00657         std::vector<int> bx_times = wire[i_layer][i_wire];
00658         for (unsigned int i = 0; i < bx_times.size(); i++) {
00659           // Check that min and max times are within the allowed range.
00660           if (bx_times[i] < 0 || bx_times[i] + hit_persist >= bits_in_pulse) {
00661             if (infoV > 0) edm::LogWarning("L1CSCTPEmulatorOutOfTimeDigi")
00662               << "+++ BX time of wire digi (wire = " << i_wire
00663               << " layer = " << i_layer << ") bx = " << bx_times[i]
00664               << " is not within the range (0-" << bits_in_pulse
00665               << "] allowed for pulse extension.  Skip this digi! +++\n";
00666             continue;
00667           }
00668 
00669           // Found at least one in-time digi; set chamber_empty to false
00670           if (chamber_empty) chamber_empty = false;
00671 
00672           // make the pulse
00673           for (unsigned int bx = bx_times[i];
00674                bx < (bx_times[i] + hit_persist); bx++)
00675           pulse[i_layer][i_wire] = pulse[i_layer][i_wire] | (1 << bx);
00676 
00677           // Debug information.
00678           if (infoV > 1) {
00679             LogTrace("CSCAnodeLCTProcessor")
00680               << "Wire digi: layer " << i_layer
00681               << " digi #" << ++digi_num << " wire group " << i_wire
00682               << " time " << bx_times[i];
00683             if (infoV > 2) {
00684               std::ostringstream strstrm;
00685               for (int i = 1; i <= 32; i++) {
00686                 strstrm << ((pulse[i_layer][i_wire]>>(32-i)) & 1);
00687               }
00688               LogTrace("CSCAnodeLCTProcessor") << "  Pulse: " << strstrm.str();
00689             }
00690           }
00691         }
00692       }
00693     }
00694   }
00695 
00696   if (infoV > 1 && !chamber_empty) {
00697     dumpDigis(wire);
00698   }
00699 
00700   return chamber_empty;
00701 }
00702 
00703 bool CSCAnodeLCTProcessor::preTrigger(const int key_wire, const int start_bx) {
00704   /* Check that there are nplanes_hit_pretrig or more layers hit in collision
00705      or accelerator patterns for a particular key_wire.  If so, return
00706      true and the PatternDetection process will start. */
00707 
00708   unsigned int layers_hit;
00709   bool hit_layer[CSCConstants::NUM_LAYERS];
00710   int this_layer, this_wire;
00711   // If nplanes_hit_accel_pretrig is 0, the firmware uses the value
00712   // of nplanes_hit_pretrig instead.
00713   const unsigned int nplanes_hit_pretrig_acc =
00714     (nplanes_hit_accel_pretrig != 0) ? nplanes_hit_accel_pretrig :
00715     nplanes_hit_pretrig;
00716   const unsigned int pretrig_thresh[CSCConstants::NUM_ALCT_PATTERNS] = {
00717     nplanes_hit_pretrig_acc, nplanes_hit_pretrig, nplanes_hit_pretrig
00718   };
00719 
00720   // Loop over bx times, accelerator and collision patterns to 
00721   // look for pretrigger.
00722   // Stop drift_delay bx's short of fifo_tbins since at later bx's we will
00723   // not have a full set of hits to start pattern search anyway.
00724   unsigned int stop_bx = fifo_tbins - drift_delay;
00725   for (unsigned int bx_time = start_bx; bx_time < stop_bx; bx_time++) {
00726     for (int i_pattern = 0; i_pattern < CSCConstants::NUM_ALCT_PATTERNS; i_pattern++) {
00727       for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++)
00728         hit_layer[i_layer] = false;
00729       layers_hit = 0;
00730 
00731       for (int i_wire = 0; i_wire < NUM_PATTERN_WIRES; i_wire++){
00732         if (pattern_mask[i_pattern][i_wire] != 0){
00733           this_layer = pattern_envelope[0][i_wire];
00734           this_wire  = pattern_envelope[1+MESelection][i_wire]+key_wire;
00735           if ((this_wire >= 0) && (this_wire < numWireGroups)){
00736             // Perform bit operation to see if pulse is 1 at a certain bx_time.
00737             if (((pulse[this_layer][this_wire] >> bx_time) & 1) == 1) {
00738               // Store number of layers hit.
00739               if (hit_layer[this_layer] == false){
00740                 hit_layer[this_layer] = true;
00741                 layers_hit++;
00742               }
00743 
00744               // See if number of layers hit is greater than or equal to
00745               // pretrig_thresh.
00746               if (layers_hit >= pretrig_thresh[i_pattern]) {
00747                 first_bx[key_wire] = bx_time;
00748                 if (infoV > 1) {
00749                   LogTrace("CSCAnodeLCTProcessor")
00750                     << "Pretrigger was satisfied for wire: " << key_wire
00751                     << " pattern: " << i_pattern
00752                     << " bx_time: " << bx_time;
00753                 }
00754                 return true;
00755               }
00756             }
00757           }
00758         }
00759       }
00760     }
00761   }
00762   // If the pretrigger was never satisfied, then return false.
00763   return false;
00764 }
00765 
00766 bool CSCAnodeLCTProcessor::patternDetection(const int key_wire) {
00767   /* See if there is a pattern that satisfies nplanes_hit_pattern number of
00768      layers hit for either the accelerator or collision patterns.  Use
00769      the pattern with the best quality. */
00770 
00771   bool trigger = false;
00772   bool hit_layer[CSCConstants::NUM_LAYERS];
00773   unsigned int temp_quality;
00774   int this_layer, this_wire;
00775   // If nplanes_hit_accel_pattern is 0, the firmware uses the value
00776   // of nplanes_hit_pattern instead.
00777   const unsigned int nplanes_hit_pattern_acc =
00778     (nplanes_hit_accel_pattern != 0) ? nplanes_hit_accel_pattern :
00779     nplanes_hit_pattern;
00780   const unsigned int pattern_thresh[CSCConstants::NUM_ALCT_PATTERNS] = {
00781     nplanes_hit_pattern_acc, nplanes_hit_pattern, nplanes_hit_pattern
00782   };
00783   const std::string ptn_label[] = {"Accelerator", "CollisionA", "CollisionB"};
00784 
00785   for (int i_pattern = 0; i_pattern < CSCConstants::NUM_ALCT_PATTERNS; i_pattern++){
00786     temp_quality = 0;
00787     for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++)
00788       hit_layer[i_layer] = false;
00789 
00790     for (int i_wire = 0; i_wire < NUM_PATTERN_WIRES; i_wire++){
00791       if (pattern_mask[i_pattern][i_wire] != 0){
00792         this_layer = pattern_envelope[0][i_wire];
00793         this_wire  = pattern_envelope[1+MESelection][i_wire]+key_wire;
00794         if ((this_wire >= 0) && (this_wire < numWireGroups)){
00795 
00796           // Wait a drift_delay time later and look for layers hit in
00797           // the pattern.
00798           if (((pulse[this_layer][this_wire] >> 
00799                 (first_bx[key_wire] + drift_delay)) & 1) == 1) {
00800 
00801             // If layer has never had a hit before, then increment number
00802             // of layer hits.
00803             if (hit_layer[this_layer] == false){
00804               temp_quality++;
00805               // keep track of which layers already had hits.
00806               hit_layer[this_layer] = true;
00807               if (infoV > 1)
00808                 LogTrace("CSCAnodeLCTProcessor")
00809                   << "bx_time: " << first_bx[key_wire]
00810                   << " pattern: " << i_pattern << " keywire: " << key_wire
00811                   << " layer: "     << this_layer
00812                   << " quality: "   << temp_quality;
00813             }
00814           }
00815         }
00816       }
00817     }
00818     if (temp_quality >= pattern_thresh[i_pattern]) {
00819       trigger = true;
00820 
00821       if (!isTMB07) {
00822         // Quality reported by the pattern detector is defined as the number
00823         // of the layers hit in a pattern minus (pattern_thresh-1) value.
00824         temp_quality -= (pattern_thresh[i_pattern]-1);
00825       }
00826       else {
00827         // Quality definition changed on 22 June 2007: it no longer depends
00828         // on pattern_thresh.
00829         if (temp_quality > 3) temp_quality -= 3;
00830         else                  temp_quality  = 0; // quality code 0 is valid!
00831       }
00832 
00833       if (i_pattern == 0) {
00834         // Accelerator pattern
00835         quality[key_wire][0] = temp_quality;
00836       }
00837       else {
00838         // Only one collision pattern (of the best quality) is reported
00839         if (static_cast<int>(temp_quality) > quality[key_wire][1]) {
00840           quality[key_wire][1] = temp_quality;
00841           quality[key_wire][2] = i_pattern-1;
00842         }
00843       }
00844       if (infoV > 1) {
00845         LogTrace("CSCAnodeLCTProcessor")
00846           << "Pattern found; keywire: "  << key_wire
00847           << " type: " << ptn_label[i_pattern]
00848           << " quality: " << temp_quality << "\n";
00849       }
00850     }
00851   }
00852   if (infoV > 1 && quality[key_wire][1] > 0) {
00853     if (quality[key_wire][2] == 0)
00854       LogTrace("CSCAnodeLCTProcessor")
00855         << "Collision Pattern A is chosen" << "\n";
00856     else if (quality[key_wire][2] == 1)
00857       LogTrace("CSCAnodeLCTProcessor")
00858         << "Collision Pattern B is chosen" << "\n";
00859   }
00860   return trigger;
00861 }
00862 
00863 void CSCAnodeLCTProcessor::ghostCancellationLogic() {
00864   /* This function looks for LCTs on the previous and next wires.  If one
00865      exists and it has a better quality and a bx_time up to 4 clocks earlier
00866      than the present, then the present LCT is cancelled.  The present LCT
00867      also gets cancelled if it has the same quality as the one on the
00868      previous wire (this has not been done in 2003 test beam).  The
00869      cancellation is done separately for collision and accelerator patterns. */
00870 
00871   int ghost_cleared[CSCConstants::MAX_NUM_WIRES][2];
00872 
00873   for (int key_wire = 0; key_wire < numWireGroups; key_wire++) {
00874     for (int i_pattern = 0; i_pattern < 2; i_pattern++) {
00875       ghost_cleared[key_wire][i_pattern] = 0;
00876 
00877       // Non-empty wire group.
00878       int qual_this = quality[key_wire][i_pattern];
00879       if (qual_this > 0) {
00880 
00881         // Previous wire.
00882         int qual_prev = (key_wire > 0) ? quality[key_wire-1][i_pattern] : 0;
00883         if (qual_prev > 0) {
00884           int dt = first_bx[key_wire] - first_bx[key_wire-1];
00885           // Cancel this wire
00886           //   1) If the candidate at the previous wire is at the same bx
00887           //      clock and has better quality (or equal quality - this has
00888           //      been implemented only in 2004).
00889           //   2) If the candidate at the previous wire is up to 4 clocks
00890           //      earlier, regardless of quality.
00891           if (dt == 0) {
00892             if (qual_prev >= qual_this) ghost_cleared[key_wire][i_pattern] = 1;
00893           }
00894           else if (dt > 0 && dt <= 4) {
00895             // Next "if" check accounts for firmware bug and should be
00896             // removed once the next firmware version is used.
00897             // The bug is fixed in 5/5/2008 version of ALCT firmware,
00898             // which is used in all chambers starting with 26/05/2008.
00900             ghost_cleared[key_wire][i_pattern] = 1;
00901           }
00902         }
00903 
00904         // Next wire.
00905         // Skip this step if this wire is already declared "ghost".
00906         if (ghost_cleared[key_wire][i_pattern] == 1) {
00907           if (infoV > 1) LogTrace("CSCAnodeLCTProcessor")
00908             << ((i_pattern == 0) ? "Accelerator" : "Collision")
00909             << " pattern ghost cancelled on key_wire " << key_wire
00910             << " by wire " << key_wire-1;
00911           continue;
00912         }
00913 
00914         int qual_next =
00915           (key_wire < numWireGroups-1) ? quality[key_wire+1][i_pattern] : 0;
00916         if (qual_next > 0) {
00917           int dt = first_bx[key_wire] - first_bx[key_wire+1];
00918           // Same cancellation logic as for the previous wire.
00919           if (dt == 0) {
00920             if (qual_next > qual_this) ghost_cleared[key_wire][i_pattern] = 1;
00921           }
00922           else if (dt > 0 && dt <= 4) {
00923             // Next "if" check accounts for firmware bug and should be
00924             // removed once the next firmware version is used.
00925             // The bug is fixed in 5/5/2008 version of ALCT firmware,
00926             // which is used in all chambers starting with 26/05/2008.
00928             ghost_cleared[key_wire][i_pattern] = 1;
00929           }
00930         }
00931         if (ghost_cleared[key_wire][i_pattern] == 1) {
00932           if (infoV > 1) LogTrace("CSCAnodeLCTProcessor")
00933             << ((i_pattern == 0) ? "Accelerator" : "Collision")
00934             << " pattern ghost cancelled on key_wire " << key_wire
00935             << " by wire " << key_wire+1;
00936           continue;
00937         }
00938       }
00939     }
00940   }
00941 
00942   // All cancellation is done in parallel, so wiregroups do not know what
00943   // their neighbors are cancelling.
00944   for (int key_wire = 0; key_wire < numWireGroups; key_wire++) {
00945     for (int i_pattern = 0; i_pattern < 2; i_pattern++) {
00946       if (ghost_cleared[key_wire][i_pattern] > 0) {
00947         clear(key_wire, i_pattern);
00948       }
00949     }
00950   }
00951 }
00952 
00953 void CSCAnodeLCTProcessor::lctSearch() {
00954   // First modify the quality according accel_mode, then store all
00955   // of the valid LCTs in an array.
00956   std::vector<CSCALCTDigi> lct_list;
00957 
00958   for (int i_wire = 0; i_wire < numWireGroups; i_wire++) {
00959     // If there is either accelerator or collision, perform trigMode
00960     // function before storing and sorting.
00961     if (quality[i_wire][0] > 0 || quality[i_wire][1] > 0) {
00962       trigMode(i_wire);
00963 
00964       // Store any valid accelerator pattern LCTs.
00965       if (quality[i_wire][0] > 0) {
00966         int qual = (quality[i_wire][0] & 0x03); // 2 LSBs
00967         CSCALCTDigi lct_info(1, qual, 1, 0, i_wire, first_bx[i_wire]);
00968         lct_list.push_back(lct_info);
00969       }
00970 
00971       // Store any valid collision pattern LCTs.
00972       if (quality[i_wire][1] > 0) {
00973         int qual = (quality[i_wire][1] & 0x03); // 2 LSBs
00974         CSCALCTDigi lct_info(1, qual, 0, quality[i_wire][2], i_wire,
00975                              first_bx[i_wire]);
00976         lct_list.push_back(lct_info);
00977       }
00978 
00979       // Modify qualities according to accel_mode parameter.
00980       accelMode(i_wire);
00981     }
00982   }
00983 
00984   // Best track selector selects two collision and two accelerator ALCTs
00985   // with the best quality per time bin.
00986   std::vector<CSCALCTDigi> fourBest = bestTrackSelector(lct_list);
00987 
00988   // Select two best of four per time bin, based on quality and
00989   // accel_mode parameter.
00990   for (std::vector<CSCALCTDigi>::const_iterator plct = fourBest.begin();
00991        plct != fourBest.end(); plct++) {
00992 
00993     int bx = plct->getBX();
00994     if (bx >= MAX_ALCT_BINS) {
00995       if (infoV > 0) edm::LogWarning("L1CSCTPEmulatorOutOfTimeALCT")
00996         << "+++ Bx of ALCT candidate, " << bx << ", exceeds max allowed, "
00997         << MAX_ALCT_BINS-1 << "; skipping it... +++\n";
00998       continue;
00999     }
01000 
01001     if (isBetterALCT(*plct, bestALCT[bx])) {
01002       if (isBetterALCT(bestALCT[bx], secondALCT[bx])) {
01003         secondALCT[bx] = bestALCT[bx];
01004       }
01005       bestALCT[bx] = *plct;
01006     }
01007     else if (isBetterALCT(*plct, secondALCT[bx])) {
01008       secondALCT[bx] = *plct;
01009     }
01010   }
01011 
01012   if (!isTMB07) {
01013     // Prior to DAQ-2006 format, only ALCTs at the earliest bx were reported.
01014     int first_bx = MAX_ALCT_BINS;
01015     for (int bx = 0; bx < MAX_ALCT_BINS; bx++) {
01016       if (bestALCT[bx].isValid()) {
01017         first_bx = bx;
01018         break;
01019       }
01020     }
01021     if (first_bx < MAX_ALCT_BINS) {
01022       for (int bx = first_bx + 1; bx < MAX_ALCT_BINS; bx++) {
01023         if (bestALCT[bx].isValid())   bestALCT[bx].clear();
01024         if (secondALCT[bx].isValid()) secondALCT[bx].clear();
01025       }
01026     }
01027   }
01028 
01029   for (int bx = 0; bx < MAX_ALCT_BINS; bx++) {
01030     if (bestALCT[bx].isValid()) {
01031       bestALCT[bx].setTrknmb(1);
01032       if (infoV > 0) {
01033         LogDebug("CSCAnodeLCTProcessor")
01034           << "\n" << bestALCT[bx] << " found in ME"
01035           << ((theEndcap == 1) ? "+" : "-") << theStation << "/"
01036           << CSCTriggerNumbering::ringFromTriggerLabels(theStation,
01037                                                         theTrigChamber) << "/"
01038           << CSCTriggerNumbering::chamberFromTriggerLabels(theSector,
01039                               theSubsector, theStation, theTrigChamber)
01040           << " (sector " << theSector << " subsector " << theSubsector
01041           << " trig id. " << theTrigChamber << ")" << "\n";
01042       }
01043       if (secondALCT[bx].isValid()) {
01044         secondALCT[bx].setTrknmb(2);
01045         if (infoV > 0) {
01046           LogDebug("CSCAnodeLCTProcessor")
01047             << secondALCT[bx] << " found in ME"
01048             << ((theEndcap == 1) ? "+" : "-") << theStation << "/"
01049             << CSCTriggerNumbering::ringFromTriggerLabels(theStation,
01050                                                           theTrigChamber) <<"/"
01051             << CSCTriggerNumbering::chamberFromTriggerLabels(theSector,
01052                                 theSubsector, theStation, theTrigChamber)
01053             << " (sector " << theSector << " subsector " << theSubsector
01054             << " trig id. " << theTrigChamber << ")" << "\n";
01055         }
01056       }
01057     }
01058   }
01059 }
01060 
01061 std::vector<CSCALCTDigi> CSCAnodeLCTProcessor::bestTrackSelector(
01062                                  const std::vector<CSCALCTDigi>& all_alcts) {
01063   /* Selects two collision and two accelerator ALCTs per time bin with
01064      the best quality. */
01065   CSCALCTDigi bestALCTs[MAX_ALCT_BINS][2], secondALCTs[MAX_ALCT_BINS][2];
01066 
01067   if (infoV > 1) {
01068     LogTrace("CSCAnodeLCTProcessor") << all_alcts.size() <<
01069       " ALCTs at the input of best-track selector: ";
01070     for (std::vector <CSCALCTDigi>::const_iterator plct = all_alcts.begin();
01071          plct != all_alcts.end(); plct++) {
01072       if (!plct->isValid()) continue;
01073       LogTrace("CSCAnodeLCTProcessor") << (*plct);
01074     }
01075   }
01076 
01077   CSCALCTDigi tA[MAX_ALCT_BINS][2], tB[MAX_ALCT_BINS][2];
01078   for (std::vector <CSCALCTDigi>::const_iterator plct = all_alcts.begin();
01079        plct != all_alcts.end(); plct++) {
01080     if (!plct->isValid()) continue;
01081 
01082     // Select two collision and two accelerator ALCTs with the highest
01083     // quality at every bx.  The search for best ALCTs is done in parallel
01084     // for collision and accelerator patterns, and simultaneously for
01085     // two ALCTs, tA and tB.  If two or more ALCTs have equal qualities,
01086     // the priority is given to the ALCT with larger wiregroup number
01087     // in the search for tA (collision and accelerator), and to the ALCT
01088     // with smaller wiregroup number in the search for tB.
01089     int bx    = (*plct).getBX();
01090     int accel = (*plct).getAccelerator();
01091     int qual  = (*plct).getQuality();
01092     int wire  = (*plct).getKeyWG();
01093     bool vA = tA[bx][accel].isValid();
01094     bool vB = tB[bx][accel].isValid();
01095     int qA  = tA[bx][accel].getQuality();
01096     int qB  = tB[bx][accel].getQuality();
01097     int wA  = tA[bx][accel].getKeyWG();
01098     int wB  = tB[bx][accel].getKeyWG();
01099     if (!vA || qual > qA || (qual == qA && wire > wA)) {
01100       tA[bx][accel] = *plct;
01101     }
01102     if (!vB || qual > qB || (qual == qB && wire < wB)) {
01103       tB[bx][accel] = *plct;
01104     }
01105   }
01106 
01107   for (int bx = 0; bx < MAX_ALCT_BINS; bx++) {
01108     for (int accel = 0; accel <= 1; accel++) {
01109       // Best ALCT is always tA.
01110       if (tA[bx][accel].isValid()) {
01111         if (infoV > 2) {
01112           LogTrace("CSCAnodeLCTProcessor") << "tA: " << tA[bx][accel];
01113           LogTrace("CSCAnodeLCTProcessor") << "tB: " << tB[bx][accel];
01114         }
01115         bestALCTs[bx][accel] = tA[bx][accel];
01116 
01117         // If tA exists, tB exists too.
01118         if (tA[bx][accel] != tB[bx][accel] &&
01119             tA[bx][accel].getQuality() == tB[bx][accel].getQuality()) {
01120           secondALCTs[bx][accel] = tB[bx][accel];
01121         }
01122         else {
01123           // Funny part: if tA and tB are the same, or the quality of tB
01124           // is inferior to the quality of tA, the second best ALCT is
01125           // not tB.  Instead it is the largest-wiregroup ALCT among those
01126           // ALCT whose qualities are lower than the quality of the best one.
01127           for (std::vector <CSCALCTDigi>::const_iterator plct =
01128                  all_alcts.begin(); plct != all_alcts.end(); plct++) {
01129             if ((*plct).isValid() && 
01130                 (*plct).getAccelerator() == accel && (*plct).getBX() == bx &&
01131                 (*plct).getQuality() <  bestALCTs[bx][accel].getQuality() && 
01132                 (*plct).getQuality() >= secondALCTs[bx][accel].getQuality() &&
01133                 (*plct).getKeyWG()   >= secondALCTs[bx][accel].getKeyWG()) {
01134               secondALCTs[bx][accel] = *plct;
01135             }
01136           }
01137         }
01138       }
01139     }
01140   }
01141 
01142   // Fill the vector with up to four best ALCTs per bx and return it.
01143   std::vector<CSCALCTDigi> fourBest;
01144   for (int bx = 0; bx < MAX_ALCT_BINS; bx++) {
01145     for (int i = 0; i < 2; i++) {
01146       if (bestALCTs[bx][i].isValid())   fourBest.push_back(bestALCTs[bx][i]);
01147     }
01148     for (int i = 0; i < 2; i++) {
01149       if (secondALCTs[bx][i].isValid()) fourBest.push_back(secondALCTs[bx][i]);
01150     }
01151   }
01152 
01153   if (infoV > 1) {
01154     LogTrace("CSCAnodeLCTProcessor") << fourBest.size() << " ALCTs selected: ";
01155     for (std::vector<CSCALCTDigi>::const_iterator plct = fourBest.begin();
01156          plct != fourBest.end(); plct++) {
01157       LogTrace("CSCAnodeLCTProcessor") << (*plct);
01158     }
01159   }
01160 
01161   return fourBest;
01162 }
01163 
01164 bool CSCAnodeLCTProcessor::isBetterALCT(const CSCALCTDigi& lhsALCT,
01165                                         const CSCALCTDigi& rhsALCT) {
01166   /* This method should have been an overloaded > operator, but we
01167      have to keep it here since need to check values in quality[][]
01168      array modified according to accel_mode parameter. */
01169   bool returnValue = false;
01170 
01171   if (lhsALCT.isValid() && !rhsALCT.isValid()) {return true;}
01172 
01173   // ALCTs found at earlier bx times are ranked higher than ALCTs found at
01174   // later bx times regardless of the quality.
01175   if (lhsALCT.getBX()  < rhsALCT.getBX()) {returnValue = true;}
01176   if (lhsALCT.getBX() != rhsALCT.getBX()) {return returnValue;}
01177 
01178   // First check the quality of ALCTs.
01179   int qual1 = lhsALCT.getQuality();
01180   int qual2 = rhsALCT.getQuality();
01181   if (qual1 >  qual2) {returnValue = true;}
01182   // If qualities are the same, check accelerator bits of both ALCTs.
01183   // If they are not the same, rank according to accel_mode value.
01184   // If they are the same, keep the track selector assignment.
01185   else if (qual1 == qual2 && 
01186            lhsALCT.getAccelerator() != rhsALCT.getAccelerator() &&
01187            quality[lhsALCT.getKeyWG()][1-lhsALCT.getAccelerator()] >
01188            quality[rhsALCT.getKeyWG()][1-rhsALCT.getAccelerator()])
01189     {returnValue = true;}
01190 
01191   return returnValue;
01192 }
01193 
01194 void CSCAnodeLCTProcessor::trigMode(const int key_wire) {
01195   /* Function which enables/disables either collision or accelerator tracks.
01196      The function uses the trig_mode parameter to decide. */
01197 
01198   switch(trig_mode) {
01199   default:
01200   case 0:
01201     // Enables both collision and accelerator tracks
01202     break;
01203   case 1:
01204     // Disables collision tracks
01205     if (quality[key_wire][1] > 0) {
01206       quality[key_wire][1] = 0;
01207       if (infoV > 1) LogTrace("CSCAnodeLCTProcessor")
01208         << "trigMode(): collision track " << key_wire << " disabled" << "\n";
01209     }
01210     break;
01211   case 2:
01212     // Disables accelerator tracks
01213     if (quality[key_wire][0] > 0) {
01214       quality[key_wire][0] = 0;
01215       if (infoV > 1) LogTrace("CSCAnodeLCTProcessor")
01216         << "trigMode(): accelerator track " << key_wire << " disabled" << "\n";
01217     }
01218     break;
01219   case 3:
01220     // Disables collision track if there is an accelerator track found
01221     // in the same wire group at the same time
01222     if (quality[key_wire][0] > 0 && quality[key_wire][1] > 0) {
01223       quality[key_wire][1] = 0;
01224       if (infoV > 1) LogTrace("CSCAnodeLCTProcessor")
01225         << "trigMode(): collision track " << key_wire << " disabled" << "\n";
01226     }
01227     break;
01228   }
01229 }
01230 
01231 void CSCAnodeLCTProcessor::accelMode(const int key_wire) {
01232   /* Function which gives a preference either to the collision patterns
01233      or accelerator patterns.  The function uses the accel_mode parameter
01234      to decide. */
01235   int promotionBit = 1 << 2;
01236 
01237   switch(accel_mode) {
01238   default:
01239   case 0:
01240     // Ignore accelerator muons.
01241     if (quality[key_wire][0] > 0) {
01242       quality[key_wire][0] = 0;
01243       if (infoV > 1) LogTrace("CSCAnodeLCTProcessor")
01244         << "alctMode(): accelerator track " << key_wire << " ignored" << "\n";
01245     }
01246     break;
01247   case 1:
01248     // Prefer collision muons by adding promotion bit.
01249     if (quality[key_wire][1] > 0) {
01250       quality[key_wire][1] += promotionBit;
01251       if (infoV > 1) LogTrace("CSCAnodeLCTProcessor")
01252         << "alctMode(): collision track " << key_wire << " promoted" << "\n";
01253     }
01254     break;
01255   case 2:
01256     // Prefer accelerator muons by adding promotion bit.
01257     if (quality[key_wire][0] > 0) {
01258       quality[key_wire][0] += promotionBit;
01259       if (infoV > 1) LogTrace("CSCAnodeLCTProcessor")
01260         << "alctMode(): accelerator track " << key_wire << " promoted"<< "\n";
01261     }
01262     break;
01263   case 3:
01264     // Ignore collision muons.
01265     if (quality[key_wire][1] > 0) {
01266       quality[key_wire][1] = 0;
01267       if (infoV > 1) LogTrace("CSCAnodeLCTProcessor")
01268         << "alctMode(): collision track " << key_wire << " ignored" << "\n";
01269     }
01270     break;
01271   }
01272 }
01273 
01274 // Dump of configuration parameters.
01275 void CSCAnodeLCTProcessor::dumpConfigParams() const {
01276   std::ostringstream strm;
01277   strm << "\n";
01278   strm << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
01279   strm << "+                  ALCT configuration parameters:                  +\n";
01280   strm << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
01281   strm << " fifo_tbins   [total number of time bins in DAQ readout] = "
01282        << fifo_tbins << "\n";
01283   strm << " fifo_pretrig [start time of anode raw hits in DAQ readout] = "
01284        << fifo_pretrig << "\n";
01285   strm << " drift_delay  [drift delay after pre-trigger, in 25 ns bins] = "
01286        << drift_delay << "\n";
01287   strm << " nplanes_hit_pretrig [min. number of layers hit for pre-trigger] = "
01288        << nplanes_hit_pretrig << "\n";
01289   strm << " nplanes_hit_pattern [min. number of layers hit for trigger] = "
01290        << nplanes_hit_pattern << "\n";
01291   strm << " nplanes_hit_accel_pretrig [min. number of layers hit for accel."
01292        << " pre-trig.] = " << nplanes_hit_accel_pretrig << "\n";
01293   strm << " nplanes_hit_accel_pattern [min. number of layers hit for accel."
01294        << " trigger] = "   << nplanes_hit_accel_pattern << "\n";
01295   strm << " trig_mode  [enabling/disabling collision/accelerator tracks] = "
01296        << trig_mode << "\n";
01297   strm << " accel_mode [preference to collision/accelerator tracks] = "
01298        << accel_mode << "\n";
01299   strm << " l1a_window_width [L1Accept window width, in 25 ns bins] = "
01300        << l1a_window_width << "\n";
01301   strm << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
01302   LogDebug("CSCAnodeLCTProcessor") << strm.str();
01303 }
01304 
01305 // Dump of digis on wire groups.
01306 void CSCAnodeLCTProcessor::dumpDigis(const std::vector<int> wire[CSCConstants::NUM_LAYERS][CSCConstants::MAX_NUM_WIRES]) const {
01307   LogDebug("CSCAnodeLCTProcessor")
01308     << "ME" << ((theEndcap == 1) ? "+" : "-") << theStation << "/"
01309     << CSCTriggerNumbering::ringFromTriggerLabels(theStation, theTrigChamber)
01310     << "/" << CSCTriggerNumbering::chamberFromTriggerLabels(theSector,
01311                                     theSubsector, theStation, theTrigChamber)
01312     << " nWiregroups " << numWireGroups;
01313 
01314   std::ostringstream strstrm;
01315   for (int i_wire = 0; i_wire < numWireGroups; i_wire++) {
01316     if (i_wire%10 == 0) {
01317       if (i_wire < 100) strstrm << i_wire/10;
01318       else              strstrm << (i_wire-100)/10;
01319     }
01320     else                strstrm << " ";
01321   }
01322   strstrm << "\n";
01323   for (int i_wire = 0; i_wire < numWireGroups; i_wire++) {
01324     strstrm << i_wire%10;
01325   }
01326   for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
01327     strstrm << "\n";
01328     for (int i_wire = 0; i_wire < numWireGroups; i_wire++) {
01329       if (wire[i_layer][i_wire].size() > 0) {
01330         std::vector<int> bx_times = wire[i_layer][i_wire];
01331         strstrm << std::hex << bx_times[0] << std::dec;
01332       }
01333       else {
01334         strstrm << ".";
01335       }
01336     }
01337   }
01338   LogTrace("CSCAnodeLCTProcessor") << strstrm.str();
01339 }
01340 
01341 // Returns vector of read-out ALCTs, if any.  Starts with the vector of
01342 // all found ALCTs and selects the ones in the read-out time window.
01343 std::vector<CSCALCTDigi> CSCAnodeLCTProcessor::readoutALCTs() {
01344   std::vector<CSCALCTDigi> tmpV;
01345 
01346   static int fpga_latency = 6;
01347   static int early_tbins  = fifo_pretrig - fpga_latency;
01348   // The number of LCT bins in the read-out is given by the
01349   // l1a_window_width parameter, but made even by setting the LSB of
01350   // l1a_window_width to 0.
01351   static int lct_bins   = 
01352     //    (l1a_window_width%2 == 0) ? l1a_window_width : l1a_window_width-1;
01353     l1a_window_width;
01354   static int late_tbins = early_tbins + lct_bins;
01355 
01356   static int ifois = 0;
01357   if (ifois == 0) {
01358     if (infoV >= 0 && early_tbins < 0) {
01359       edm::LogWarning("L1CSCTPEmulatorSuspiciousParameters")
01360         << "+++ fifo_pretrig = " << fifo_pretrig
01361         << "; in-time ALCTs are not getting read-out!!! +++" << "\n";
01362     }
01363 
01364     if (late_tbins > MAX_ALCT_BINS-1) {
01365       if (infoV >= 0) edm::LogWarning("L1CSCTPEmulatorSuspiciousParameters")
01366         << "+++ Allowed range of time bins, [0-" << late_tbins
01367         << "] exceeds max allowed, " << MAX_ALCT_BINS-1 << " +++\n"
01368         << "+++ Set late_tbins to max allowed +++\n";
01369       late_tbins = MAX_ALCT_BINS-1;
01370     }
01371     ifois = 1;
01372   }
01373 
01374   // Start from the vector of all found ALCTs and select those within
01375   // the ALCT*L1A coincidence window.
01376   std::vector<CSCALCTDigi> all_alcts = getALCTs();
01377   for (std::vector <CSCALCTDigi>::const_iterator plct = all_alcts.begin();
01378        plct != all_alcts.end(); plct++) {
01379     if (!plct->isValid()) continue;
01380 
01381     int bx = (*plct).getBX();
01382     // Skip ALCTs found too early relative to L1Accept.
01383     if (bx <= early_tbins) {
01384       if (infoV > 1) LogDebug("CSCAnodeLCTProcessor")
01385         << " Do not report ALCT on keywire " << plct->getKeyWG()
01386         << ": found at bx " << bx << ", whereas the earliest allowed bx is "
01387         << early_tbins+1;
01388       continue;
01389     }
01390 
01391     // Skip ALCTs found too late relative to L1Accept.
01392     if (bx > late_tbins) {
01393       if (infoV > 1) LogDebug("CSCAnodeLCTProcessor")
01394         << " Do not report ALCT on keywire " << plct->getKeyWG()
01395         << ": found at bx " << bx << ", whereas the latest allowed bx is "
01396         << late_tbins;
01397       continue;
01398     }
01399 
01400     tmpV.push_back(*plct);
01401   }
01402   return tmpV;
01403 }
01404 
01405 // Returns vector of all found ALCTs, if any.  Used in ALCT-CLCT matching.
01406 std::vector<CSCALCTDigi> CSCAnodeLCTProcessor::getALCTs() {
01407   std::vector<CSCALCTDigi> tmpV;
01408   for (int bx = 0; bx < MAX_ALCT_BINS; bx++) {
01409     if (bestALCT[bx].isValid())   tmpV.push_back(bestALCT[bx]);
01410     if (secondALCT[bx].isValid()) tmpV.push_back(secondALCT[bx]);
01411   }
01412   return tmpV;
01413 }
01414 
01417 
01418 void CSCAnodeLCTProcessor::showPatterns(const int key_wire) {
01419   /* Method to test the pretrigger */
01420   for (int i_pattern = 0; i_pattern < CSCConstants::NUM_ALCT_PATTERNS;
01421        i_pattern++) {
01422     std::ostringstream strstrm_header;
01423     LogTrace("CSCAnodeLCTProcessor")
01424       << "\n" << "Pattern: " << i_pattern << " Key wire: " << key_wire;
01425     for (int i = 1; i <= 32; i++) {
01426       strstrm_header << ((32-i)%10);
01427     }
01428     LogTrace("CSCAnodeLCTProcessor") << strstrm_header.str();
01429     for (int i_wire = 0; i_wire < NUM_PATTERN_WIRES; i_wire++) {
01430       if (pattern_mask[i_pattern][i_wire] != 0) {
01431         std::ostringstream strstrm_pulse;
01432         int this_layer = pattern_envelope[0][i_wire];
01433         int this_wire  = pattern_envelope[1+MESelection][i_wire]+key_wire;
01434         if (this_wire >= 0 && this_wire < numWireGroups) {
01435           for (int i = 1; i <= 32; i++) {
01436             strstrm_pulse << ((pulse[this_layer][this_wire]>>(32-i)) & 1);
01437           }
01438           LogTrace("CSCAnodeLCTProcessor")
01439             << strstrm_pulse.str() << " on layer " << this_layer;
01440         }
01441       }
01442     }
01443     LogTrace("CSCAnodeLCTProcessor")
01444       << "-------------------------------------------";
01445   }
01446 }