CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
CSCGEMMatcher.cc
Go to the documentation of this file.
7 
8 #include <algorithm>
9 #include <cmath>
10 
12  int endcap, unsigned station, unsigned chamber, const edm::ParameterSet& tmbParams, const edm::ParameterSet& conf)
13  : endcap_(endcap), station_(station), chamber_(chamber) {
14  isEven_ = (chamber_ % 2 == 0);
15 
16  maxDeltaBXALCTGEM_ = tmbParams.getParameter<unsigned>("maxDeltaBXALCTGEM");
17  maxDeltaBXCLCTGEM_ = tmbParams.getParameter<unsigned>("maxDeltaBXCLCTGEM");
18 
19  matchWithHS_ = tmbParams.getParameter<bool>("matchWithHS");
20 
21  maxDeltaHsEven_ = tmbParams.getParameter<unsigned>("maxDeltaHsEven");
22  maxDeltaHsOdd_ = tmbParams.getParameter<unsigned>("maxDeltaHsOdd");
23 
24  if (station_ == 1) {
25  maxDeltaHsEvenME1a_ = tmbParams.getParameter<unsigned>("maxDeltaHsEvenME1a");
26  maxDeltaHsOddME1a_ = tmbParams.getParameter<unsigned>("maxDeltaHsOddME1a");
27  }
28 
29  mitigateSlopeByCosi_ = tmbParams.getParameter<bool>("mitigateSlopeByCosi");
30  assign_gem_csc_bending_ = tmbParams.getParameter<bool>("assignGEMCSCBending");
31 }
32 
34 
36 
37 unsigned CSCGEMMatcher::calculateGEMCSCBending(const CSCCLCTDigi& clct, const GEMInternalCluster& cluster) const {
38  // difference in 1/8-strip number
39  const unsigned diff = std::abs(int(clct.getKeyStrip(8)) - int(cluster.getKeyStrip(8)));
40 
41  unsigned slope = 0;
42 
43  // need LUT to convert differences in 1/8-strips between GEM and CSC to slope
44  if (station_ == 2) {
45  if (isEven_) {
46  if (cluster.id().layer() == 1)
48  else
50  } else {
51  if (cluster.id().layer() == 1)
53  else
55  }
56  } else if (station_ == 1) {
57  if (clct.getKeyStrip() > CSCConstants::MAX_HALF_STRIP_ME1B) { //is in ME1a
58  if (isEven_) {
59  if (cluster.id().layer() == 1)
61  else
63  } else {
64  if (cluster.id().layer() == 1)
66  else
68  }
69  } else {
70  if (isEven_) {
71  if (cluster.id().layer() == 1)
73  else
75  } else {
76  if (cluster.id().layer() == 1)
78  else
80  }
81  }
82  }
83 
84  return slope;
85 }
86 
87 // match an ALCT to GEMInternalCluster by bunch-crossing
90  GEMInternalClusters& output) const {
91  if (!alct.isValid() or clusters.empty())
92  return;
93 
94  // select clusters matched in time
95  for (const auto& cl : clusters) {
96  const unsigned diff = std::abs(int(alct.getBX()) - cl.bx());
97  if (diff <= maxDeltaBXALCTGEM_)
98  output.push_back(cl);
99  }
100 }
101 
102 // match a CLCT to GEMInternalCluster by bunch-crossing
105  GEMInternalClusters& output) const {
106  if (!clct.isValid() or clusters.empty())
107  return;
108 
109  // select clusters matched in time
110  for (const auto& cl : clusters) {
111  const unsigned diff = std::abs(int(clct.getBX()) - cl.bx());
112  if (diff <= maxDeltaBXCLCTGEM_)
113  output.push_back(cl);
114  }
115 }
116 
117 // match an ALCT and CLCT to GEMInternalCluster by bunch-crossing
119  const CSCCLCTDigi& clct,
121  GEMInternalClusters& output) const {
122  // both need to be valid
123  if (!alct.isValid() or !clct.isValid() or clusters.empty())
124  return;
125 
126  // get the single matches
127  GEMInternalClusters alctClusters, clctClusters;
128  matchingClustersBX(alct, clusters, alctClusters);
129  matchingClustersBX(clct, clusters, clctClusters);
130 
131  // get the intersection
132  for (const auto& p : alctClusters) {
133  for (const auto& q : clctClusters) {
134  if (p == q) {
135  output.push_back(p);
136  }
137  }
138  }
139 }
140 
143  GEMInternalClusters& output) const {
144  if (!alct.isValid() or clusters.empty())
145  return;
146 
147  // select clusters matched in wiregroup
148  for (const auto& cl : clusters) {
149  // for now add 10 wiregroups to make sure the matching can be done
150  // this should be quite generous
151  unsigned deltaWG(station_ == 1 ? 10 : 20);
152  if (cl.min_wg() <= alct.getKeyWG() and alct.getKeyWG() <= cl.max_wg() + deltaWG) {
153  output.push_back(cl);
154  }
155  }
156 }
157 
160  GEMInternalClusters& output) const {
161  if (!clct.isValid() or clusters.empty())
162  return;
163 
164  // select clusters matched by 1/2-strip or 1/8-strip
165  for (const auto& cl : clusters) {
166  const bool isMatched(matchWithHS_ ? matchedClusterLocHS(clct, cl) : matchedClusterLocES(clct, cl));
167  if (isMatched) {
168  output.push_back(cl);
169  }
170  }
171 }
172 
173 // match by 1/2-strip
174 bool CSCGEMMatcher::matchedClusterLocHS(const CSCCLCTDigi& clct, const GEMInternalCluster& cluster) const {
175  const bool isME1a(station_ == 1 and clct.getKeyStrip() > CSCConstants::MAX_HALF_STRIP_ME1B);
176 
177  unsigned halfStripDiff = std::abs(int(clct.getKeyStrip(2)) - int(cluster.getKeyStrip(2)));
178  if (isME1a) {
179  halfStripDiff = std::abs(int(clct.getKeyStrip(2)) - int(cluster.getKeyStripME1a(2)));
180  }
181 
182  // 98% acceptance cuts
183  unsigned halfStripCut;
184  if (isEven_) {
185  if (isME1a)
186  halfStripCut = maxDeltaHsEvenME1a_;
187  else
188  halfStripCut = maxDeltaHsEven_;
189  } else {
190  if (isME1a)
191  halfStripCut = maxDeltaHsOddME1a_;
192  else
193  halfStripCut = maxDeltaHsOdd_;
194  }
195  // 10 degree chamber is ~0.18 radian wide
196  // 98% acceptance for clusters in odd/even chambers for muons with 5 GeV
197  // {5, 0.02123785, 0.00928431}
198  // This corresponds to 0.12 and 0.052 fractions of the chamber
199  // or 16 and 7 half-strips
200 
201  // 20 degree chamber is ~0.35 radian wide
202  // 98% acceptance for clusters in odd/even chambers for muons with 5 GeV
203  // {5, 0.01095490, 0.00631625},
204  // This corresponds to 0.031 and 0.018 fractions of the chamber
205  // or 5 and 3 half-strips
206 
207  return halfStripDiff <= halfStripCut;
208 }
209 
210 // match by 1/8-strip
212  // key 1/8-strip
213  int key_es = -1;
214 
215  //modification of DeltaStrip by CLCT slope
216  int SlopeShift = 0;
217  uint16_t baseSlope = 0;
219  baseSlope = mitigatedSlopeByConsistency(clct);
220  else
221  baseSlope = clct.getSlope();
222  int clctSlope = pow(-1, clct.getBend()) * baseSlope;
223 
224  // for coincidences or single clusters in L1
225  if (cl.isCoincidence() or cl.id().layer() == 1) {
226  key_es = cl.layer1_middle_es();
228  key_es = cl.layer1_middle_es_me1a();
229 
230  //set SlopeShift for L1 or Copad case
231  SlopeShift =
232  CSCGEMSlopeCorrector(true, clctSlope); // fixed to facing detectors, must be determined at motherboard level
233  }
234 
235  // for single clusters in L2
236  else if (cl.id().layer() == 2) {
237  key_es = cl.layer2_middle_es();
239  key_es = cl.layer2_middle_es_me1a();
240 
241  //set SlopeShift for L2 case
242  SlopeShift =
243  CSCGEMSlopeCorrector(false, clctSlope); // fixed to facing detectors, must be determined at motherboard level
244 
245  }
246 
247  else
248  edm::LogWarning("CSCGEMMatcher") << "cluster.id().layer =" << cl.id().layer() << " out of acceptable range 1-2!";
249 
250  // matching by 1/8-strip
251  // determine matching window by chamber, assuming facing chambers only are processed
252  int window = chamber_ % 2 == 0 ? 20 : 40;
253 
254  return std::abs(clct.getKeyStrip(8) - key_es + SlopeShift) < window;
255 }
256 
258  const CSCCLCTDigi& clct,
260  GEMInternalClusters& output) const {
261  // both need to be valid
262  if (!alct.isValid() or !clct.isValid() or clusters.empty())
263  return;
264 
265  // get the single matches
266  GEMInternalClusters alctClusters, clctClusters;
267  matchingClustersLoc(alct, clusters, alctClusters);
268  matchingClustersLoc(clct, clusters, clctClusters);
269 
270  // get the intersection
271  for (const auto& p : alctClusters) {
272  for (const auto& q : clctClusters) {
273  if (p == q) {
274  output.push_back(p);
275  }
276  }
277  }
278 }
279 
282  GEMInternalClusters& output) const {
283  if (!alct.isValid() or clusters.empty())
284  return;
285 
286  // match by BX
287  GEMInternalClusters clustersBX;
288  matchingClustersBX(alct, clusters, clustersBX);
289 
290  // match spatially
291  matchingClustersLoc(alct, clustersBX, output);
292 }
293 
296  GEMInternalClusters& output) const {
297  if (!clct.isValid() or clusters.empty())
298  return;
299 
300  // match by BX
301  GEMInternalClusters clustersBX;
302  matchingClustersBX(clct, clusters, clustersBX);
303 
304  // match spatially
305  matchingClustersLoc(clct, clustersBX, output);
306 }
307 
309  const CSCCLCTDigi& clct,
311  GEMInternalClusters& selected) const {
312  // both need to be valid
313  if (!alct.isValid() or !clct.isValid() or clusters.empty())
314  return;
315 
316  // match by BX
317  GEMInternalClusters clustersBX;
318  matchingClustersBX(alct, clct, clusters, clustersBX);
319 
320  // match spatially
321  matchingClustersLoc(alct, clct, clustersBX, selected);
322 }
323 
326  GEMInternalCluster& best) const {
327  if (!alct.isValid() or clusters.empty())
328  return;
329 
330  GEMInternalClusters clustersBXLoc;
331  matchingClustersBXLoc(alct, clusters, clustersBXLoc);
332 
333  // simply pick the first matching one
334  if (!clustersBXLoc.empty())
335  best = clustersBXLoc[0];
336 }
337 
340  GEMInternalCluster& best) const {
341  if (!clct.isValid() or clusters.empty())
342  return;
343 
344  // match by BX
345  GEMInternalClusters clustersBXLoc;
346  matchingClustersBXLoc(clct, clusters, clustersBXLoc);
347 
348  // FIXME - for now: pick the first matching one
349  if (!clustersBXLoc.empty())
350  best = clustersBXLoc[0];
351 }
352 
354  const CSCCLCTDigi& clct,
356  GEMInternalCluster& best) const {
357  // match by BX
358  GEMInternalClusters clustersBXLoc;
359  matchingClustersBXLoc(alct, clct, clusters, clustersBXLoc);
360 
361  // FIXME - for now: pick the first matching one
362  if (!clustersBXLoc.empty())
363  best = clustersBXLoc[0];
364 }
365 
367  //extract hit values from CLCT hit matrix
368  std::vector<std::vector<uint16_t>> CLCTHitMatrix = clct.getHits();
369  int CLCTHits[6] = {-1, -1, -1, -1, -1, -1};
370 
371  for (unsigned layer = 0; layer < CLCTHitMatrix.size(); ++layer) {
372  for (unsigned position = 0; position < CLCTHitMatrix.at(layer).size(); ++position) {
373  const uint16_t value = CLCTHitMatrix.at(layer).at(position);
374  if (value != 0 && value != 65535) {
375  CLCTHits[layer] = (int)value;
376  break;
377  }
378  }
379  }
380 
381  //calculate slope consistency
382  float MinMaxPairDifferences[2] = {999., -999.};
383  for (unsigned First = 0; First < 5; ++First) {
384  //skip empty layers
385  if (CLCTHits[First] == -1)
386  continue;
387  for (unsigned Second = First + 1; Second < 6; ++Second) {
388  //skip empty layers
389  if (CLCTHits[Second] == -1)
390  continue;
391  float PairDifference = (CLCTHits[First] - CLCTHits[Second]) / (float)(Second - First);
392  if (PairDifference < MinMaxPairDifferences[0])
393  MinMaxPairDifferences[0] = PairDifference;
394  if (PairDifference > MinMaxPairDifferences[1])
395  MinMaxPairDifferences[1] = PairDifference;
396  }
397  }
398 
399  //calculate consistency of slope indicator: cosi
400  uint16_t cosi = std::ceil(std::abs(MinMaxPairDifferences[1] - MinMaxPairDifferences[0]));
401 
402  //disambiguate cosi cases
403 
404  //extremely inconsistent track, deprecate slope
405  if (cosi > 3)
406  return 0;
407  //consistent slope, do not change
408  else if (cosi < 2)
409  return clct.getSlope();
410  //need to look up in table 2->1
411  else if (cosi == 2) {
412  if (chamber_ % 2 == 0)
414  else
416  }
417  //need to look up in table 3->1
418  else if (cosi == 3) {
419  if (chamber_ % 2 == 0)
421  else
423  }
424  //just to avoid compiler errors an error code
425  else {
426  return 999;
427  }
428 }
429 
430 int CSCGEMMatcher::CSCGEMSlopeCorrector(bool isL1orCoincidence, int cscSlope) const {
431  int SlopeShift = 0;
432  int SlopeSign = cscSlope / std::abs(cscSlope);
433  //account for slope mitigation by cosi, if opted-in
434  if (mitigateSlopeByCosi_) {
435  //determine cosi-based slope correction
436  if (chamber_ % 2 == 0) {
437  if (isL1orCoincidence)
439  else
441  } else {
442  if (isL1orCoincidence)
444  else
446  }
447  } else {
448  //determine shift by slope correction
449  if (chamber_ % 2 == 0) {
450  if (isL1orCoincidence)
452  else
454  } else {
455  if (isL1orCoincidence)
457  else
459  }
460  }
461  return std::round(SlopeShift * SlopeSign * endcap_);
462 }
unsigned maxDeltaHsOdd_
constexpr int32_t ceil(float num)
void matchingClustersBXLoc(const CSCALCTDigi &alct, const GEMInternalClusters &clusters, GEMInternalClusters &selected) const
uint16_t getKeyStrip(int n=2) const
def window
Definition: svgfig.py:643
uint16_t getKeyStripME1a(int n=2) const
unsigned CSC_slope_corr_L2_ME11_odd(unsigned channel) const
unsigned maxDeltaBXALCTGEM_
bool mitigateSlopeByCosi_
unsigned CSC_slope_cosi_corr_L2_ME11_even(unsigned channel) const
unsigned station_
unsigned CSC_slope_corr_L2_ME11_even(unsigned channel) const
uint16_t getBX() const
return BX
Definition: CSCCLCTDigi.h:123
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
unsigned maxDeltaHsEvenME1a_
uint16_t getBend() const
Definition: CSCCLCTDigi.h:93
unsigned es_diff_slope_L2_ME1a_odd(unsigned es_diff) const
bool isValid() const
check ALCT validity (1 - valid ALCT)
Definition: CSCALCTDigi.h:40
static const double slope[3]
GEMDetId id() const
int layer1_middle_es_me1a() const
uint16_t getBX() const
return BX - five low bits of BXN counter tagged by the ALCT
Definition: CSCALCTDigi.h:73
bool assign_gem_csc_bending_
unsigned maxDeltaHsEven_
unsigned CSC_slope_corr_L1_ME11_odd(unsigned channel) const
unsigned calculateGEMCSCBending(const CSCCLCTDigi &clct, const GEMInternalCluster &cluster) const
int layer1_middle_es() const
bool matchedClusterLocES(const CSCCLCTDigi &clct, const GEMInternalCluster &cluster) const
void setESLookupTables(const CSCL1TPLookupTableME11ILT *conf)
void bestClusterBXLoc(const CSCALCTDigi &alct, const GEMInternalClusters &clusters, GEMInternalCluster &best) const
unsigned es_diff_slope_L1_ME1b_even(unsigned es_diff) const
tuple cl
Definition: haddnano.py:49
constexpr std::array< uint8_t, layerIndexSize > layer
unsigned es_diff_slope_L2_ME21_odd(unsigned es_diff) const
CSCGEMMatcher(int endcap, unsigned station, unsigned chamber, const edm::ParameterSet &tmbParams, const edm::ParameterSet &luts)
unsigned es_diff_slope_L1_ME21_even(unsigned es_diff) const
uint16_t getKeyStrip(const uint16_t n=2) const
Definition: CSCCLCTDigi.cc:107
unsigned maxDeltaBXCLCTGEM_
unsigned CSC_slope_corr_L1_ME11_even(unsigned channel) const
unsigned chamber_
unsigned es_diff_slope_L1_ME1a_odd(unsigned es_diff) const
unsigned es_diff_slope_L1_ME1b_odd(unsigned es_diff) const
int CSCGEMSlopeCorrector(const bool isL1orCopad, const int cscSlope) const
void matchingClustersBX(const CSCALCTDigi &alct, const GEMInternalClusters &clusters, GEMInternalClusters &selected) const
uint16_t mitigatedSlopeByConsistency(const CSCCLCTDigi &clct) const
const CSCL1TPLookupTableME11ILT * lookupTableME11ILT_
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
unsigned es_diff_slope_L2_ME1b_even(unsigned es_diff) const
unsigned CSC_slope_cosi_2to1_L1_ME11_odd(unsigned channel) const
bool isValid() const
check CLCT validity (1 - valid CLCT)
Definition: CSCCLCTDigi.h:50
unsigned es_diff_slope_L2_ME1b_odd(unsigned es_diff) const
bool isMatched(TrackingRecHit const &hit)
bool matchedClusterLocHS(const CSCCLCTDigi &clct, const GEMInternalCluster &cluster) const
unsigned CSC_slope_cosi_corr_L1_ME11_odd(unsigned channel) const
unsigned CSC_slope_cosi_2to1_L1_ME11_even(unsigned channel) const
unsigned CSC_slope_cosi_3to1_L1_ME11_odd(unsigned channel) const
int layer2_middle_es() const
unsigned es_diff_slope_L1_ME1a_even(unsigned es_diff) const
int layer2_middle_es_me1a() const
uint16_t getKeyWG() const
return key wire group
Definition: CSCALCTDigi.h:67
constexpr int layer() const
Definition: GEMDetId.h:190
T getParameter(std::string const &) const
Definition: ParameterSet.h:303
const ComparatorContainer & getHits() const
Definition: CSCCLCTDigi.h:176
unsigned endcap_
uint16_t getSlope() const
return the slope
Definition: CSCCLCTDigi.h:74
void matchingClustersLoc(const CSCALCTDigi &alct, const GEMInternalClusters &clusters, GEMInternalClusters &selected) const
unsigned CSC_slope_cosi_corr_L2_ME11_odd(unsigned channel) const
static int position[264][3]
Definition: ReadPGInfo.cc:289
std::vector< GEMInternalCluster > GEMInternalClusters
Definition: CSCGEMMatcher.h:26
unsigned es_diff_slope_L2_ME21_even(unsigned es_diff) const
const CSCL1TPLookupTableME21ILT * lookupTableME21ILT_
unsigned CSC_slope_cosi_corr_L1_ME11_even(unsigned channel) const
Log< level::Warning, false > LogWarning
bool isCoincidence() const
unsigned maxDeltaHsOddME1a_
unsigned es_diff_slope_L1_ME21_odd(unsigned es_diff) const
unsigned CSC_slope_cosi_3to1_L1_ME11_even(unsigned channel) const
Power< A, B >::type pow(const A &a, const B &b)
Definition: Power.h:29
unsigned es_diff_slope_L2_ME1a_even(unsigned es_diff) const