CMS 3D CMS Logo

GEMClusterProcessor.cc
Go to the documentation of this file.
3 
4 #include <algorithm>
5 #include <iostream>
6 
8  : region_(region), station_(station), chamber_(chamber), hasGE21Geometry16Partitions_(false) {
9  isEven_ = chamber_ % 2 == 0;
10 
11  const edm::ParameterSet aux(conf.getParameter<edm::ParameterSet>("commonParam"));
12 
13  if (station_ == 1) {
14  const edm::ParameterSet tmb(conf.getParameter<edm::ParameterSet>("tmbPhase2"));
15  const edm::ParameterSet tmb_gem(conf.getParameter<edm::ParameterSet>("tmbPhase2GE11"));
16  const edm::ParameterSet copad(conf.getParameter<edm::ParameterSet>("copadParamGE11"));
17  tmbL1aWindowSize_ = tmb.getParameter<unsigned int>("tmbL1aWindowSize");
18  delayGEMinOTMB_ = tmb_gem.getParameter<unsigned int>("delayGEMinOTMB");
19  maxDeltaPad_ = copad.getParameter<unsigned int>("maxDeltaPad");
20  maxDeltaRoll_ = copad.getParameter<unsigned int>("maxDeltaRoll");
21  maxDeltaBX_ = copad.getParameter<unsigned int>("maxDeltaBX");
22  }
23 
24  if (station_ == 2) {
25  // by default set to true
27 
28  const edm::ParameterSet tmb(conf.getParameter<edm::ParameterSet>("tmbPhase2"));
29  const edm::ParameterSet tmb_gem(conf.getParameter<edm::ParameterSet>("tmbPhase2GE21"));
30  const edm::ParameterSet copad(conf.getParameter<edm::ParameterSet>("copadParamGE21"));
31  tmbL1aWindowSize_ = tmb.getParameter<unsigned int>("tmbL1aWindowSize");
32  delayGEMinOTMB_ = tmb_gem.getParameter<unsigned int>("delayGEMinOTMB");
33  maxDeltaPad_ = copad.getParameter<unsigned int>("maxDeltaPad");
34  maxDeltaRoll_ = copad.getParameter<unsigned int>("maxDeltaRoll");
35  maxDeltaBX_ = copad.getParameter<unsigned int>("maxDeltaBX");
36  }
37 }
38 
40 
42  const CSCL1TPLookupTableME11ILT* lookupTableME11ILT,
43  const CSCL1TPLookupTableME21ILT* lookupTableME21ILT) {
44  // Step 1: clear the GEMInternalCluster vector
45  clear();
46 
47  if (in_clusters == nullptr) {
48  edm::LogWarning("GEMClusterProcessor") << "Attempt to run without valid in_clusters pointer.";
49  return;
50  }
51 
52  // Step 2: put coincidence clusters in GEMInternalCluster vector
53  addCoincidenceClusters(in_clusters);
54 
55  // Step 3: put single clusters in GEMInternalCluster vector who are not part of any coincidence cluster
56  addSingleClusters(in_clusters);
57 
58  // Step 4: translate the cluster central pad numbers into 1/8-strip number for matching with CSC trigger primitives
59  doCoordinateConversion(lookupTableME11ILT, lookupTableME21ILT);
60 }
61 
62 std::vector<GEMInternalCluster> GEMClusterProcessor::getClusters(int bx, ClusterTypes option) const {
63  std::vector<GEMInternalCluster> output;
64 
65  for (const auto& cl : clusters_) {
66  // valid single clusters with the right BX
67  if (cl.bx() == bx and cl.isValid()) {
68  // ignore the coincidence clusters
69  if (option == SingleClusters and cl.isCoincidence())
70  continue;
71  // ignore the single clusters
72  if (option == CoincidenceClusters and !cl.isCoincidence())
73  continue;
74  output.push_back(cl);
75  }
76  }
77  return output;
78 }
79 
81  // Build coincidences
82  for (auto det_range = in_clusters->begin(); det_range != in_clusters->end(); ++det_range) {
83  const GEMDetId& id = (*det_range).first;
84 
85  // coincidence pads are not built for ME0
86  if (id.isME0())
87  continue;
88 
89  // same chamber (no restriction on the roll number)
90  if (id.region() != region_ or id.station() != station_ or id.chamber() != chamber_)
91  continue;
92 
93  // all coincidences detIDs will have layer=1
94  if (id.layer() != 1)
95  continue;
96 
97  // find all corresponding ids with layer 2 and same roll that differs at most maxDeltaRoll_
98  for (unsigned int roll = id.roll() - maxDeltaRoll_; roll <= id.roll() + maxDeltaRoll_; ++roll) {
99  GEMDetId co_id(id.region(), id.ring(), id.station(), 2, id.chamber(), roll);
100 
101  auto co_clusters_range = in_clusters->get(co_id);
102 
103  // empty range = no possible coincidence pads
104  if (co_clusters_range.first == co_clusters_range.second)
105  continue;
106 
107  // now let's correlate the pads in two layers of this partition
108  const auto& pads_range = (*det_range).second;
109  for (auto p = pads_range.first; p != pads_range.second; ++p) {
110  // ignore 8-partition GE2/1 pads
111  if (id.isGE21() and p->nPartitions() == GEMPadDigiCluster::GE21) {
113  continue;
114  }
115 
116  // only consider valid pads
117  if (!p->isValid())
118  continue;
119 
120  for (auto co_p = co_clusters_range.first; co_p != co_clusters_range.second; ++co_p) {
121  // only consider valid clusters
122  if (!co_p->isValid())
123  continue;
124 
125  // check the match in BX
126  if ((unsigned)std::abs(p->bx() - co_p->bx()) > maxDeltaBX_)
127  continue;
128 
129  // get the corrected minimum and maximum of cluster 1
130  int cl1_min = p->pads().front() - maxDeltaPad_;
131  int cl1_max = p->pads().back() + maxDeltaPad_;
132 
133  // get the minimum and maximum of cluster 2
134  int cl2_min = co_p->pads().front();
135  int cl2_max = co_p->pads().back();
136 
137  // match condition
138  const bool condition1(cl1_min <= cl2_min and cl1_max >= cl2_min);
139  const bool condition2(cl1_min <= cl2_max and cl1_max >= cl2_max);
140  const bool match(condition1 or condition2);
141 
142  if (!match)
143  continue;
144 
145  // make a new coincidence
146  clusters_.emplace_back(id, co_id, *p, *co_p, delayGEMinOTMB_, tmbL1aWindowSize_);
147  // std::cout << clusters_.back() << std::endl;
148  }
149  }
150  }
151  }
152 }
153 
155  // first get the coincidences
156  const std::vector<GEMInternalCluster>& coincidences = clusters_;
157 
158  // now start add single clusters
159  for (auto det_range = in_clusters->begin(); det_range != in_clusters->end(); ++det_range) {
160  const GEMDetId& id = (*det_range).first;
161 
162  // ignore ME0
163  if (id.isME0())
164  continue;
165 
166  // same chamber (no restriction on the roll number)
167  if (id.region() != region_ or id.station() != station_ or id.chamber() != chamber_)
168  continue;
169 
170  const auto& clusters_range = (*det_range).second;
171  for (auto p = clusters_range.first; p != clusters_range.second; ++p) {
172  // only consider valid clusters
173  if (!p->isValid())
174  continue;
175 
176  // ignore 8-partition GE2/1 pads
177  if (id.isGE21() and p->nPartitions() == GEMPadDigiCluster::GE21) {
179  continue;
180  }
181 
182  // ignore clusters already contained in a coincidence cluster
183  if (std::find_if(std::begin(coincidences), std::end(coincidences), [p](const GEMInternalCluster& q) {
184  return q.has_cluster(*p);
185  }) != std::end(coincidences))
186  continue;
187 
188  // put the single clusters into the collection
189  if (id.layer() == 1) {
190  clusters_.emplace_back(id, id, *p, GEMPadDigiCluster(), delayGEMinOTMB_, tmbL1aWindowSize_);
191  // std::cout << clusters_.back() << std::endl;
192  } else {
193  clusters_.emplace_back(id, id, GEMPadDigiCluster(), *p, delayGEMinOTMB_, tmbL1aWindowSize_);
194  // std::cout << clusters_.back() << std::endl;
195  }
196  }
197  }
198 }
199 
201  const CSCL1TPLookupTableME21ILT* lookupTableME21ILT) {
202  // loop on clusters
203  for (auto& cluster : clusters_) {
204  if (cluster.cl1().isValid()) {
205  // starting coordinates
206  const int layer1_first_pad = cluster.layer1_pad();
207  const int layer1_last_pad = layer1_first_pad + cluster.layer1_size() - 1;
208 
209  // calculate the 1/8-strips
210  int layer1_pad_to_first_es = -1;
211  int layer1_pad_to_last_es = -1;
212 
213  int layer1_pad_to_first_es_me1a = -1;
214  int layer1_pad_to_last_es_me1a = -1;
215 
216  // ME1/1
217  if (station_ == 1) {
218  if (isEven_) {
219  // ME1/b
220  layer1_pad_to_first_es = lookupTableME11ILT->GEM_pad_CSC_es_ME11b_even(layer1_first_pad);
221  layer1_pad_to_last_es = lookupTableME11ILT->GEM_pad_CSC_es_ME11b_even(layer1_last_pad);
222  // ME1/a
223  layer1_pad_to_first_es_me1a = lookupTableME11ILT->GEM_pad_CSC_es_ME11a_even(layer1_first_pad);
224  layer1_pad_to_last_es_me1a = lookupTableME11ILT->GEM_pad_CSC_es_ME11a_even(layer1_last_pad);
225  } else {
226  // ME1/b
227  layer1_pad_to_first_es = lookupTableME11ILT->GEM_pad_CSC_es_ME11b_odd(layer1_first_pad);
228  layer1_pad_to_last_es = lookupTableME11ILT->GEM_pad_CSC_es_ME11b_odd(layer1_last_pad);
229  // ME1/a
230  layer1_pad_to_first_es_me1a = lookupTableME11ILT->GEM_pad_CSC_es_ME11a_odd(layer1_first_pad);
231  layer1_pad_to_last_es_me1a = lookupTableME11ILT->GEM_pad_CSC_es_ME11a_odd(layer1_last_pad);
232  }
233  }
234  // ME2/1
235  if (station_ == 2) {
236  if (isEven_) {
237  layer1_pad_to_first_es = lookupTableME21ILT->GEM_pad_CSC_es_ME21_even(layer1_first_pad);
238  layer1_pad_to_last_es = lookupTableME21ILT->GEM_pad_CSC_es_ME21_even(layer1_last_pad);
239  } else {
240  layer1_pad_to_first_es = lookupTableME21ILT->GEM_pad_CSC_es_ME21_odd(layer1_first_pad);
241  layer1_pad_to_last_es = lookupTableME21ILT->GEM_pad_CSC_es_ME21_odd(layer1_last_pad);
242  }
243  }
244  // middle 1/8-strip
245  int layer1_middle_es = (layer1_pad_to_first_es + layer1_pad_to_last_es) / 2.;
246  int layer1_middle_es_me1a = (layer1_pad_to_first_es_me1a + layer1_pad_to_last_es_me1a) / 2.;
247 
248  cluster.set_layer1_first_es(layer1_pad_to_first_es);
249  cluster.set_layer1_last_es(layer1_pad_to_last_es);
250  cluster.set_layer1_middle_es(layer1_middle_es);
251 
252  if (station_ == 1) {
253  cluster.set_layer1_first_es_me1a(layer1_pad_to_first_es_me1a);
254  cluster.set_layer1_last_es_me1a(layer1_pad_to_last_es_me1a);
255  cluster.set_layer1_middle_es_me1a(layer1_middle_es_me1a);
256  }
257 
258  // calculate the wiregroups
259  // need to subtract 1 to use the LUTs
260  const int roll = cluster.roll1() - 1;
261 
262  int roll_l1_to_min_wg = -1;
263  int roll_l1_to_max_wg = -1;
264 
265  // ME1/1
266  if (station_ == 1) {
267  if (isEven_) {
268  roll_l1_to_min_wg = lookupTableME11ILT->GEM_roll_CSC_min_wg_ME11_even(roll);
269  roll_l1_to_max_wg = lookupTableME11ILT->GEM_roll_CSC_max_wg_ME11_even(roll);
270  } else {
271  roll_l1_to_min_wg = lookupTableME11ILT->GEM_roll_CSC_min_wg_ME11_odd(roll);
272  roll_l1_to_max_wg = lookupTableME11ILT->GEM_roll_CSC_max_wg_ME11_odd(roll);
273  }
274  }
275 
276  // ME2/1
277  if (station_ == 2) {
278  if (isEven_) {
279  roll_l1_to_min_wg = lookupTableME21ILT->GEM_roll_L1_CSC_min_wg_ME21_even(roll);
280  roll_l1_to_max_wg = lookupTableME21ILT->GEM_roll_L1_CSC_max_wg_ME21_even(roll);
281  } else {
282  roll_l1_to_min_wg = lookupTableME21ILT->GEM_roll_L1_CSC_min_wg_ME21_odd(roll);
283  roll_l1_to_max_wg = lookupTableME21ILT->GEM_roll_L1_CSC_max_wg_ME21_odd(roll);
284  }
285  }
286 
287  // set the values
288  cluster.set_layer1_min_wg(roll_l1_to_min_wg);
289  cluster.set_layer1_max_wg(roll_l1_to_max_wg);
290  }
291 
292  if (cluster.cl2().isValid()) {
293  // starting coordinates
294  const int layer2_first_pad = cluster.layer2_pad();
295  const int layer2_last_pad = layer2_first_pad + cluster.layer2_size() - 1;
296 
297  // calculate the 1/8-strips
298  int layer2_pad_to_first_es = -1;
299  int layer2_pad_to_last_es = -1;
300 
301  int layer2_pad_to_first_es_me1a = -1;
302  int layer2_pad_to_last_es_me1a = -1;
303 
304  if (station_ == 1) {
305  if (isEven_) {
306  // ME1/b
307  layer2_pad_to_first_es = lookupTableME11ILT->GEM_pad_CSC_es_ME11b_even(layer2_first_pad);
308  layer2_pad_to_last_es = lookupTableME11ILT->GEM_pad_CSC_es_ME11b_even(layer2_last_pad);
309  // ME1/a
310  layer2_pad_to_first_es_me1a = lookupTableME11ILT->GEM_pad_CSC_es_ME11a_even(layer2_first_pad);
311  layer2_pad_to_last_es_me1a = lookupTableME11ILT->GEM_pad_CSC_es_ME11a_even(layer2_last_pad);
312  } else {
313  // ME1/b
314  layer2_pad_to_first_es = lookupTableME11ILT->GEM_pad_CSC_es_ME11b_odd(layer2_first_pad);
315  layer2_pad_to_last_es = lookupTableME11ILT->GEM_pad_CSC_es_ME11b_odd(layer2_last_pad);
316  // ME1/a
317  layer2_pad_to_first_es_me1a = lookupTableME11ILT->GEM_pad_CSC_es_ME11a_odd(layer2_first_pad);
318  layer2_pad_to_last_es_me1a = lookupTableME11ILT->GEM_pad_CSC_es_ME11a_odd(layer2_last_pad);
319  }
320  }
321 
322  // ME2/1
323  if (station_ == 2) {
324  if (isEven_) {
325  layer2_pad_to_first_es = lookupTableME21ILT->GEM_pad_CSC_es_ME21_even(layer2_first_pad);
326  layer2_pad_to_last_es = lookupTableME21ILT->GEM_pad_CSC_es_ME21_even(layer2_last_pad);
327  } else {
328  layer2_pad_to_first_es = lookupTableME21ILT->GEM_pad_CSC_es_ME21_odd(layer2_first_pad);
329  layer2_pad_to_last_es = lookupTableME21ILT->GEM_pad_CSC_es_ME21_odd(layer2_last_pad);
330  }
331  }
332  // middle 1/8-strip
333  int layer2_middle_es = int((layer2_pad_to_first_es + layer2_pad_to_last_es) / 2.0);
334  int layer2_middle_es_me1a = int((layer2_pad_to_first_es_me1a + layer2_pad_to_last_es_me1a) / 2.0);
335 
336  cluster.set_layer2_first_es(layer2_pad_to_first_es);
337  cluster.set_layer2_last_es(layer2_pad_to_last_es);
338  cluster.set_layer2_middle_es(layer2_middle_es);
339 
340  if (station_ == 1) {
341  cluster.set_layer2_first_es_me1a(layer2_pad_to_first_es_me1a);
342  cluster.set_layer2_last_es_me1a(layer2_pad_to_last_es_me1a);
343  cluster.set_layer2_middle_es_me1a(layer2_middle_es_me1a);
344  }
345  }
346 
347  // calculate the wiregroups
348  // need to subtract 1 to use the LUTs
349  const int roll = cluster.roll2() - 1;
350 
351  int roll_l2_to_min_wg = -1;
352  int roll_l2_to_max_wg = -1;
353 
354  // ME1/1
355  if (station_ == 1) {
356  if (isEven_) {
357  roll_l2_to_min_wg = lookupTableME11ILT->GEM_roll_CSC_min_wg_ME11_even(roll);
358  roll_l2_to_max_wg = lookupTableME11ILT->GEM_roll_CSC_max_wg_ME11_even(roll);
359  } else {
360  roll_l2_to_min_wg = lookupTableME11ILT->GEM_roll_CSC_min_wg_ME11_odd(roll);
361  roll_l2_to_max_wg = lookupTableME11ILT->GEM_roll_CSC_max_wg_ME11_odd(roll);
362  }
363  }
364 
365  // ME2/1
366  if (station_ == 2) {
367  if (isEven_) {
368  roll_l2_to_min_wg = lookupTableME21ILT->GEM_roll_L2_CSC_min_wg_ME21_even(roll);
369  roll_l2_to_max_wg = lookupTableME21ILT->GEM_roll_L2_CSC_max_wg_ME21_even(roll);
370  } else {
371  roll_l2_to_min_wg = lookupTableME21ILT->GEM_roll_L2_CSC_min_wg_ME21_odd(roll);
372  roll_l2_to_max_wg = lookupTableME21ILT->GEM_roll_L2_CSC_max_wg_ME21_odd(roll);
373  }
374  }
375 
376  // set the values
377  cluster.set_layer2_min_wg(roll_l2_to_min_wg);
378  cluster.set_layer2_max_wg(roll_l2_to_max_wg);
379  }
380 }
381 
382 std::vector<GEMCoPadDigi> GEMClusterProcessor::readoutCoPads() const {
383  std::vector<GEMCoPadDigi> output;
384 
385  // loop on clusters
386  for (const auto& cluster : clusters_) {
387  // ignore single clusters
388  if (!cluster.isCoincidence())
389  continue;
390 
391  // construct coincidence pads out of the centers of the coincidence clusters
392  output.emplace_back(cluster.roll2(), cluster.mid1(), cluster.mid2());
393  }
394 
395  return output;
396 }
T getParameter(std::string const &) const
Definition: ParameterSet.h:307
std::vector< GEMInternalCluster > clusters_
unsigned GEM_roll_L1_CSC_min_wg_ME21_even(unsigned roll) const
bool isME0(GeomDetEnumerators::SubDetector m)
unsigned GEM_roll_CSC_min_wg_ME11_odd(unsigned roll) const
unsigned GEM_pad_CSC_es_ME11b_odd(unsigned pad) const
std::vector< GEMInternalCluster > getClusters(int bx, ClusterTypes option=AllClusters) const
unsigned GEM_pad_CSC_es_ME21_even(unsigned pad) const
unsigned GEM_pad_CSC_es_ME11a_even(unsigned pad) const
unsigned GEM_roll_L1_CSC_max_wg_ME21_odd(unsigned roll) const
unsigned GEM_pad_CSC_es_ME11b_even(unsigned pad) const
unsigned int tmbL1aWindowSize_
unsigned GEM_pad_CSC_es_ME21_odd(unsigned pad) const
unsigned GEM_roll_CSC_min_wg_ME11_even(unsigned roll) const
unsigned GEM_roll_CSC_max_wg_ME11_even(unsigned roll) const
unsigned GEM_roll_L2_CSC_max_wg_ME21_odd(unsigned roll) const
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::EventID const &, edm::Timestamp const & > We also list in braces which AR_WATCH_USING_METHOD_ is used for those or
Definition: Activities.doc:12
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
void run(const GEMPadDigiClusterCollection *, const CSCL1TPLookupTableME11ILT *lookupTableME11ILT, const CSCL1TPLookupTableME21ILT *lookupTableME21ILT)
void addSingleClusters(const GEMPadDigiClusterCollection *)
std::vector< GEMCoPadDigi > readoutCoPads() const
unsigned GEM_roll_L1_CSC_max_wg_ME21_even(unsigned roll) const
unsigned GEM_roll_L2_CSC_max_wg_ME21_even(unsigned roll) const
unsigned GEM_roll_L2_CSC_min_wg_ME21_even(unsigned roll) const
unsigned GEM_pad_CSC_es_ME11a_odd(unsigned pad) const
unsigned GEM_roll_CSC_max_wg_ME11_odd(unsigned roll) const
void addCoincidenceClusters(const GEMPadDigiClusterCollection *)
unsigned GEM_roll_L1_CSC_min_wg_ME21_odd(unsigned roll) const
std::pair< typename Association::data_type::first_type, double > match(Reference key, Association association, bool bestMatchByMaxValue)
Generic matching function.
Definition: Utils.h:10
Definition: output.py:1
unsigned GEM_roll_L2_CSC_min_wg_ME21_odd(unsigned roll) const
GEMClusterProcessor(int region, unsigned station, unsigned chamber, const edm::ParameterSet &conf)
Log< level::Warning, false > LogWarning
unsigned int delayGEMinOTMB_
void doCoordinateConversion(const CSCL1TPLookupTableME11ILT *lookupTableME11ILT, const CSCL1TPLookupTableME21ILT *lookupTableME21ILT)