CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
CSCMotherboardME21GEM.cc
Go to the documentation of this file.
8 #include <iomanip>
9 #include "boost/container/flat_set.hpp"
10 
11 const double CSCMotherboardME21GEM::lut_wg_eta_odd[112][2] = {
12 { 0,2.441},{ 1,2.435},{ 2,2.425},{ 3,2.414},{ 4,2.404},{ 5,2.394},{ 6,2.384},{ 7,2.374},
13 { 8,2.365},{ 9,2.355},{10,2.346},{11,2.336},{12,2.327},{13,2.317},{14,2.308},{15,2.299},
14 {16,2.290},{17,2.281},{18,2.273},{19,2.264},{20,2.255},{21,2.247},{22,2.238},{23,2.230},
15 {24,2.221},{25,2.213},{26,2.205},{27,2.197},{28,2.189},{29,2.181},{30,2.173},{31,2.165},
16 {32,2.157},{33,2.149},{34,2.142},{35,2.134},{36,2.127},{37,2.119},{38,2.112},{39,2.104},
17 {40,2.097},{41,2.090},{42,2.083},{43,2.075},{44,2.070},{45,2.059},{46,2.054},{47,2.047},
18 {48,2.041},{49,2.034},{50,2.027},{51,2.020},{52,2.014},{53,2.007},{54,2.000},{55,1.994},
19 {56,1.988},{57,1.981},{58,1.975},{59,1.968},{60,1.962},{61,1.956},{62,1.950},{63,1.944},
20 {64,1.937},{65,1.931},{66,1.924},{67,1.916},{68,1.909},{69,1.902},{70,1.895},{71,1.888},
21 {72,1.881},{73,1.875},{74,1.868},{75,1.861},{76,1.854},{77,1.848},{78,1.841},{79,1.835},
22 {80,1.830},{81,1.820},{82,1.815},{83,1.809},{84,1.803},{85,1.796},{86,1.790},{87,1.784},
23 {88,1.778},{89,1.772},{90,1.766},{91,1.760},{92,1.754},{93,1.748},{94,1.742},{95,1.736},
24 {96,1.731},{97,1.725},{98,1.719},{99,1.714},{100,1.708},{101,1.702},{102,1.697},{103,1.691},
25 {104,1.686},{105,1.680},{106,1.675},{107,1.670},{108,1.664},{109,1.659},{110,1.654},{111,1.648},
26 };
27 
28 const double CSCMotherboardME21GEM::lut_wg_eta_even[112][2] = {
29 { 0,2.412},{ 1,2.405},{ 2,2.395},{ 3,2.385},{ 4,2.375},{ 5,2.365},{ 6,2.355},{ 7,2.345},
30 { 8,2.335},{ 9,2.325},{10,2.316},{11,2.306},{12,2.297},{13,2.288},{14,2.279},{15,2.270},
31 {16,2.261},{17,2.252},{18,2.243},{19,2.234},{20,2.226},{21,2.217},{22,2.209},{23,2.200},
32 {24,2.192},{25,2.184},{26,2.175},{27,2.167},{28,2.159},{29,2.151},{30,2.143},{31,2.135},
33 {32,2.128},{33,2.120},{34,2.112},{35,2.105},{36,2.097},{37,2.090},{38,2.082},{39,2.075},
34 {40,2.068},{41,2.060},{42,2.053},{43,2.046},{44,2.041},{45,2.030},{46,2.025},{47,2.018},
35 {48,2.011},{49,2.005},{50,1.998},{51,1.991},{52,1.985},{53,1.978},{54,1.971},{55,1.965},
36 {56,1.958},{57,1.952},{58,1.946},{59,1.939},{60,1.933},{61,1.927},{62,1.921},{63,1.915},
37 {64,1.909},{65,1.902},{66,1.895},{67,1.887},{68,1.880},{69,1.873},{70,1.866},{71,1.859},
38 {72,1.853},{73,1.846},{74,1.839},{75,1.832},{76,1.826},{77,1.819},{78,1.812},{79,1.806},
39 {80,1.801},{81,1.792},{82,1.787},{83,1.780},{84,1.774},{85,1.768},{86,1.762},{87,1.756},
40 {88,1.750},{89,1.744},{90,1.738},{91,1.732},{92,1.726},{93,1.720},{94,1.714},{95,1.708},
41 {96,1.702},{97,1.697},{98,1.691},{99,1.685},{100,1.680},{101,1.674},{102,1.669},{103,1.663},
42 {104,1.658},{105,1.652},{106,1.647},{107,1.642},{108,1.636},{109,1.631},{110,1.626},{111,1.621},
43 };
44 
45 // LUT with bending angles of the GEM-CSC high efficiency patterns (98%)
46 // 1st index: pt value = {5,10,15,20,30,40}
47 // 2nd index: bending angle for odd numbered chambers
48 // 3rd index: bending angle for even numbered chambers
50  {3, 0.01832829, 0.01003643 },
51  {5, 0.01095490, 0.00631625 },
52  {7, 0.00786026, 0.00501017 },
53  {10, 0.00596349, 0.00414560 },
54  {15, 0.00462411, 0.00365550 },
55  {20, 0.00435298, 0.00361550 },
56  {30, 0.00465160, 0.00335700 },
57  {40, 0.00372145, 0.00366262 }
58 };
59 
61  unsigned sector, unsigned subsector,
62  unsigned chamber,
63  const edm::ParameterSet& conf) :
64  CSCMotherboard(endcap, station, sector, subsector, chamber, conf)
65 {
66  const edm::ParameterSet commonParams(conf.getParameter<edm::ParameterSet>("commonParam"));
67  runME21ILT_ = commonParams.getParameter<bool>("runME21ILT");
68 
69  if (!isSLHC) edm::LogError("L1CSCTPEmulatorConfigError")
70  << "+++ Upgrade CSCMotherboardME21GEM constructed while isSLHC is not set! +++\n";
71 
72  const edm::ParameterSet me21tmbParams(conf.getParameter<edm::ParameterSet>("me21tmbSLHCGEM"));
73 
74  // whether to not reuse CLCTs that were used by previous matching ALCTs
75  // in ALCT-to-CLCT algorithm
76  drop_used_clcts = me21tmbParams.getParameter<bool>("tmbDropUsedClcts");
77 
78  match_earliest_clct_me21_only = me21tmbParams.getParameter<bool>("matchEarliestClctME21Only");
79 
80  tmb_cross_bx_algo = me21tmbParams.getParameter<unsigned int>("tmbCrossBxAlgorithm");
81 
82  // maximum lcts per BX in ME2
83  max_me21_lcts = me21tmbParams.getParameter<unsigned int>("maxME21LCTs");
84 
86  for (unsigned int m=2; m<match_trig_window_size; m+=2)
87  {
88  pref[m-1] = pref[0] - m/2;
89  pref[m] = pref[0] + m/2;
90  }
91 
92  //----------------------------------------------------------------------------------------//
93 
94  // G E M - C S C I N T E G R A T E D L O C A L A L G O R I T H M
95 
96  //----------------------------------------------------------------------------------------//
97 
99  do_gem_matching = me21tmbParams.getParameter<bool>("doGemMatching");
100 
102  gem_match_delta_phi_odd = me21tmbParams.getParameter<double>("gemMatchDeltaPhiOdd");
103  gem_match_delta_phi_even = me21tmbParams.getParameter<double>("gemMatchDeltaPhiEven");
104  gem_match_delta_eta = me21tmbParams.getParameter<double>("gemMatchDeltaEta");
105 
107  gem_match_delta_bx = me21tmbParams.getParameter<int>("gemMatchDeltaBX");
108 
110  gem_match_min_eta = me21tmbParams.getParameter<double>("gemMatchMinEta");
111  gem_match_max_eta = me21tmbParams.getParameter<double>("gemMatchMaxEta");
112 
114  gem_clear_nomatch_lcts = me21tmbParams.getParameter<bool>("gemClearNomatchLCTs");
115 
116  // debug gem matching
117  debug_gem_matching = me21tmbParams.getParameter<bool>("debugMatching");
118  debug_luts = me21tmbParams.getParameter<bool>("debugLUTs");
119  debug_gem_dphi = me21tmbParams.getParameter<bool>("debugGEMDphi");
120 
121  // deltas used to construct GEM coincidence pads
122  maxDeltaBXInCoPad_ = me21tmbParams.getParameter<int>("maxDeltaBXInCoPad");
123  maxDeltaPadInCoPad_ = me21tmbParams.getParameter<int>("maxDeltaPadInCoPad");
124 
125  // deltas used to match to GEM pads
126  maxDeltaBXPad_ = me21tmbParams.getParameter<int>("maxDeltaBXPad");
127  maxDeltaPadPadOdd_ = me21tmbParams.getParameter<int>("maxDeltaPadPadOdd");
128  maxDeltaPadPadEven_ = me21tmbParams.getParameter<int>("maxDeltaPadPadEven");
129  maxDeltaWg_ = me21tmbParams.getParameter<int>("maxDeltaWg");
130 
131  // deltas used to match to GEM coincidence pads
132  maxDeltaBXCoPad_ = me21tmbParams.getParameter<int>("maxDeltaBXCoPad");
133  maxDeltaPadCoPad_ = me21tmbParams.getParameter<int>("maxDeltaPadCoPad");
134 
135  // drop low quality stubs if they don't have GEMs
136  dropLowQualityCLCTsNoGEMs_ = me21tmbParams.getParameter<bool>("dropLowQualityCLCTsNoGEMs");
137  dropLowQualityALCTsNoGEMs_ = me21tmbParams.getParameter<bool>("dropLowQualityALCTsNoGEMs");
138 
139  // correct LCT timing with GEMs
140  correctLCTtimingWithGEM_ = me21tmbParams.getParameter<bool>("correctLCTtimingWithGEM");
141 
142  // build LCT from ALCT and GEM
143  buildLCTfromALCTandGEM_ = me21tmbParams.getParameter<bool>("buildLCTfromALCTandGEM");
144  buildLCTfromCLCTandGEM_ = me21tmbParams.getParameter<bool>("buildLCTfromCLCTandGEM");
145 
146  // LCT ghostbusting
147  doLCTGhostBustingWithGEMs_ = me21tmbParams.getParameter<bool>("doLCTGhostBustingWithGEMs");
148 
149  // use "old" or "new" dataformat for integrated LCTs?
150  useOldLCTDataFormat_ = me21tmbParams.getParameter<bool>("useOldLCTDataFormat");
151 
152  // promote ALCT-GEM pattern
153  promoteALCTGEMpattern_ = me21tmbParams.getParameter<bool>("promoteALCTGEMpattern");
154 
155  // promote ALCT-GEM quality
156  promoteALCTGEMquality_ = me21tmbParams.getParameter<bool>("promoteALCTGEMquality");
157  promoteCLCTGEMquality_ = me21tmbParams.getParameter<bool>("promoteCLCTGEMquality");
158 }
159 
161 {
162 }
163 
165 {
167 
168  for (int bx = 0; bx < MAX_LCT_BINS; bx++)
169  for (unsigned int mbx = 0; mbx < match_trig_window_size; mbx++)
170  for (int i=0;i<2;i++)
171  allLCTs[bx][mbx][i].clear();
172 
173  gemRollToEtaLimits_.clear();
174  cscWgToGemRoll_.clear();
175  gemPadToCscHs_.clear();
176  cscHsToGemPad_.clear();
177  pads_.clear();
178  coPads_.clear();
179 }
180 
181 void
183  const CSCComparatorDigiCollection* compdc,
184  const GEMPadDigiCollection* gemPads)
185 {
186  clear();
187 
188  if (!( alct and clct and runME21ILT_))
189  {
190  if (infoV >= 0) edm::LogError("L1CSCTPEmulatorSetupError")
191  << "+++ run() called for non-existing ALCT/CLCT processor! +++ \n";
192  return;
193  }
194 
195  alct->run(wiredc); // run anodeLCT
196  clct->run(compdc); // run cathodeLCT
197 
198  bool gemGeometryAvailable(false);
199  if (gem_g != nullptr) {
200  if (infoV >= 0) edm::LogInfo("L1CSCTPEmulatorSetupInfo")
201  << "+++ run() called for GEM-CSC integrated trigger! +++ \n";
202  gemGeometryAvailable = true;
203  }
204 
205  // retrieve CSCChamber geometry
207  const CSCChamber* cscChamber(geo_manager->chamber(theEndcap, theStation, theSector, theSubsector, theTrigChamber));
208  const CSCDetId csc_id(cscChamber->id());
209 
210  if (runME21ILT_){
211 
212  // check for GE2/1 geometry
213  if ((not gemGeometryAvailable) or (gemGeometryAvailable and (gem_g->stations()).size()==2)) {
214  if (infoV >= 0) edm::LogError("L1CSCTPEmulatorSetupError")
215  << "+++ run() called for GEM-CSC integrated trigger without valid GE21 geometry! +++ \n";
216  return;
217  }
218 
219  // trigger geometry
220  const CSCLayer* keyLayer(cscChamber->layer(3));
221  const CSCLayerGeometry* keyLayerGeometry(keyLayer->geometry());
222 
223  // const bool isEven(csc_id%2==0);
224  const int region((theEndcap == 1) ? 1: -1);
225  const bool isEven(csc_id.chamber()%2==0);
226  const GEMDetId gem_id_long(region, 1, 3, 1, csc_id.chamber(), 0);
227  const GEMChamber* gemChamberLong(gem_g->chamber(gem_id_long));
228 
229  // LUT<roll,<etaMin,etaMax> >
231 
232  if (debug_luts){
233  std::cout<<"csc id "<< csc_id <<" "<< csc_id.rawId() << (isEven ? " even" : " odd") << " chamber" << csc_id.chamber()<<std::endl;
234  if (gemRollToEtaLimits_.size())
235  for(auto p : gemRollToEtaLimits_) {
236  std::cout << "pad "<< p.first << " min eta " << (p.second).first << " max eta " << (p.second).second << std::endl;
237  }
238  }
239 
240  // loop on all wiregroups to create a LUT <WG,rollMin,rollMax>
241  const int numberOfWG(keyLayerGeometry->numberOfWireGroups());
242  for (int i = 0; i< numberOfWG; ++i){
243  auto eta(isEven ? lut_wg_eta_even[i][1] : lut_wg_eta_odd[i][1]);
245  }
246  if (debug_luts){
247  for(auto p : cscWgToGemRoll_) {
248  std::cout << "WG "<< p.first << " GEM roll " << p.second << std::endl;
249  }
250  }
251 
252  auto randRoll(gemChamberLong->etaPartition(2));
253  auto nStrips(keyLayerGeometry->numberOfStrips());
254  for (float i = 0; i< nStrips; i = i+0.5){
255  const LocalPoint lpCSC(keyLayerGeometry->topology()->localPosition(i));
256  const GlobalPoint gp(keyLayer->toGlobal(lpCSC));
257  const LocalPoint lpGEM(randRoll->toLocal(gp));
258  const int HS(i/0.5);
259  const bool edge(HS < 5 or HS > 155);
260  const float pad(edge ? -99 : randRoll->pad(lpGEM));
261  // HS are wrapped-around
262  cscHsToGemPad_[HS] = std::make_pair(std::floor(pad),std::ceil(pad));
263  }
264  if (debug_luts){
265  std::cout << "detId " << csc_id << std::endl;
266  for(auto p : cscHsToGemPad_) {
267  std::cout << "CSC HS "<< p.first << " GEM Pad low " << (p.second).first << " GEM Pad high " << (p.second).second << std::endl;
268  }
269  }
270 
271  // pick any roll
272  const int nGEMPads(randRoll->npads());
273  for (int i = 0; i< nGEMPads; ++i){
274  const LocalPoint lpGEM(randRoll->centreOfPad(i));
275  const GlobalPoint gp(randRoll->toGlobal(lpGEM));
276  const LocalPoint lpCSC(keyLayer->toLocal(gp));
277  const float strip(keyLayerGeometry->strip(lpCSC));
278  // HS are wrapped-around
279  gemPadToCscHs_[i] = (int) (strip - 0.25)/0.5;
280  }
281  if (debug_luts){
282  std::cout << "detId " << csc_id << std::endl;
283  for(auto p : gemPadToCscHs_) {
284  std::cout << "GEM Pad "<< p.first << " CSC HS : " << p.second << std::endl;
285  }
286  }
287 
288  //select correct scenario, even or odd
290  // build coincidence pads
291  std::auto_ptr<GEMCoPadDigiCollection> pCoPads(new GEMCoPadDigiCollection());
292  buildCoincidencePads(gemPads, *pCoPads, csc_id);
293 
294  // retrieve pads and copads in a certain BX window for this CSC
295  pads_.clear();
296  coPads_.clear();
297  retrieveGEMPads(gemPads, gem_id_long);
298  retrieveGEMCoPads(pCoPads.get(), gem_id_long);
299  }
300 
301  int used_clct_mask[20];
302  for (int c=0;c<20;++c) used_clct_mask[c]=0;
303 
304  const bool hasPads(pads_.size()!=0);
305  const bool hasCoPads(hasPads and coPads_.size()!=0);
306 
307  // ALCT centric matching
308  for (int bx_alct = 0; bx_alct < CSCAnodeLCTProcessor::MAX_ALCT_BINS; bx_alct++)
309  {
310  if (alct->bestALCT[bx_alct].isValid())
311  {
312  const int bx_clct_start(bx_alct - match_trig_window_size/2);
313  const int bx_clct_stop(bx_alct + match_trig_window_size/2);
314  const int bx_copad_start(bx_alct - maxDeltaBXCoPad_);
315  const int bx_copad_stop(bx_alct + maxDeltaBXCoPad_);
316 
317  if (debug_gem_matching){
318  std::cout << "========================================================================" << std::endl;
319  std::cout << "ALCT-CLCT matching in ME2/1 chamber: " << cscChamber->id() << std::endl;
320  std::cout << "------------------------------------------------------------------------" << std::endl;
321  std::cout << "+++ Best ALCT Details: ";
322  alct->bestALCT[bx_alct].print();
323  std::cout << "+++ Second ALCT Details: ";
324  alct->secondALCT[bx_alct].print();
325 
326  printGEMTriggerPads(bx_clct_start, bx_clct_stop);
327 
328  std::cout << "------------------------------------------------------------------------" << std::endl;
329  std::cout << "Attempt ALCT-CLCT matching in ME2/1 in bx range: [" << bx_clct_start << "," << bx_clct_stop << "]" << std::endl;
330  }
331 
332  // ALCT-to-CLCT
333  int nSuccesFulMatches = 0;
334  for (int bx_clct = bx_clct_start; bx_clct <= bx_clct_stop; bx_clct++)
335  {
336  if (bx_clct < 0 or bx_clct >= CSCCathodeLCTProcessor::MAX_CLCT_BINS) continue;
337  if (drop_used_clcts and used_clct_mask[bx_clct]) continue;
338  if (clct->bestCLCT[bx_clct].isValid())
339  {
340  // clct quality
341  const int quality(clct->bestCLCT[bx_clct].getQuality());
342  // low quality ALCT
343  const bool lowQualityALCT(alct->bestALCT[bx_alct].getQuality() == 0);
344  // low quality ALCT or CLCT
345  const bool lowQuality(quality<4 or lowQualityALCT);
346  if (debug_gem_matching) std::cout << "++Valid ME21 CLCT: " << clct->bestCLCT[bx_clct] << std::endl;
347 
348  // pick the pad that corresponds
349  auto matchingPads(matchingGEMPads(clct->bestCLCT[bx_clct], alct->bestALCT[bx_alct], pads_[bx_clct], false));
350  auto matchingCoPads(matchingGEMPads(clct->bestCLCT[bx_clct], alct->bestALCT[bx_alct], coPads_[bx_clct], true));
351  if (runME21ILT_ and dropLowQualityCLCTsNoGEMs_ and lowQuality and hasPads){
352  int nFound(matchingPads.size());
353  const bool clctInEdge(clct->bestCLCT[bx_clct].getKeyStrip() < 5 or clct->bestCLCT[bx_clct].getKeyStrip() > 155);
354  if (clctInEdge){
355  if (debug_gem_matching) std::cout << "\tInfo: low quality CLCT in CSC chamber edge, don't care about GEM pads" << std::endl;
356  }
357  else {
358  if (nFound != 0){
359  if (debug_gem_matching) std::cout << "\tInfo: low quality CLCT with " << nFound << " matching GEM trigger pads" << std::endl;
360  }
361  else {
362  if (debug_gem_matching) std::cout << "\tWarning: low quality CLCT without matching GEM trigger pad" << std::endl;
363  continue;
364  }
365  }
366  }
367 
368  // check timing
369  if (runME21ILT_ and correctLCTtimingWithGEM_){
370  int nFound(matchingCoPads.size());
371  if (nFound != 0 and bx_alct == 6 and bx_clct != 6){
372  if (debug_gem_matching) std::cout << "\tInfo: CLCT with incorrect timing" << std::endl;
373  continue;
374  }
375  }
376 
377  ++nSuccesFulMatches;
378 
379  int mbx = bx_clct-bx_clct_start;
380 
381  correlateLCTsGEM(alct->bestALCT[bx_alct], alct->secondALCT[bx_alct],
382  clct->bestCLCT[bx_clct], clct->secondCLCT[bx_clct],
383  allLCTs[bx_alct][mbx][0], allLCTs[bx_alct][mbx][1], matchingPads, matchingCoPads);
384  if (debug_gem_matching) {
385  // if (infoV > 1) LogTrace("CSCMotherboard")
386  std::cout << "Successful ALCT-CLCT match in ME21: bx_alct = " << bx_alct
387  << "; match window: [" << bx_clct_start << "; " << bx_clct_stop
388  << "]; bx_clct = " << bx_clct << std::endl;
389  std::cout << "+++ Best CLCT Details: ";
390  clct->bestCLCT[bx_clct].print();
391  std::cout << "+++ Second CLCT Details: ";
392  clct->secondCLCT[bx_clct].print();
393  }
394  if (allLCTs[bx_alct][mbx][0].isValid()) {
395  used_clct_mask[bx_clct] += 1;
397  }
398  }
399  }
400 
401  // ALCT-to-GEM matching
402  int nSuccesFulGEMMatches = 0;
403  if (runME21ILT_ and nSuccesFulMatches==0 and buildLCTfromALCTandGEM_){
404  if (debug_gem_matching) std::cout << "++No valid ALCT-CLCT matches in ME21" << std::endl;
405  for (int bx_gem = bx_copad_start; bx_gem <= bx_copad_stop; bx_gem++) {
406  if (not hasCoPads) {
407  continue;
408  }
409 
410  // find the best matching copad - first one
411  auto copads(matchingGEMPads(alct->bestALCT[bx_alct], coPads_[bx_gem], true));
412  if (debug_gem_matching) std::cout << "\t++Number of matching GEM CoPads in BX " << bx_alct << " : "<< copads.size() << std::endl;
413  if (copads.size()==0) {
414  continue;
415  }
416 
417  correlateLCTsGEM(alct->bestALCT[bx_alct], alct->secondALCT[bx_alct],
418  *(copads.at(0)).second, allLCTs[bx_alct][0][0], allLCTs[bx_alct][0][1]);
419  if (allLCTs[bx_alct][0][0].isValid()) {
420  ++nSuccesFulGEMMatches;
422  }
423  if (debug_gem_matching) {
424  std::cout << "Successful ALCT-GEM CoPad match in ME21: bx_alct = " << bx_alct << std::endl << std::endl;
425  std::cout << "------------------------------------------------------------------------" << std::endl << std::endl;
426  }
427  }
428  }
429 
430  if (debug_gem_matching) {
431  std::cout << "========================================================================" << std::endl;
432  std::cout << "Summary: " << std::endl;
433  if (nSuccesFulMatches>1)
434  std::cout << "Too many successful ALCT-CLCT matches in ME21: " << nSuccesFulMatches
435  << ", CSCDetId " << cscChamber->id()
436  << ", bx_alct = " << bx_alct
437  << "; match window: [" << bx_clct_start << "; " << bx_clct_stop << "]" << std::endl;
438  else if (nSuccesFulMatches==1)
439  std::cout << "1 successful ALCT-CLCT match in ME21: "
440  << " CSCDetId " << cscChamber->id()
441  << ", bx_alct = " << bx_alct
442  << "; match window: [" << bx_clct_start << "; " << bx_clct_stop << "]" << std::endl;
443  else if (nSuccesFulGEMMatches==1)
444  std::cout << "1 successful ALCT-GEM match in ME21: "
445  << " CSCDetId " << cscChamber->id()
446  << ", bx_alct = " << bx_alct
447  << "; match window: [" << bx_clct_start << "; " << bx_clct_stop << "]" << std::endl;
448  else
449  std::cout << "Unsuccessful ALCT-CLCT match in ME21: "
450  << "CSCDetId " << cscChamber->id()
451  << ", bx_alct = " << bx_alct
452  << "; match window: [" << bx_clct_start << "; " << bx_clct_stop << "]" << std::endl;
453  }
454  }
455  // at this point we have invalid ALCTs --> try GEM pad matching
456  else{
457  auto coPads(coPads_[bx_alct]);
458  if (runME21ILT_ and coPads.size() and buildLCTfromCLCTandGEM_) {
459  //const int bx_clct_start(bx_alct - match_trig_window_size/2);
460  //const int bx_clct_stop(bx_alct + match_trig_window_size/2);
461 
462  if (debug_gem_matching){
463  std::cout << "========================================================================" << std::endl;
464  // std::cout << "GEM-CLCT matching in ME2/1 chamber: " << cscChamber->id() << " in bx range: [" << bx_clct_start << "," << bx_clct_stop << "]" << std::endl;
465  std::cout <<"GEM-CLCT matching in ME2/1 chamber: "<< cscChamber->id()<< "in bx:"<<bx_alct<<std::endl;
466  std::cout << "------------------------------------------------------------------------" << std::endl;
467  }
468  // GEM-to-CLCT
469  int nSuccesFulMatches = 0;
470  //for (int bx_clct = bx_clct_start; bx_clct <= bx_clct_stop; bx_clct++)
471  // {
472  // if (bx_clct < 0 or bx_clct >= CSCCathodeLCTProcessor::MAX_CLCT_BINS) continue;
473  if (drop_used_clcts and used_clct_mask[bx_alct]) continue;
474  if (clct->bestCLCT[bx_alct].isValid())
475  {
476  const int quality(clct->bestCLCT[bx_alct].getQuality());
477  // only use high-Q stubs for the time being
478  if (quality < 4) continue;
479 
480  ++nSuccesFulMatches;
481 
482  int mbx = std::abs(clct->bestCLCT[bx_alct].getBX()-bx_alct);
483  int bx_gem = (coPads[0].second)->bx()+lct_central_bx;
484  correlateLCTsGEM(clct->bestCLCT[bx_alct], clct->secondCLCT[bx_alct], *(coPads[0].second), GEMDetId(coPads[0].first).roll(),
485  allLCTs[bx_gem][mbx][0], allLCTs[bx_gem][mbx][1]);
486  if (debug_gem_matching) {
487  // if (infoV > 1) LogTrace("CSCMotherboard")
488  std::cout << "Successful GEM-CLCT match in ME21: bx_alct = " << bx_alct <<std::endl;
489  //<< "; match window: [" << bx_clct_start << "; " << bx_clct_stop
490  //<< "]; bx_clct = " << bx_clct << std::endl;
491  std::cout << "+++ Best CLCT Details: ";
492  clct->bestCLCT[bx_alct].print();
493  std::cout << "+++ Second CLCT Details: ";
494  clct->secondCLCT[bx_alct].print();
495  }
496  if (allLCTs[bx_gem][mbx][0].isValid()) {
497  used_clct_mask[bx_alct] += 1;
499  }
500  }
501  }
502  }
503  }
504 
505  // Possibly use some discrimination from GEMs
506  if (gemGeometryAvailable and runME21ILT_ and do_gem_matching) matchGEMPads();
507 
508  // reduction of nLCTs per each BX
509  for (int bx = 0; bx < MAX_LCT_BINS; bx++)
510  {
511  // counting
512  unsigned int n=0;
513  for (unsigned int mbx = 0; mbx < match_trig_window_size; mbx++)
514  for (int i=0;i<2;i++)
515  {
516  int cbx = bx + mbx - match_trig_window_size/2;
517  if (allLCTs[bx][mbx][i].isValid())
518  {
519  ++n;
520  if (infoV > 0) LogDebug("CSCMotherboard")
521  << "LCT"<<i+1<<" "<<bx<<"/"<<cbx<<": "<<allLCTs[bx][mbx][i]<<std::endl;
522  }
523  }
524 
525  // some simple cross-bx sorting algorithms
526  if (tmb_cross_bx_algo == 1 and (n>2))
527  {
528  n=0;
529  for (unsigned int mbx = 0; mbx < match_trig_window_size; mbx++)
530  for (int i=0;i<2;i++)
531  {
532  if (allLCTs[bx][pref[mbx]][i].isValid())
533  {
534  n++;
535  if (n>2) allLCTs[bx][pref[mbx]][i].clear();
536  }
537  }
538 
539  n=0;
540  for (unsigned int mbx = 0; mbx < match_trig_window_size; mbx++)
541  for (int i=0;i<2;i++)
542  {
543  int cbx = bx + mbx - match_trig_window_size/2;
544  if (allLCTs[bx][mbx][i].isValid())
545  {
546  n++;
547  if (infoV > 0) LogDebug("CSCMotherboard")
548  << "LCT"<<i+1<<" "<<bx<<"/"<<cbx<<": "<<allLCTs[bx][mbx][i]<<std::cout;
549  }
550  }
551  if (infoV > 0 and n>0) LogDebug("CSCMotherboard")
552  <<"bx "<<bx<<" nnLCT:"<<n<<" "<<n<<std::endl;
553  } // x-bx sorting
554  }
555 
556  bool first = true;
557  unsigned int n=0;
558  for (auto p : readoutLCTs()) {
559  if (debug_gem_matching and first){
560  std::cout << "========================================================================" << std::endl;
561  std::cout << "Counting the final LCTs" << std::endl;
562  std::cout << "========================================================================" << std::endl;
563  first = false;
564  std::cout << "tmb_cross_bx_algo: " << tmb_cross_bx_algo << std::endl;
565  }
566  n++;
567  if (debug_gem_matching)
568  std::cout << "LCT "<<n<<" " << p <<std::endl;
569  }
570 }
571 
572 
573 //readout LCTs
574 std::vector<CSCCorrelatedLCTDigi> CSCMotherboardME21GEM::readoutLCTs()
575 {
576  return getLCTs();
577 }
578 
579 //getLCTs when we use different sort algorithm
580 std::vector<CSCCorrelatedLCTDigi> CSCMotherboardME21GEM::getLCTs()
581 {
582  std::vector<CSCCorrelatedLCTDigi> result;
583  for (int bx = 0; bx < MAX_LCT_BINS; bx++) {
584  std::vector<CSCCorrelatedLCTDigi> tmpV;
585  if (tmb_cross_bx_algo == 2) {
586  tmpV = sortLCTsByQuality(bx);
587  result.insert(result.end(), tmpV.begin(), tmpV.end());
588  }
589  else if (tmb_cross_bx_algo == 3) {
590  tmpV = sortLCTsByGEMDPhi(bx);
591  result.insert(result.end(), tmpV.begin(), tmpV.end());
592  }
593  else {
594  for (unsigned int mbx = 0; mbx < match_trig_window_size; mbx++) {
595  for (int i=0;i<2;i++) {
596  if (allLCTs[bx][mbx][i].isValid()) {
597  result.push_back(allLCTs[bx][mbx][i]);
598  }
599  }
600  }
601  }
602  }
603  return result;
604 }
605 
606 //sort LCTs by Quality in each BX
607 std::vector<CSCCorrelatedLCTDigi> CSCMotherboardME21GEM::sortLCTsByQuality(int bx)
608 {
609  std::vector<CSCCorrelatedLCTDigi> LCTs;
610  LCTs.clear();
611  for (unsigned int mbx = 0; mbx < match_trig_window_size; mbx++)
612  for (int i=0;i<2;i++)
613  if (allLCTs[bx][mbx][i].isValid())
614  LCTs.push_back(allLCTs[bx][mbx][i]);
615 
616  //std::cout<<"LCT before sorting in Bx:"<<bx<<std::endl;
617  //for (auto p : LCTs)
618  // std::cout<< p <<std::endl;
619  // return sorted vector with 2 highest quality LCTs
620  std::sort(LCTs.begin(), LCTs.end(), CSCMotherboard::sortByQuality);
621  if (LCTs.size()> max_me21_lcts) LCTs.erase(LCTs.begin()+max_me21_lcts, LCTs.end());
622  //std::cout<<"LCT after sorting by quality in BX:"<<bx<<std::endl;
623  //for (auto p : LCTs)
624  // std::cout<< p <<std::endl;
625  return LCTs;
626 }
627 
628 //sort LCTs by dphi in each BX
629 std::vector<CSCCorrelatedLCTDigi> CSCMotherboardME21GEM::sortLCTsByGEMDPhi(int bx)
630 {
631  std::vector<CSCCorrelatedLCTDigi> LCTs;
632  LCTs.clear();
633  for (unsigned int mbx = 0; mbx < match_trig_window_size; mbx++)
634  for (int i=0;i<2;i++)
635  if (allLCTs[bx][mbx][i].isValid())
636  LCTs.push_back(allLCTs[bx][mbx][i]);
637 
638  // return sorted vector with 2 highest quality LCTs
639  std::sort(LCTs.begin(), LCTs.end(), CSCMotherboard::sortByGEMDphi);
640  if (LCTs.size()> max_me21_lcts) LCTs.erase(LCTs.begin()+max_me21_lcts, LCTs.end());
641  return LCTs;
642 }
643 
644 
646  CSCALCTDigi secondALCT,
647  CSCCLCTDigi bestCLCT,
648  CSCCLCTDigi secondCLCT,
649  CSCCorrelatedLCTDigi& lct1,
650  CSCCorrelatedLCTDigi& lct2,
651  const GEMPadsBX& pads,
652  const GEMPadsBX& copads)
653 {
654  // check for pads
655  const int nPads(pads.size());
656  const int nCoPads(copads.size());
657  const bool hasPads(nPads!=0);
658  const bool hasCoPads(nCoPads!=0);
659 
660  bool anodeBestValid = bestALCT.isValid();
661  bool anodeSecondValid = secondALCT.isValid();
662  bool cathodeBestValid = bestCLCT.isValid();
663  bool cathodeSecondValid = secondCLCT.isValid();
664 
665  if (anodeBestValid and !anodeSecondValid) secondALCT = bestALCT;
666  if (!anodeBestValid and anodeSecondValid) bestALCT = secondALCT;
667  if (cathodeBestValid and !cathodeSecondValid) secondCLCT = bestCLCT;
668  if (!cathodeBestValid and cathodeSecondValid) bestCLCT = secondCLCT;
669 
670  // ALCT-CLCT matching conditions are defined by "trig_enable" configuration
671  // parameters.
672  if ((alct_trig_enable and bestALCT.isValid()) or
673  (clct_trig_enable and bestCLCT.isValid()) or
674  (match_trig_enable and bestALCT.isValid() and bestCLCT.isValid()))
675  {
676  lct1 = constructLCTsGEM(bestALCT, bestCLCT, hasPads, hasCoPads);
677  lct1.setTrknmb(1);
678  }
679 
680  if (((secondALCT != bestALCT) or (secondCLCT != bestCLCT)) and
681  ((alct_trig_enable and secondALCT.isValid()) or
682  (clct_trig_enable and secondCLCT.isValid()) or
683  (match_trig_enable and secondALCT.isValid() and secondCLCT.isValid())))
684  {
685  lct2 = constructLCTsGEM(secondALCT, secondCLCT, hasPads, hasCoPads);
686  lct2.setTrknmb(2);
687  }
688 }
689 
690 
692  CSCALCTDigi secondALCT,
693  GEMPadDigi gemPad,
694  CSCCorrelatedLCTDigi& lct1,
695  CSCCorrelatedLCTDigi& lct2)
696 {
697  bool anodeBestValid = bestALCT.isValid();
698  bool anodeSecondValid = secondALCT.isValid();
699 
700  if (anodeBestValid and !anodeSecondValid) secondALCT = bestALCT;
701  if (!anodeBestValid and anodeSecondValid) bestALCT = secondALCT;
702 
703  if ((alct_trig_enable and bestALCT.isValid()) or
704  (match_trig_enable and bestALCT.isValid()))
705  {
706  lct1 = constructLCTsGEM(bestALCT, gemPad, useOldLCTDataFormat_);
707  lct1.setTrknmb(1);
708  // lct1.setGEMDPhi(0.0);
709  }
710 
711  if ((alct_trig_enable and secondALCT.isValid()) or
712  (match_trig_enable and secondALCT.isValid() and secondALCT != bestALCT))
713  {
714  lct2 = constructLCTsGEM(secondALCT, gemPad, useOldLCTDataFormat_);
715  lct2.setTrknmb(2);
716  // lct2.setGEMDPhi(0.0);
717  }
718 }
719 
720 
722  CSCCLCTDigi secondCLCT,
723  GEMPadDigi gemPad, int roll,
724  CSCCorrelatedLCTDigi& lct1,
725  CSCCorrelatedLCTDigi& lct2)
726 {
727  bool cathodeBestValid = bestCLCT.isValid();
728  bool cathodeSecondValid = secondCLCT.isValid();
729 
730  if (cathodeBestValid and !cathodeSecondValid) secondCLCT = bestCLCT;
731  if (!cathodeBestValid and cathodeSecondValid) bestCLCT = secondCLCT;
732 
733  if ((clct_trig_enable and bestCLCT.isValid()) or
734  (match_trig_enable and bestCLCT.isValid()))
735  {
736  lct1 = constructLCTsGEM(bestCLCT, gemPad, roll, useOldLCTDataFormat_);
737  lct1.setTrknmb(1);
738  }
739 
740  if ((clct_trig_enable and secondCLCT.isValid()) or
741  (match_trig_enable and secondCLCT.isValid() and secondCLCT != bestCLCT))
742  {
743  lct2 = constructLCTsGEM(secondCLCT, gemPad, roll, useOldLCTDataFormat_);
744  lct2.setTrknmb(2);
745  }
746 }
747 
748 
750  const GEMPadDigi& gem,
751  bool oldDataFormat)
752 {
753  if (oldDataFormat){
754  // CLCT pattern number - set it to a highest value
755  // hack to get LCTs in the CSCTF
756  unsigned int pattern = promoteALCTGEMpattern_ ? 10 : 0;
757 
758  // LCT quality number - set it to a very high value
759  // hack to get LCTs in the CSCTF
760  unsigned int quality = promoteALCTGEMquality_ ? 14 : 11;
761 
762  // Bunch crossing
763  int bx = alct.getBX();
764 
765  // get keyStrip from LUT
766  int keyStrip = gemPadToCscHs_[gem.pad()];
767 
768  // get wiregroup from ALCT
769  int wg = alct.getKeyWG();
770 
771  // construct correlated LCT; temporarily assign track number of 0.
772  return CSCCorrelatedLCTDigi(0, 1, quality, wg, keyStrip, pattern, 0, bx, 0, 0, 0, theTrigChamber);
773  }
774  else {
775  // CLCT pattern number - no pattern
776  unsigned int pattern = 0;
777 
778  // LCT quality number
779  unsigned int quality = 1;
780 
781  // Bunch crossing
782  int bx = gem.bx() + lct_central_bx;
783 
784  // get keyStrip from LUT
785  int keyStrip = gemPadToCscHs_[gem.pad()];
786  // get wiregroup from ALCT
787  int wg = alct.getKeyWG();
788 
789  // construct correlated LCT; temporarily assign track number of 0.
790  return CSCCorrelatedLCTDigi(0, 1, quality, wg, keyStrip, pattern, 0, bx, 0, 0, 0, theTrigChamber);
791  }
792 }
793 
795  const GEMPadDigi& gem, int roll,
796  bool oldDataFormat)
797 {
798  if (oldDataFormat){
799  // CLCT pattern number - for the time being, do not include GEMs in the pattern
800  unsigned int pattern = encodePattern(clct.getPattern(), clct.getStripType());
801 
802  // LCT quality number - dummy quality
803  unsigned int quality = promoteCLCTGEMquality_ ? 14 : 11;
804 
805  // Bunch crossing: pick GEM bx
806  int bx = gem.bx() + lct_central_bx;
807 
808  // pick a random WG in the roll range
809  int wg(20);
810 
811  // construct correlated LCT; temporarily assign track number of 0.
812  return CSCCorrelatedLCTDigi(0, 1, quality, wg, clct.getKeyStrip(), pattern, clct.getBend(), bx, 0, 0, 0, theTrigChamber);
813  }
814  else {
815  // CLCT pattern number - no pattern
816  unsigned int pattern = 0;//encodePatternGEM(clct.getPattern(), clct.getStripType());
817 
818  // LCT quality number - dummy quality
819  unsigned int quality = 5;//findQualityGEM(alct, gem);
820 
821  // Bunch crossing: get it from cathode LCT if anode LCT is not there.
822  int bx = gem.bx() + lct_central_bx;;
823 
824  // ALCT WG
825  int wg(0);
826 
827  // construct correlated LCT; temporarily assign track number of 0.
828  return CSCCorrelatedLCTDigi(0, 1, quality, wg, 0, pattern, 0, bx, 0, 0, 0, theTrigChamber);
829  }
830 }
831 
832 
834  bool hasPad, bool hasCoPad)
835 {
836  // CLCT pattern number
837  unsigned int pattern = encodePattern(cLCT.getPattern(), cLCT.getStripType());
838 
839  // LCT quality number
840  unsigned int quality = findQualityGEM(aLCT, cLCT, hasPad, hasCoPad);
841 
842  // Bunch crossing: get it from cathode LCT if anode LCT is not there.
843  int bx = aLCT.isValid() ? aLCT.getBX() : cLCT.getBX();
844 
845  // construct correlated LCT; temporarily assign track number of 0.
846  int trknmb = 0;
847  CSCCorrelatedLCTDigi thisLCT(trknmb, 1, quality, aLCT.getKeyWG(),
848  cLCT.getKeyStrip(), pattern, cLCT.getBend(),
849  bx, 0, 0, 0, theTrigChamber);
850  return thisLCT;
851 }
852 
853 
854 unsigned int CSCMotherboardME21GEM::findQualityGEM(const CSCALCTDigi& aLCT, const CSCCLCTDigi& cLCT,
855  bool hasPad, bool hasCoPad)
856 {
857 
858  /*
859  Same LCT quality definition as standard LCTs
860  c4 takes GEMs into account!!!
861  */
862 
863  unsigned int quality = 0;
864 
865  if (!isTMB07) {
866  bool isDistrip = (cLCT.getStripType() == 0);
867 
868  if (aLCT.isValid() && !(cLCT.isValid())) { // no CLCT
869  if (aLCT.getAccelerator()) {quality = 1;}
870  else {quality = 3;}
871  }
872  else if (!(aLCT.isValid()) && cLCT.isValid()) { // no ALCT
873  if (isDistrip) {quality = 4;}
874  else {quality = 5;}
875  }
876  else if (aLCT.isValid() && cLCT.isValid()) { // both ALCT and CLCT
877  if (aLCT.getAccelerator()) {quality = 2;} // accelerator muon
878  else { // collision muon
879  // CLCT quality is, in fact, the number of layers hit, so subtract 3
880  // to get quality analogous to ALCT one.
881  int sumQual = aLCT.getQuality() + (cLCT.getQuality()-3);
882  if (sumQual < 1 || sumQual > 6) {
883  if (infoV >= 0) edm::LogWarning("L1CSCTPEmulatorWrongValues")
884  << "+++ findQuality: sumQual = " << sumQual << "+++ \n";
885  }
886  if (isDistrip) { // distrip pattern
887  if (sumQual == 2) {quality = 6;}
888  else if (sumQual == 3) {quality = 7;}
889  else if (sumQual == 4) {quality = 8;}
890  else if (sumQual == 5) {quality = 9;}
891  else if (sumQual == 6) {quality = 10;}
892  }
893  else { // halfstrip pattern
894  if (sumQual == 2) {quality = 11;}
895  else if (sumQual == 3) {quality = 12;}
896  else if (sumQual == 4) {quality = 13;}
897  else if (sumQual == 5) {quality = 14;}
898  else if (sumQual == 6) {quality = 15;}
899  }
900  }
901  }
902  }
903 #ifdef OLD
904  else {
905  // Temporary definition, used until July 2008.
906  // First if statement is fictitious, just to help the CSC TF emulator
907  // handle such cases (one needs to make sure they will be accounted for
908  // in the new quality definition.
909  if (!(aLCT.isValid()) || !(cLCT.isValid())) {
910  if (aLCT.isValid() && !(cLCT.isValid())) quality = 1; // no CLCT
911  else if (!(aLCT.isValid()) && cLCT.isValid()) quality = 2; // no ALCT
912  else quality = 0; // both absent; should never happen.
913  }
914  else {
915  // Sum of ALCT and CLCT quality bits. CLCT quality is, in fact, the
916  // number of layers hit, so subtract 3 to put it to the same footing as
917  // the ALCT quality.
918  int sumQual = aLCT.getQuality() + (cLCT.getQuality()-3);
919  if (sumQual < 1 || sumQual > 6) {
920  if (infoV >= 0) edm::LogWarning("L1CSCTPEmulatorWrongValues")
921  << "+++ findQuality: Unexpected sumQual = " << sumQual << "+++\n";
922  }
923 
924  // LCT quality is basically the sum of ALCT and CLCT qualities, but split
925  // in two groups depending on the CLCT pattern id (higher quality for
926  // straighter patterns).
927  int offset = 0;
928  if (cLCT.getPattern() <= 7) offset = 4;
929  else offset = 9;
930  quality = offset + sumQual;
931  }
932  }
933 #endif
934  else {
935  // 2008 definition.
936  if (!(aLCT.isValid()) || !(cLCT.isValid())) {
937  if (aLCT.isValid() && !(cLCT.isValid())) quality = 1; // no CLCT
938  else if (!(aLCT.isValid()) && cLCT.isValid()) quality = 2; // no ALCT
939  else quality = 0; // both absent; should never happen.
940  }
941  else {
942  const int pattern(cLCT.getPattern());
943  if (pattern == 1) quality = 3; // layer-trigger in CLCT
944  else {
945  // ALCT quality is the number of layers hit minus 3.
946  // CLCT quality is the number of layers hit.
947  int n_gem = 0;
948  if (hasPad) n_gem = 1;
949  if (hasCoPad) n_gem = 2;
950  const bool a4((aLCT.getQuality() >= 1) or (aLCT.getQuality() >= 0 and n_gem >=1));
951  const bool c4((cLCT.getQuality() >= 4) or (cLCT.getQuality() >= 3 and n_gem>=1));
952  // quality = 4; "reserved for low-quality muons in future"
953  if (!a4 && !c4) quality = 5; // marginal anode and cathode
954  else if ( a4 && !c4) quality = 6; // HQ anode, but marginal cathode
955  else if (!a4 && c4) quality = 7; // HQ cathode, but marginal anode
956  else if ( a4 && c4) {
957  if (aLCT.getAccelerator()) quality = 8; // HQ muon, but accel ALCT
958  else {
959  // quality = 9; "reserved for HQ muons with future patterns
960  // quality = 10; "reserved for HQ muons with future patterns
961  if (pattern == 2 || pattern == 3) quality = 11;
962  else if (pattern == 4 || pattern == 5) quality = 12;
963  else if (pattern == 6 || pattern == 7) quality = 13;
964  else if (pattern == 8 || pattern == 9) quality = 14;
965  else if (pattern == 10) quality = 15;
966  else {
967  if (infoV >= 0) edm::LogWarning("L1CSCTPEmulatorWrongValues")
968  << "+++ findQuality: Unexpected CLCT pattern id = "
969  << pattern << "+++\n";
970  }
971  }
972  }
973  }
974  }
975  }
976  return quality;
977 }
978 
979 
981  GEMCoPadDigiCollection& out_co_pads,
982  CSCDetId csc_id)
983 {
984  gemCoPadV.clear();
985 
986  // build coincidences
987  for (auto det_range = out_pads->begin(); det_range != out_pads->end(); ++det_range) {
988  const GEMDetId& id = (*det_range).first;
989 
990  // same chamber
991  if (id.region() != csc_id.zendcap() or
992  id.ring() != csc_id.ring() or id.chamber() != csc_id.chamber()) continue;
993 
994  // build coincidences only for long superchamber pads
995  if (id.station() != 3) continue;
996 
997  // all coincidences detIDs will have layer=1
998  if (id.layer() != 1) continue;
999 
1000  // find the corresponding id with layer=2
1001  GEMDetId co_id(id.region(), id.ring(), id.station(), 2, id.chamber(), id.roll());
1002 
1003  auto co_pads_range = out_pads->get(co_id);
1004  // empty range = no possible coincidence pads
1005  if (co_pads_range.first == co_pads_range.second) continue;
1006 
1007  // now let's correlate the pads in two layers of this partition
1008  const auto& pads_range = (*det_range).second;
1009  for (auto p = pads_range.first; p != pads_range.second; ++p) {
1010  for (auto co_p = co_pads_range.first; co_p != co_pads_range.second; ++co_p) {
1011  // check the match in pad
1012  if (std::abs(p->pad() - co_p->pad()) > maxDeltaPadInCoPad_) continue;
1013  // check the match in BX
1014  if (std::abs(p->bx() - co_p->bx()) > maxDeltaBXInCoPad_ ) continue;
1015 
1016  // make a new coincidence pad digi
1017  gemCoPadV.push_back(GEMCoPadDigi(id.roll(),*p,*co_p));
1018  out_co_pads.insertDigi(id, GEMCoPadDigi(id.roll(),*p,*co_p));
1019  }
1020  }
1021  }
1022 }
1023 
1024 
1025 std::map<int,std::pair<double,double> >
1027 {
1028  std::map<int,std::pair<double,double> > result;
1029 
1030  auto chamber(gem_g->chamber(GEMDetId(1,1,3,1,1,0)));
1031  if (chamber==nullptr) return result;
1032 
1033  for(int i = 1; i<= chamber->nEtaPartitions(); ++i){
1034  auto roll(chamber->etaPartition(i));
1035  if (roll==nullptr) continue;
1036  const float half_striplength(roll->specs()->specificTopology().stripLength()/2.);
1037  const LocalPoint lp_top(0., half_striplength, 0.);
1038  const LocalPoint lp_bottom(0., -half_striplength, 0.);
1039  const GlobalPoint gp_top(roll->toGlobal(lp_top));
1040  const GlobalPoint gp_bottom(roll->toGlobal(lp_bottom));
1041  //result[i] = std::make_pair(floorf(gp_top.eta() * 100) / 100, ceilf(gp_bottom.eta() * 100) / 100);
1042  result[i] = std::make_pair(gp_top.eta(), gp_bottom.eta());
1043  }
1044  return result;
1045 }
1046 
1048 {
1049  auto superChamber(gem_g->superChamber(id));
1050  for (auto ch : superChamber->chambers()) {
1051  for (auto roll : ch->etaPartitions()) {
1052  GEMDetId roll_id(roll->id());
1053  auto pads_in_det = gemPads->get(roll_id);
1054  for (auto pad = pads_in_det.first; pad != pads_in_det.second; ++pad) {
1055  auto id_pad = std::make_pair(roll_id, &(*pad));
1056  const int bx_shifted(lct_central_bx + pad->bx());
1057  for (int bx = bx_shifted - maxDeltaBXPad_;bx <= bx_shifted + maxDeltaBXPad_; ++bx) {
1058  pads_[bx].push_back(id_pad);
1059  }
1060  }
1061  }
1062  }
1063 }
1064 
1066 {
1067  auto superChamber(gem_g->superChamber(id));
1068  for (auto ch : superChamber->chambers()) {
1069  for (auto roll : ch->etaPartitions()) {
1070  GEMDetId roll_id(roll->id());
1071  auto pads_in_det = gemPads->get(roll_id);
1072  for (auto pad = pads_in_det.first; pad != pads_in_det.second; ++pad) {
1073  GEMPadDigi gfirst((*pad).first());
1074  auto id_pad = std::make_pair(roll_id, &gfirst);
1075  const int bx_shifted(lct_central_bx + (pad->first()).bx());
1076  for (int bx = bx_shifted - maxDeltaBXPad_;bx <= bx_shifted + maxDeltaBXPad_; ++bx) {
1077  if(bx != lct_central_bx) continue;
1078  coPads_[bx].push_back(id_pad);
1079  }
1080  }
1081  }
1082  }
1083 }
1084 
1085 void CSCMotherboardME21GEM::printGEMTriggerPads(int bx_start, int bx_stop, bool iscopad)
1086 {
1087  // pads or copads?
1088  auto thePads(!iscopad ? pads_ : coPads_ );
1089  const bool hasPads(thePads.size()!=0);
1090 
1091  std::cout << "------------------------------------------------------------------------" << std::endl;
1092  bool first = true;
1093  for (int bx = bx_start; bx <= bx_stop; bx++) {
1094  // print only the pads for the central BX
1095  //if (bx!=lct_central_bx and iscopad) continue;
1096  std::vector<std::pair<unsigned int, const GEMPadDigi*> > in_pads = thePads[bx];
1097  if (first) {
1098  if (!iscopad) std::cout << "* GEM trigger pads: " << std::endl;
1099  else std::cout << "* GEM trigger coincidence pads: " << std::endl;
1100  }
1101  first = false;
1102  if (!iscopad) std::cout << "N(pads) BX " << bx << " : " << in_pads.size() << std::endl;
1103  else std::cout << "N(copads) BX " << bx << " : " << in_pads.size() << std::endl;
1104  if (hasPads){
1105  for (auto pad : in_pads){
1106  auto roll_id(GEMDetId(pad.first));
1107  std::cout << "\tdetId " << pad.first << " " << roll_id << ", pad = " << pad.second->pad() << ", BX = " << pad.second->bx() + 6 << std::endl;
1108  }
1109  }
1110  else
1111  break;
1112  }
1113 }
1114 
1115 
1117 CSCMotherboardME21GEM::matchingGEMPads(const CSCCLCTDigi& clct, const GEMPadsBX& pads, bool isCoPad, bool first)
1118 {
1120 
1121  // fetch the low and high pad edges for the long superchambers
1122  int deltaPad(isCoPad ? maxDeltaPadCoPad_ : maxDeltaPadPad_);
1123  int deltaBX(isCoPad ? maxDeltaBXCoPad_ : maxDeltaBXPad_);
1124  int clct_bx = clct.getBX();
1125  const int lowPad(cscHsToGemPad_[clct.getKeyStrip()].first);
1126  const int highPad(cscHsToGemPad_[clct.getKeyStrip()].second);
1127  const bool debug(false);
1128  if (debug) std::cout << "lowpad " << lowPad << " highpad " << highPad << " delta pad " << deltaPad <<std::endl;
1129  for (auto p: pads){
1130  if (debug) std::cout<<"DetId"<<GEMDetId(p.first)<<" "<< *(p.second)<<std::endl;
1131  auto padRoll((p.second)->pad());
1132  int pad_bx = (p.second)->bx()+lct_central_bx;
1133  if (debug) std::cout << "padRoll " << padRoll << std::endl;
1134  if (std::abs(clct_bx-pad_bx)>deltaBX) continue;
1135  if (std::abs(lowPad - padRoll) <= deltaPad or std::abs(padRoll - highPad) <= deltaPad){
1136  if (debug) std::cout << "++Matches! " << std::endl;
1137  result.push_back(p);
1138  if (first) return result;
1139  }
1140  }
1141  return result;
1142 }
1143 
1144 
1146 CSCMotherboardME21GEM::matchingGEMPads(const CSCALCTDigi& alct, const GEMPadsBX& pads, bool isCoPad, bool first)
1147 {
1149  int deltaBX(isCoPad ? maxDeltaBXCoPad_ : maxDeltaBXPad_);
1150  int alct_bx = alct.getBX();
1151  int Wg = alct.getKeyWG();
1152  std::vector<int> Rolls;
1153  Rolls.push_back(cscWgToGemRoll_[Wg]);
1154  if (Wg>=maxDeltaWg_ && cscWgToGemRoll_[Wg] != cscWgToGemRoll_[Wg-maxDeltaWg_])
1155  Rolls.push_back(cscWgToGemRoll_[Wg-maxDeltaWg_]);
1156  if ((unsigned int)(Wg+maxDeltaWg_)<cscWgToGemRoll_.size() && cscWgToGemRoll_[Wg] != cscWgToGemRoll_[Wg+maxDeltaWg_])
1157  Rolls.push_back(cscWgToGemRoll_[Wg+maxDeltaWg_]);
1158 
1159  const bool debug(false);
1160  if (debug) std::cout << "ALCT keyWG " << alct.getKeyWG() << std::endl;
1161  for (auto alctRoll : Rolls)
1162  {
1163  if (debug) std::cout <<"roll " << alctRoll << std::endl;
1164  for (auto p: pads){
1165  auto padRoll(GEMDetId(p.first).roll());
1166  int pad_bx = (p.second)->bx()+lct_central_bx;
1167  if (debug) std::cout<<"Detid "<< GEMDetId(p.first) <<" "<< *(p.second)<<std::endl;
1168  if (debug) std::cout << "Candidate ALCT: " << padRoll << std::endl;
1169  if (std::abs(alct_bx-pad_bx)>deltaBX) continue;
1170  if (alctRoll != padRoll) continue;
1171  if (debug) std::cout << "++Matches! " << std::endl;
1172  result.push_back(p);
1173  if (first) return result;
1174  }
1175  }
1176  return result;
1177 }
1178 
1179 
1182  bool isCoPad, bool first)
1183 {
1185 
1186  // Fetch all (!) pads matching to ALCTs and CLCTs
1187  auto padsClct(matchingGEMPads(clct, pads, isCoPad, false));
1188  auto padsAlct(matchingGEMPads(alct, pads, isCoPad, false));
1189 
1190  const bool debug(false);
1191  if (debug) std::cout << "-----------------------------------------------------------------------"<<std::endl;
1192  // Check if the pads overlap
1193  for (auto p : padsAlct){
1194  if (debug) std::cout<< "Candidate ALCT: " << p.first << " " << *(p.second) << std::endl;
1195  for (auto q: padsClct){
1196  if (debug) std::cout<< "++Candidate CLCT: " << q.first << " " << *(q.second) << std::endl;
1197  // look for exactly the same pads
1198  if ((p.first != q.first) or GEMPadDigi(*(p.second)) != *(q.second)) continue;
1199  if (debug) std::cout << "++Matches! " << std::endl;
1200  result.push_back(p);
1201  if (first) return result;
1202  }
1203  }
1204  if (debug) std::cout << "-----------------------------------------------------------------------"<<std::endl;
1205  return result;
1206 }
1207 
1209 {
1210  /*
1211  using namespace std;
1212 
1213  // check if we have any LCTs at all
1214  int nlct = 0;
1215  for (int bx = 0; bx < MAX_LCT_BINS; bx++)
1216  for (unsigned int mbx = 0; mbx < match_trig_window_size; mbx++)
1217  for (int i=0;i<2;i++)
1218  {
1219  CSCCorrelatedLCTDigi& lct = allLCTs[bx][mbx][i];
1220  if (lct.isValid()) nlct++;
1221  }
1222  if (nlct == 0) return;
1223 
1224  // retrieve CSCChamber geometry
1225  CSCTriggerGeomManager* geo_manager = CSCTriggerGeometry::get();
1226  CSCChamber* cscChamber = geo_manager->chamber(theEndcap, theStation, theSector, theSubsector, theTrigChamber);
1227  const CSCDetId csc_id(cscChamber->id());
1228  const int chamber(csc_id.chamber());
1229  const bool is_odd(chamber%2==1);
1230 
1231 
1232  if (debug_gem_dphi) std::cout<<"++++++++ matchGEMPads "<< csc_id <<" +++++++++ "<<std::endl;
1233 
1234  // check if there are any pads
1235  if (pads_.empty()) {
1236  if (debug_gem_dphi) std::cout<<"igotnopads"<<std::endl;
1237  return;
1238  }
1239 
1240  // walk over BXs
1241  for (int bx = 0; bx < MAX_LCT_BINS; ++bx)
1242  {
1243  auto in_pads = pads_.find(bx);
1244 
1245  // walk over potential LCTs in this BX
1246  for (unsigned int mbx = 0; mbx < match_trig_window_size; ++mbx)
1247  for (int i=0; i<2; ++i)
1248  {
1249  CSCCorrelatedLCTDigi& lct = allLCTs[bx][mbx][i];
1250  if (!lct.isValid() or fabs(lct.getGEMDPhi()) < 0.000001) continue;
1251  if (debug_gem_dphi) std::cout<<"LCTbefore "<<bx<<" "<<mbx<<" "<<i<<" "<<lct;
1252 
1253  // use -99 as default value whe we don't know if there could have been a gem match
1254  lct.setGEMDPhi(-99.);
1255 
1256  // "strip" here is actually a half-strip in geometry's terms
1257  // note that LCT::getStrip() starts from 0
1258  float fractional_strip = 0.5 * (lct.getStrip() + 1) - 0.25;
1259  auto layer_geo = cscChamber->layer(CSCConstants::KEY_CLCT_LAYER)->geometry();
1260  // LCT::getKeyWG() also starts from 0
1261  float wire = layer_geo->middleWireOfGroup(lct.getKeyWG() + 1);
1262 
1263  LocalPoint csc_intersect = layer_geo->intersectionOfStripAndWire(fractional_strip, wire);
1264  GlobalPoint csc_gp = csc_g->idToDet(csc_id)->surface().toGlobal(csc_intersect);
1265 
1266  // is LCT located in the high efficiency GEM eta range?
1267  bool gem_fid = ( std::abs(csc_gp.eta()) >= gem_match_min_eta );
1268 
1269  if (debug_gem_dphi) std::cout<<" lct eta "<<csc_gp.eta()<<" phi "<<csc_gp.phi()<<std::endl;
1270 
1271  if (!gem_fid)
1272  {
1273  if (debug_gem_dphi) std::cout<<" -- lct pass no gem req"<<std::endl;
1274  continue;
1275  }
1276  // use 100 ad default value when within gem fiducial region
1277  lct.setGEMDPhi(100.);
1278 
1279  if (in_pads == pads_.end()) // has no potential GEM hits with similar BX -> zap it
1280  {
1281  if (gem_clear_nomatch_lcts) lct.clear();
1282  if (debug_gem_dphi) std::cout<<" -- no gem"<<std::endl;
1283  continue;
1284  }
1285  if (debug_gem_dphi) std::cout<<" -- gem possible"<<std::endl;
1286  // use 99 ad default value when we expect there to be a gem match
1287  lct.setGEMDPhi(99.);
1288 
1289  // to consider a GEM pad as "matched" it has to be
1290  // within specified delta_eta and delta_phi ranges
1291  // and if there are multiple ones, only the min|delta_phi| is considered as matched
1292  bool gem_matched = false;
1293  //int gem_bx = 99;
1294  float min_dphi = 99.;
1295  for (auto& id_pad: in_pads->second)
1296  {
1297  GEMDetId gem_id(id_pad.first);
1298  LocalPoint gem_lp = gem_g->etaPartition(gem_id)->centreOfPad(id_pad.second->pad());
1299  GlobalPoint gem_gp = gem_g->idToDet(gem_id)->surface().toGlobal(gem_lp);
1300  float dphi = deltaPhi(csc_gp.phi(), gem_gp.phi());
1301  float deta = csc_gp.eta() - gem_gp.eta();
1302  if (debug_gem_dphi) std::cout<<" gem with dphi "<< std::abs(dphi) <<" deta "<< std::abs(deta) <<std::endl;
1303 
1304  if( ( std::abs(deta) <= gem_match_delta_eta ) and // within delta_eta
1305  ( ( is_odd and std::abs(dphi) <= gem_match_delta_phi_odd ) or
1306  ( !is_odd and std::abs(dphi) <= gem_match_delta_phi_even ) ) and // within delta_phi
1307  ( std::abs(dphi) < std::abs(min_dphi) ) // minimal delta phi
1308  )
1309  {
1310  gem_matched = true;
1311  min_dphi = dphi;
1312  //gem_bx = id_pad.second->bx();
1313  }
1314  }
1315  if (gem_matched)
1316  {
1317  if (debug_gem_dphi) std::cout<<" GOT MATCHED GEM!"<<std::endl;
1318  lct.setGEMDPhi(min_dphi);
1319  // assing the bit value
1320  int oddEven = int(not is_odd) + 1;
1321  int numberOfBendAngles(sizeof lut_pt_vs_dphi_gemcsc / sizeof *lut_pt_vs_dphi_gemcsc);
1322  int iFound = 0;
1323  if (abs(min_dphi) < lut_pt_vs_dphi_gemcsc[numberOfBendAngles-1][oddEven]) iFound = numberOfBendAngles;
1324  else {
1325  for (int i=0; i< numberOfBendAngles-1; ++i) {
1326  if (debug_gem_dphi) std::cout<<"is_odd "<<is_odd <<" min_dphi "<<abs(min_dphi)<<" bend angle lib "<<i<<" "<<lut_pt_vs_dphi_gemcsc[i][oddEven]<< std::endl;
1327  if (abs(min_dphi) < lut_pt_vs_dphi_gemcsc[i][oddEven] and abs(min_dphi) > lut_pt_vs_dphi_gemcsc[i+1][oddEven])
1328  iFound = i+1;
1329  }
1330  }
1331  lct.setGEMDPhiBits(iFound);
1332  if (debug_gem_dphi) std::cout<<"found bend angle "<<abs(min_dphi)<<" "<<lct.getGEMDPhiBits()<<" "<<lut_pt_vs_dphi_gemcsc[iFound][oddEven]<<" "<<iFound << std::endl;
1333  }
1334  else
1335  {
1336  if (debug_gem_dphi) std::cout<<" no gem match";
1337  if (gem_clear_nomatch_lcts)
1338  {
1339  lct.clear();
1340  if (debug_gem_dphi) std::cout<<" - cleared lct";
1341  }
1342  if (debug_gem_dphi) std::cout<<std::endl;
1343  }
1344  if (debug_gem_dphi) std::cout<<"LCTafter "<<bx<<" "<<mbx<<" "<<i<<" "<<lct;
1345  }
1346  }
1347 
1348  // final count
1349  int nlct_after = 0;
1350  for (int bx = 0; bx < MAX_LCT_BINS; bx++)
1351  for (unsigned int mbx = 0; mbx < match_trig_window_size; mbx++)
1352  for (int i=0;i<2;i++)
1353  {
1354  if (allLCTs[bx][mbx][i].isValid()) nlct_after++;
1355  }
1356  if (debug_gem_dphi) std::cout<<"before "<<nlct<<" after "<<nlct_after<<std::endl;
1357  */
1358 }
1359 
1360 
1362 {
1363  int result = -99;
1364  for(auto p : gemRollToEtaLimits_) {
1365  const float minEta((p.second).first);
1366  const float maxEta((p.second).second);
1367  if (minEta <= eta and eta <= maxEta) {
1368  result = p.first;
1369  break;
1370  }
1371  }
1372  return result;
1373 }
1374 
1375 
1376 std::vector<GEMCoPadDigi> CSCMotherboardME21GEM::readoutCoPads()
1377 {
1378  return gemCoPadV;
1379 }
#define LogDebug(id)
int getQuality() const
return quality of a pattern (number of layers hit!)
Definition: CSCCLCTDigi.h:33
std::vector< GEMCoPadDigi > readoutCoPads()
int chamber() const
Definition: CSCDetId.h:68
const unsigned theSector
T getParameter(std::string const &) const
int i
Definition: DBlmapReader.cc:9
std::vector< CSCCorrelatedLCTDigi > getLCTs()
GEMPadsBX matchingGEMPads(const CSCCLCTDigi &cLCT, const GEMPadsBX &pads=GEMPadsBX(), bool isCopad=false, bool first=true)
unsigned int clct_trig_enable
CSCChamber * chamber(unsigned endcap, unsigned station, unsigned sector, unsigned subsector, unsigned tcscid) const
Return the CSCChamber for a corresponding endcap/station/sector/subsector/trigger cscid...
unsigned int findQualityGEM(const CSCALCTDigi &aLCT, const CSCCLCTDigi &cLCT, bool hasPad, bool hasCoPad)
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle e< void, edm::EventIDconst &, edm::Timestampconst & > We also list in braces which AR_WATCH_USING_METHOD_ is used for those or
Definition: Activities.doc:12
static bool sortByGEMDphi(const CSCCorrelatedLCTDigi &, const CSCCorrelatedLCTDigi &)
unsigned int match_trig_window_size
const unsigned theTrigChamber
bool isValid() const
check ALCT validity (1 - valid ALCT)
Definition: CSCALCTDigi.h:30
std::map< int, std::pair< double, double > > gemRollToEtaLimits_
int roll() const
Definition: GEMDetId.h:80
const unsigned theEndcap
double maxEta
std::vector< CSCCorrelatedLCTDigi > sortLCTsByQuality(int bx)
int getStripType() const
return striptype
Definition: CSCCLCTDigi.h:39
tuple result
Definition: mps_fire.py:84
int deltaPad(int hs, int pad)
int getBend() const
return bend
Definition: CSCCLCTDigi.h:42
double gem_match_delta_phi_odd
GEM matching dphi and deta.
U second(std::pair< T, U > const &p)
const unsigned theStation
void retrieveGEMPads(const GEMPadDigiCollection *pads, unsigned id)
static CSCTriggerGeomManager * get()
static const double lut_wg_eta_odd[112][2]
int pad() const
Definition: GEMPadDigi.h:25
const unsigned theSubsector
int getBX() const
return BX
Definition: CSCCLCTDigi.h:51
unsigned int encodePattern(const int ptn, const int highPt)
bool do_gem_matching
Do GEM matching?
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
std::vector< GEMPadBX > GEMPadsBX
double gem_match_min_eta
min eta of LCT for which we require GEM match (we don&#39;t throw out LCTs below this min eta) ...
bool isValid() const
check CLCT validity (1 - valid CLCT)
Definition: CSCCLCTDigi.h:30
unsigned int match_trig_enable
MuonDigiCollection< GEMDetId, GEMCoPadDigi > GEMCoPadDigiCollection
std::map< int, std::pair< double, double > > createGEMRollEtaLUT()
const GEMSuperChamber * superChamber(GEMDetId id) const
Definition: GEMGeometry.cc:91
int getBX() const
return BX - five low bits of BXN counter tagged by the ALCT
Definition: CSCALCTDigi.h:48
int ring() const
Definition: CSCDetId.h:75
short int zendcap() const
Definition: CSCDetId.h:100
int getQuality() const
return quality of a pattern
Definition: CSCALCTDigi.h:33
#define debug
Definition: HDRShower.cc:19
static const double lut_pt_vs_dphi_gemcsc[8][3]
int getAccelerator() const
Definition: CSCALCTDigi.h:37
void run(const CSCWireDigiCollection *wiredc, const CSCComparatorDigiCollection *compdc, const GEMPadDigiCollection *gemPads)
std::map< int, std::pair< int, int > > cscHsToGemPad_
int bx() const
Definition: GEMPadDigi.h:26
int getPattern() const
return pattern
Definition: CSCCLCTDigi.h:36
const GEMChamber * chamber(GEMDetId id) const
Definition: GEMGeometry.cc:99
std::map< int, int > gemPadToCscHs_
CSCCorrelatedLCTDigi allLCTs[MAX_LCT_BINS][15][2]
int gem_match_delta_bx
delta BX for GEM pads matching
const GEMGeometry * gem_g
unsigned int alct_trig_enable
std::vector< GEMCoPadDigi > gemCoPadV
std::unique_ptr< CSCAnodeLCTProcessor > alct
void buildCoincidencePads(const GEMPadDigiCollection *out_pads, GEMCoPadDigiCollection &out_co_pads, CSCDetId csc_id)
void printGEMTriggerPads(int minBX, int maxBx, bool iscopad=false)
CSCCorrelatedLCTDigi constructLCTsGEM(const CSCALCTDigi &alct, const GEMPadDigi &gem, bool oldDataFormat=false)
std::vector< CSCCorrelatedLCTDigi > sortLCTsByGEMDPhi(int bx)
std::unique_ptr< CSCCathodeLCTProcessor > clct
std::vector< CSCCorrelatedLCTDigi > readoutLCTs()
const std::vector< const GEMStation * > & stations() const
Return a vector of all GEM stations.
Definition: GEMGeometry.cc:47
tuple cout
Definition: gather_cfg.py:145
CSCMotherboardME21GEM(unsigned endcap, unsigned station, unsigned sector, unsigned subsector, unsigned chamber, const edm::ParameterSet &conf)
void retrieveGEMCoPads(const GEMCoPadDigiCollection *pads, unsigned id)
int getKeyStrip() const
Definition: CSCCLCTDigi.h:65
void setTrknmb(const uint16_t number)
Set track number (1,2) after sorting LCTs.
void correlateLCTsGEM(CSCALCTDigi bestALCT, CSCALCTDigi secondALCT, GEMPadDigi gemPad, CSCCorrelatedLCTDigi &lct1, CSCCorrelatedLCTDigi &lct2)
std::map< int, int > cscWgToGemRoll_
int getKeyWG() const
return key wire group
Definition: CSCALCTDigi.h:45
tuple size
Write out results.
bool gem_clear_nomatch_lcts
whether to throw out GEM-fiducial LCTs that have no gem match
static bool sortByQuality(const CSCCorrelatedLCTDigi &, const CSCCorrelatedLCTDigi &)
static const double lut_wg_eta_even[112][2]