CMS 3D CMS Logo

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