ATLAS Offline Software
Loading...
Searching...
No Matches
TileL2Builder.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3*/
4
5//*****************************************************************************
6// Filename : TileL2Builder.cxx
7// Author : Aranzazu Ruiz
8// Created : February, 2009
9//
10// DESCRIPTION:
11// AlgTool used to build the TileL2 objects.
12// This tool is used by TileRawChannelToL2 and TileROD_Decoder.
13//
14// HISTORY:
15//
16// BUGS:
17//
18//*****************************************************************************
19
20// Tile includes
22#include "TileEvent/TileL2.h"
27
31
32// Calo includes
33#include "CaloDetDescr/CaloDetDescrElement.h"
36
37// Athena includes
41
42// Gaudi incldes
43#include "GaudiKernel/ServiceHandle.h"
44
45
46static const InterfaceID IID_ITileL2Builder("TileL2Builder", 1, 0);
47
48const InterfaceID& TileL2Builder::interfaceID() {
49 return IID_ITileL2Builder;
50}
51
52TileL2Builder::TileL2Builder(const std::string& type, const std::string& name,
53 const IInterface* parent)
54 : AthAlgTool(type, name, parent)
55 , m_noiseThreshold(100.0) // 100 MeV universal cut for now
56 , m_noiseType(9999) // this huge value means that noise cut is taken from JO
57 , m_tileHWID(nullptr)
58{
59
60 declareInterface<TileL2Builder>(this);
61
62 declareProperty("NoiseThreshold", m_noiseThreshold); // use channels only above noise cut
63 declareProperty("Noise", m_noiseType); // choose between electronic or total noise
64}
65
68
70
71 ATH_CHECK( detStore()->retrieve(m_tileHWID) );
72
73 ATH_CHECK( m_emScaleKey.initialize() );
74 ATH_CHECK( m_badChannelsKey.initialize() );
75
76 // Initialize
77 this->m_hashFunc.initialize(m_tileHWID);
78
79 const TileID* tileID = nullptr;
80 ATH_CHECK( detStore()->retrieve(tileID) );
81
82 const TileTBID* tileTBID = nullptr;
83 ATH_CHECK( detStore()->retrieve(tileTBID) );
84
85 // retrieve Tile detector manager and TileID helper from det store
86 const TileDetDescrManager* tileMgr = nullptr;
87 ATH_CHECK( detStore()->retrieve(tileMgr) );
88
89 ServiceHandle<TileCablingSvc> cablingSvc("TileCablingSvc", name());
90 ATH_CHECK( cablingSvc.retrieve());
91
92 const TileCablingService* cabling = cablingSvc->cablingService();
93 if (!cabling) {
94 ATH_MSG_ERROR( "Unable to retrieve TileCablingService" );
95 return StatusCode::FAILURE;
96 }
97
98 for (int ros = 0; ros < 4; ++ros) {
99 for (int ch = 0; ch < 48; ++ch) {
100 m_channelPairs[ros][ch] = ch;
101 m_connected[ros][ch] = true;
102 }
103 }
104
105 int drawer = 0;
106 for (int ros = 1; ros < 5; ++ros) {
107 int ros1 = ros - 1;
108 for (int ch = 0; ch < 48; ++ch) {
109 HWIdentifier ch_id = m_tileHWID->channel_id(ros, drawer, ch);
110 Identifier cell_id = cabling->h2s_cell_id(ch_id);
111
112 if (cell_id.is_valid()
113 && !tileTBID->is_tiletb(cell_id)
114 && tileID->sample(cell_id) != TileID::SAMP_E) {
115
116 m_sinTh[ros1][ch] = tileMgr->get_cell_element(cell_id)->sinTh();
117 m_sinThRound[ros1][ch] = round(m_sinTh[ros1][ch] * 32768) / 32768.; // set 15 bit presision a-la DSP
118 m_cosTh[ros1][ch] = fabs(tileMgr->get_cell_element(cell_id)->cosTh()); // Always positive !!!
119 m_cosThRound[ros1][ch] = round(m_cosTh[ros1][ch] * 32768) / 32768.; // set 15 bit presision a-la DSP
120
121 Identifier pmt1_id = tileID->pmt_id(cell_id, 0);
122 Identifier pmt2_id = tileID->pmt_id(cell_id, 1);
123 HWIdentifier ch1_id = cabling->s2h_channel_id(pmt1_id);
124 HWIdentifier ch2_id = cabling->s2h_channel_id(pmt2_id);
125 int ch1 = m_tileHWID->channel(ch1_id);
126 int ch2 = m_tileHWID->channel(ch2_id);
127 if (ch1 != ch && ch2 != ch) {
128 ATH_MSG_ERROR( "wrong cabling! ch=" << ch
129 << " ch1=" << ch1
130 << " ch2=" << ch2 );
131
132 } else {
133 m_channelPairs[ros1][ch1] = ch2;
134 m_channelPairs[ros1][ch2] = ch1;
135 }
136
137 ATH_MSG_VERBOSE( "ros=" << ros
138 << " ch=" << ch
139 << " tower=" << tileID->tower(cell_id)
140 << " sample=" << tileID->sample(cell_id)
141 << " sinTh=" << m_sinThRound[ros1][ch]
142 << " cosTh=" << m_cosThRound[ros1][ch]
143 << " channels in a cell: " << ch1 << " " << ch2 );
144
145 } else {
146 m_sinTh[ros1][ch] = 0.0;
147 m_sinThRound[ros1][ch] = 0;
148 m_cosTh[ros1][ch] = 0.0;
149 m_cosThRound[ros1][ch] = 0;
150 m_connected[ros1][ch] = false;
151 ATH_MSG_VERBOSE( "ros=" << ros
152 << " ch=" << ch
153 << " sinTh=" << m_sinThRound[ros1][ch]
154 << " cosTh=" << m_cosThRound[ros1][ch] );
155 }
156 }
157 }
158
159 ATH_CHECK( m_rawChannelContainerKey.initialize() );
160
161 ATH_MSG_INFO( "TileL2Builder initialization completed" );
162
163 return StatusCode::SUCCESS;
164}
165
166StatusCode TileL2Builder::process(int fragmin, int fragmax, TileL2Container *l2Container) const {
167 const EventContext& ctx{Gaudi::Hive::currentContext()};
168 return process(fragmin, fragmax, l2Container, ctx);
169};
170
171StatusCode TileL2Builder::process(int fragmin, int fragmax, TileL2Container *l2Container, const EventContext& ctx) const {
172
174 ATH_CHECK( emScale.isValid() );
175
177 ATH_CHECK( badChannels.isValid() );
178
179 // Get TileRawChannels
181 ATH_CHECK( rawChannelContainer.isValid() );
182
183 std::vector<unsigned int> extraWord;
184 std::vector<float> EtaMuons;
185 std::vector<float> EMuons0;
186 std::vector<float> EMuons1;
187 std::vector<float> EMuons2;
188 std::vector<unsigned int> qf;
189
190 float E_MeV[48];
191 bool bad[48];
192 int gain[48];
193
194 TileRawChannelUnit::UNIT rChUnit = rawChannelContainer->get_unit();
195 bool dspCont = (rChUnit >= TileRawChannelUnit::OnlineOffset);
196 bool recalibrate = (rChUnit != TileRawChannelUnit::MegaElectronVolts
198
199 // iterate over all collections in a container
200 for (const TileRawChannelCollection* rawChannelCollection : *rawChannelContainer) {
201
202 HWIdentifier drawer_id = m_tileHWID->drawer_id(rawChannelCollection->identify());
203 int ros = m_tileHWID->ros(drawer_id);
204 int drawer = m_tileHWID->drawer(drawer_id);
205 int fragId = m_tileHWID->frag(ros, drawer);
206 int drawerIdx = TileCalibUtils::getDrawerIdx(ros, drawer);
207
208 if ((fragId >= fragmin) && (fragId <= fragmax)) {
209
210 ATH_MSG_VERBOSE( "Unpacking frag 0x" << MSG::hex << fragId << MSG::dec );
211
212 memset(E_MeV, 0, sizeof(E_MeV));
213 memset(bad, 0, sizeof(bad));
214 memset(gain, -1, sizeof(gain));
215
216 // iterate over all raw channels in a collection
217 for (const TileRawChannel* rawChannel : *rawChannelCollection) {
218 HWIdentifier adc_id = rawChannel->adc_HWID();
219 int channel = m_tileHWID->channel(adc_id);
220 int adc = m_tileHWID->adc(adc_id);
221 float ampl = rawChannel->amplitude();
222 if (recalibrate) {
223 E_MeV[channel] = emScale->calibrateChannel(drawerIdx, channel, adc, ampl, rChUnit
225 } else {
226 E_MeV[channel] = ampl; // no conversion since energy is in MeV already
227 }
228 if (dspCont) {
229 bad[channel] = rawChannel->quality() > 15.99;
230 } else {
231 bad[channel] = badChannels->getAdcStatus(adc_id).isBad();
232 }
233 gain[channel] = adc;
234 }
235
236 // bad channel masking
237 MaskBad(ros, E_MeV, gain, bad);
238
239 // MET
240 std::vector<float> sumE(3);
241 SumE(ros, drawer, TileRawChannelUnit::MegaElectronVolts, E_MeV, gain, sumE);
242 (*l2Container)[m_hashFunc(fragId)]->setEt(std::move(sumE));
243
244 // MTag
245
246 EtaMuons.clear();
247 EMuons0.clear();
248 EMuons1.clear();
249 EMuons2.clear();
250 qf.clear();
251 extraWord.clear();
252
253 switch (ros) {
255 MTagLB(ros, drawer, E_MeV, EtaMuons, EMuons0, EMuons1, EMuons2, qf, extraWord);
256 break;
258 MTagLB(ros, drawer, E_MeV, EtaMuons, EMuons0, EMuons1, EMuons2, qf, extraWord);
259 break;
261 MTagEB(ros, drawer, E_MeV, EtaMuons, EMuons0, EMuons1, EMuons2, qf, extraWord);
262 break;
264 MTagEB(ros, drawer, E_MeV, EtaMuons, EMuons0, EMuons1, EMuons2, qf, extraWord);
265 break;
266 default:
267 ATH_MSG_ERROR( "incorrect ros value " << ros );
268 break;
269 }
270
271 if (EtaMuons.size())
272 (*l2Container)[m_hashFunc(fragId)]->setMu(EtaMuons, EMuons0, EMuons1, EMuons2, qf, extraWord);
273
274 } // end loop over collections
275
276 }
277
278 // Execution completed
279 ATH_MSG_DEBUG( "TileL2Builder execution completed" );
280
281 return StatusCode::SUCCESS;
282}
283
285
286 ATH_MSG_INFO( "Finalizing" );
287
288 return StatusCode::SUCCESS;
289}
290
291void TileL2Builder::MTagLB(int partition
292 , int drawer
293 , float* E
294 , std::vector<float> &EtaMuons
295 , std::vector<float> &EMuons0
296 , std::vector<float> &EMuons1
297 , std::vector<float> &EMuons2
298 , std::vector<unsigned int> &qf
299 , std::vector<unsigned int> &extraWord) const {
300
301 // Maximum number of muons tagged per superdrawer
302 int cut = 4;
303
304 // Energy thresholds (MeV)
305 int Eth_low = 150;
306 int Eth_LB_A[8] = { 1350, 960, 870, 750, 840, 840, 930, 840 };
307 int Eth_LB_BC[8] = { 2550, 1980, 1770, 1890, 1860, 1800, 1890, 1860 };
308 int Eth_LB_D[4] = { 1590, 1110, 1050, 1050 };
309
310 // Eta cells
311 float eta_LB_A[8] = { 0.05, 0.15, 0.25, 0.35, 0.45, 0.55, 0.65, 0.75 }; // A1, A2, A3, A4, A5, A6, A7, A8
312 float eta_LB_BC[8] = { 0.05, 0.15, 0.25, 0.35, 0.45, 0.55, 0.65, 0.75 }; // BC1, BC2, BC3, BC4, BC5, BC6, BC7, BC8
313 float eta_LB_D[4] = { 0.00, 0.20, 0.40, 0.60 }; // D0, D1, D2, D3
314
315 // D cells to BC cells in LB
316 int cell32[4 * 4] = {
317 1, 0, 0, 0, // D0 -> BC1
318 2, 1, 2, 0, // D1 -> BC2, BC3
319 3, 3, 4, 5, // D2 -> BC4, BC5, BC6
320 3, 5, 6, 7 // D3 -> BC6, BC7, BC8
321 };
322
323 drawer = drawer % 2;
324
325 int NMuons = 0;
326 int quality;
327 int pattern = 0;
328
329 int k2, ks, ksto2;
330 int cand = 0;
331
332 unsigned int cquality[4] = { 0 };
333 unsigned int flquality[4] = { 0 };
334 unsigned int aquality[4] = { 0 };
335
336 int eta[4] = { 0 };
337 int splited[4] = { 0 };
338 int found[4] = { 0 };
339
340 float E_A[8];
341 float E_BC[8];
342 float E_D[4];
343
344 /* A cells */
345
346 E_A[0] = E[1] + E[4]; // A1
347 E_A[1] = E[5] + E[8]; // A2
348 E_A[2] = E[9] + E[10]; // A3
349 E_A[3] = E[15] + E[18]; // A4
350 E_A[4] = E[19] + E[20]; // A5
351 E_A[5] = E[23] + E[26]; // A6
352 E_A[6] = E[29] + E[32]; // A7
353 E_A[7] = E[35] + E[38]; // A8
354
355 /* BC cells */
356
357 E_BC[0] = E[2] + E[3]; // BC1
358 E_BC[1] = E[6] + E[7]; // BC2
359 E_BC[2] = E[11] + E[12]; // BC3
360 E_BC[3] = E[16] + E[17]; // BC4
361 E_BC[4] = E[21] + E[22]; // BC5
362 E_BC[5] = E[28] + E[27]; // BC6
363 E_BC[6] = E[34] + E[33]; // BC7
364 E_BC[7] = E[40] + E[39]; // BC8
365
366 /* D cells */
367
368 E_D[0] = E[0] * 2; // D0
369 E_D[1] = E[13] + E[14]; // D1
370 E_D[2] = E[24] + E[25]; // D2
371 E_D[3] = E[41] + E[44]; // D3
372
373 /* Define candidates */
374
375 for (int i = 0; i < 4; i++) { // loop over D cells
376 if (E_D[i] >= Eth_low) {
377 eta[cand] = i;
378 splited[cand] = -1;
379 cquality[cand] = E_D[i] < Eth_LB_D[i] ? 0 : 1;
380 cand++;
381 }
382 }
383
384 /* Repair for muons splitted */
385
386 if (cand > 4) std::abort();
387 for (int i = 0; i < cand; i++) {
388 for (int j = 0; j < i; j++) {
389 if ((cquality[i] + cquality[j]) == 0) {
390 if (abs(eta[i] - eta[j]) <= 1
391 && (E_D[eta[i]] + E_D[eta[j]])
392 < (Eth_LB_D[eta[i]] > Eth_LB_D[eta[j]] ? Eth_LB_D[eta[i]] : Eth_LB_D[eta[j]])) {
393
394 splited[i] = j;
395
396 }
397 } else if ((cquality[i] + cquality[j]) == 1) {
398
399 if (abs(eta[i] - eta[j]) <= 1) {
400
401 splited[i] = j;
402
403 }
404 }
405 }
406 }
407
408 /* Loop on the candidates */
409
410 for (int i = 0;
411 (i < cand && splited[i] < 0) || ((i < cand && splited[i] >= 0) && found[splited[i]] == 0);
412 i++) {
413
414 found[i] = 0;
415 ksto2 = cell32[4 * eta[i]];
416
417 for (ks = 1; ks <= ksto2 && found[i] != 1; ks++) {
418
419 // eta position BC cell with a muon candidate
420 k2 = cell32[4 * eta[i] + ks];
421
422 // Lower threshold BC cells
423 if (E_BC[k2] > Eth_low) {
424 flquality[i] = (E_BC[k2] < Eth_LB_BC[k2] ? 0 : 1);
425 if (found[i] != 1 && E_A[k2] > Eth_low) {
426 aquality[i] = (E_A[k2] < Eth_LB_A[k2] ? 0 : 1);
427 quality = cquality[i] + flquality[i] + aquality[i];
428 if (quality <= 1) {
429 found[i] = 1;
430
431 // energy deposited by the muon (A cell)
432 EMuons0.push_back(E_A[k2]);
433
434 // energy deposited by the muon (BC cell)
435 EMuons1.push_back(E_BC[k2]);
436
437 // energy deposited by the muon (D cell)
438 EMuons2.push_back(E_D[eta[i]]);
439
440 // quality factor
441 qf.push_back(cquality[i] + flquality[i] + aquality[i]);
442
443 // LBC partition
444 if (partition == 1)
445 EtaMuons.push_back((eta_LB_D[eta[i]] + eta_LB_BC[k2] + eta_LB_A[k2]) * (1. / 3));
446
447 // LBA partition
448 if (partition == 2)
449 EtaMuons.push_back(-(eta_LB_D[eta[i]] + eta_LB_BC[k2] + eta_LB_A[k2]) * (1. / 3));
450
451 if (eta[i] == 0 && k2 == 0) pattern = 0; // D0, BC1, A1
452 if (eta[i] == 1 && k2 == 1) pattern = 1; // D1, BC2, A2
453 if (eta[i] == 1 && k2 == 2) pattern = 2; // D1, BC3, A3
454 if (eta[i] == 2 && k2 == 3) pattern = 3; // D2, BC4, A4
455 if (eta[i] == 2 && k2 == 4) pattern = 4; // D2, BC5, A5
456 if (eta[i] == 2 && k2 == 5) pattern = 5; // D2, BC6, A6
457 if (eta[i] == 3 && k2 == 5) pattern = 6; // D3, BC6, A6
458 if (eta[i] == 3 && k2 == 6) pattern = 7; // D3, BC7, A7
459 if (eta[i] == 3 && k2 == 7) pattern = 8; // D3, BC8, A8
460
461 // Words with encoded muon information for one superdrawer
462 unsigned int uquality = quality;
463 extraWord.push_back( (uquality << 31) | (drawer << 30) | (pattern << 25) | ((int) (2 * E_D[eta[i]])));
464 extraWord.push_back((((int) (2 * E_BC[k2])) << 16) | ((int) (2 * E_A[k2])));
465
466 NMuons++;
467 }
468 }
469 }
470 }
471 if (NMuons >= cut) break;
472 }
473}
474
475void TileL2Builder::MTagEB(int partition
476 , int drawer
477 , float* E
478 , std::vector<float> &EtaMuons
479 , std::vector<float> &EMuons0
480 , std::vector<float> &EMuons1
481 , std::vector<float> &EMuons2
482 , std::vector<unsigned int> &qf
483 , std::vector<unsigned int> &extraWord) const {
484
485 // Maximum number of muons tagged per superdrawer
486 int cut = 4;
487
488 // Energy thresholds (MeV)
489 int Eth_low = 150;
490 int Eth_EB_A[4] = { 810, 1140, 1230, 1380 };
491 int Eth_EB_BC[5] = { 1050, 1380, 1440, 1500, 1680 };
492 int Eth_EB_D[2] = { 2100, 2370 };
493
494 // Eta cells
495 float eta_EB_A[4] = { 1.15, 1.25, 1.35, 1.45 }; // A12, A13, A14, A15
496 float eta_EB_BC[5] = { 1.05, 1.15, 1.25, 1.35, 1.45 }; // B11, B12, B13, B14, B15
497 float eta_EB_D[2] = { 1.00, 1.20 }; // D5, D6
498
499 // D cells to B cells in EB
500 int cell32[2 * 6] = {
501 3, 0, 1, 2, 0, 0, // D5 -> B11, B12, B13
502 5, 0, 1, 2, 3, 4 // D6 -> B11, B12, B13, B14, B15
503 };
504
505 // B cells to A cells in EB
506 int cell21[5 * 4] = {
507 1, 0, 0, 0, // B11 -> A12
508 2, 0, 1, 0, // B12 -> A12, A13
509 3, 0, 1, 2, // B13 -> A12, A13, A14
510 3, 1, 2, 3, // B14 -> A13, A14, A15
511 2, 2, 3, 0 // B15 -> A14, A15
512 };
513
514 drawer = drawer % 2;
515
516 int NMuons = 0;
517 int quality;
518 int pattern = 0;
519
520 int k2, ks, ksto2, k1, ksto1;
521 int cand = 0;
522
523 unsigned int cquality[4] = { 0 };
524 unsigned int flquality[4] = { 0 };
525 unsigned int aquality[4] = { 0 };
526
527 int eta[4] = { 0 };
528 int splited[4] = { 0 };
529 int found[4] = { 0 };
530
531 float E_A[4];
532 float E_BC[5];
533 float E_D[2];
534
535 /* A cells */
536
537 E_A[0] = E[6] + E[7]; // A12
538 E_A[1] = E[10] + E[11]; // A13
539 E_A[2] = E[20] + E[21]; // A14
540 E_A[3] = E[31] + E[32]; // A15
541
542 /* B cells */
543
544 E_BC[0] = E[8] + E[9]; // B11
545 E_BC[1] = E[14] + E[15]; // B12
546 E_BC[2] = E[22] + E[23]; // B13
547 E_BC[3] = E[30] + E[35]; // B14
548 E_BC[4] = E[36] + E[39]; // B15
549
550 /* D cells */
551
552 E_D[0] = E[16] + E[17]; // D5
553 E_D[1] = E[37] + E[38]; // D6
554
555 /* Define candidates */
556
557 for (int i = 0; i < 2; i++) { // loop over D cells
558 if (E_D[i] >= Eth_low) {
559 eta[cand] = i;
560 splited[cand] = -1;
561 cquality[cand] = E_D[i] < Eth_EB_D[i] ? 0 : 1;
562 cand++;
563 }
564 }
565
566 /* Repair for muons splitted */
567
568 if (cand > 4) std::abort();
569 for (int i = 0; i < cand; i++) {
570 for (int j = 0; j < i; j++) {
571 if ((cquality[i] + cquality[j]) == 0) {
572 if (abs(eta[i] - eta[j]) <= 1
573 && (E_D[eta[i]] + E_D[eta[j]])
574 < (Eth_EB_D[eta[i]] > Eth_EB_D[eta[j]] ? Eth_EB_D[eta[i]] : Eth_EB_D[eta[j]])) {
575
576 splited[i] = j;
577 }
578 } else if ((cquality[i] + cquality[j]) == 1) {
579 if (abs(eta[i] - eta[j]) <= 1) {
580 splited[i] = j;
581 }
582 }
583 }
584 }
585
586 /* Loop on the candidates */
587
588 for (int i = 0;
589 (i < cand && splited[i] < 0) || ((i < cand && splited[i] >= 0) && found[splited[i]] == 0);
590 i++) {
591
592 found[i] = 0;
593
594 ksto2 = cell32[6 * eta[i]];
595
596 for (ks = 1; ks <= ksto2 && found[i] != 1; ks++) {
597
598 // eta position BC cell with a muon candidate
599 k2 = cell32[6 * eta[i] + ks];
600
601 // Lower threshold BC cells
602 if (E_BC[k2] > Eth_low) {
603
604 flquality[i] = (E_BC[k2] < Eth_EB_BC[k2] ? 0 : 1);
605 ksto1 = cell21[4 * k2 + 0];
606
607 for (int kp = 1; kp <= ksto1 && found[i] != 1; kp++) {
608 k1 = cell21[4 * k2 + kp];
609 if (E_A[k1] > Eth_low) {
610 aquality[i] = (E_A[k1] < Eth_EB_A[k1] ? 0 : 1);
611 quality = cquality[i] + flquality[i] + aquality[i];
612 if (quality <= 1) {
613 found[i] = 1;
614
615 // energy deposited by the muon (A cell)
616 EMuons0.push_back(E_A[k1]);
617
618 // energy deposited by the muon (B cell)
619 EMuons1.push_back(E_BC[k2]);
620
621 // energy deposited by the muon (D cell)
622 EMuons2.push_back(E_D[eta[i]]);
623
624 // quality factor
625 qf.push_back(cquality[i] + flquality[i] + aquality[i]);
626
627 // EBC partition
628 if (partition == 3)
629 EtaMuons.push_back((eta_EB_D[eta[i]] + eta_EB_BC[k2] + eta_EB_A[k1]) * (1. / 3));
630
631 // EBA partition
632 if (partition == 4)
633 EtaMuons.push_back(-(eta_EB_D[eta[i]] + eta_EB_BC[k2] + eta_EB_A[k1]) * (1. / 3));
634
635 if (eta[i] == 0 && k2 == 0 && k1 == 0) pattern = 0; // D5, B11, A12
636 if (eta[i] == 0 && k2 == 1 && k1 == 0) pattern = 1; // D5, B12, A12
637 if (eta[i] == 0 && k2 == 1 && k1 == 1) pattern = 2; // D5, B12, A13
638 if (eta[i] == 0 && k2 == 2 && k1 == 0) pattern = 3; // D5, B13, A12
639 if (eta[i] == 0 && k2 == 2 && k1 == 1) pattern = 4; // D5, B13, A13
640 if (eta[i] == 0 && k2 == 2 && k1 == 2) pattern = 5; // D5, B13, A14
641 if (eta[i] == 1 && k2 == 0 && k1 == 0) pattern = 6; // D6, B11, A12
642 if (eta[i] == 1 && k2 == 1 && k1 == 0) pattern = 7; // D6, B12; A12
643 if (eta[i] == 1 && k2 == 1 && k1 == 1) pattern = 8; // D6, B12; A13
644 if (eta[i] == 1 && k2 == 2 && k1 == 0) pattern = 9; // D6, B13, A12
645 if (eta[i] == 1 && k2 == 2 && k1 == 1) pattern = 10; // D6, B13, A13
646 if (eta[i] == 1 && k2 == 2 && k1 == 2) pattern = 11; // D6, B13, A14
647 if (eta[i] == 1 && k2 == 3 && k1 == 1) pattern = 12; // D6, B14, A13
648 if (eta[i] == 1 && k2 == 3 && k1 == 2) pattern = 13; // D6, B14, A14
649 if (eta[i] == 1 && k2 == 3 && k1 == 3) pattern = 14; // D6, B14, A15
650 if (eta[i] == 1 && k2 == 4 && k1 == 2) pattern = 15; // D6, B15, A14
651 if (eta[i] == 1 && k2 == 4 && k1 == 3) pattern = 16; // D6, B15, A15
652
653 // Words with encoded muon information for one superdrawer
654 unsigned int uquality = quality;
655 extraWord.push_back( (uquality << 31)
656 | (drawer << 30)
657 | (pattern << 25)
658 | ((int) (2 * E_D[eta[i]])));
659
660 extraWord.push_back((((int) (2 * E_BC[k2])) << 16) | ((int) (2 * E_A[k1])));
661
662 NMuons++;
663
664 }
665 }
666 }
667 }
668 }
669 if (NMuons >= cut) break;
670 }
671}
672
673void TileL2Builder::SumE(int ros, int /* drawer */, int unit, float *E, int *gain,
674 std::vector<float> &sumE) const {
675 // precision in DSP - 1/16 ADC counts or 1/2048 pC and CspC or 1/2 MeV
676 static const float AMPLITUDE_FACTOR_HG[4] = { 16.0, 32.0 * 64, 32.0 * 64., 2.0 };
677 static const float AMPLITUDE_FACTOR_LG[4] = { 16.0, 32.0, 32.0, 2.0 / 64.0 };
678
679 if (ros < 1 || ros > 4) {
680 sumE[0] = sumE[1] = sumE[2] = 0.0;
681 return;
682 }
683
684 unit &= 3; // keep last 2 bits, remove online offset
685 const float scaleHG = AMPLITUDE_FACTOR_HG[unit];
686 const float scaleLG = AMPLITUDE_FACTOR_LG[unit];
687 int ros1 = ros - 1;
688 const float* wt = m_sinThRound[ros1];
689 const float* wz = m_cosThRound[ros1];
690 const bool* connected = m_connected[ros1];
691
692 float Et = 0.0;
693 float Ez = 0.0;
694 float Es = 0.0;
695
696 // for the moment only fixed noise cut implemented
697 // and it works correctly only if energy is in MeV
698 float cut = m_noiseThreshold * scaleHG;
699
700 for (int i = 0; i < 48; ++i) {
701 if (*connected++) {
702 float e = (*gain) ? round((*E) * scaleHG) : round((*E) * scaleLG) * 64.;
703 if (e > cut) {
704 Et += round((*wt) * e);
705 Ez += round((*wz) * e);
706 Es += round(e);
707 }
708 }
709 ++E;
710 ++gain;
711 ++wt;
712 ++wz;
713 }
714
715 const float inv_scaleHG = 1. / scaleHG;
716 sumE[0] = Et * inv_scaleHG;
717 sumE[1] = Ez * inv_scaleHG;
718 sumE[2] = Es * inv_scaleHG;
719}
720
721void TileL2Builder::SumE(int ros, int /* drawer */, float *E, std::vector<float> &sumE) const {
722 if (ros < 1 || ros > 4) {
723 sumE[0] = sumE[1] = sumE[2] = 0.0;
724 return;
725 }
726
727 int ros1 = ros - 1;
728 const float* wt = m_sinTh[ros1];
729 const float* wz = m_cosTh[ros1];
730 const bool* connected = m_connected[ros1];
731 float Et = 0.0;
732 float Ez = 0.0;
733 float Es = 0.0;
734
735 for (int i = 0; i < 48; ++i) {
736 if (*connected++) {
737 float e = (*E); // assuming that E is in MeV
738 if (e > m_noiseThreshold) { // for the moment only fixed noise cut implemented
739 Et += e * (*wt);
740 Ez += e * (*wz);
741 Es += e;
742 }
743 }
744 ++E;
745 ++wt;
746 ++wz;
747 }
748
749 sumE[0] = Et;
750 sumE[1] = Ez;
751 sumE[2] = Es;
752}
753
754void TileL2Builder::MaskBad(int ros, float *E, int * gain, bool *bad) const {
755 for (int i = 0; i < 48; ++i) {
756 if (bad[i]) {
757 int j = m_channelPairs[ros - 1][i];
758 if (bad[j]) { // both bad or i=j (i.e. single channel)
759 E[i] = E[j] = 0.0;
760 gain[i] = gain[j] = -1;
761 } else {
762 E[i] = E[j]; // copy from second channel
763 gain[i] = gain[j];
764 }
765 }
766 }
767 return;
768}
769
Scalar eta() const
pseudorapidity method
const PlainObject unit() const
This is a plugin that makes Eigen look like CLHEP & defines some convenience methods.
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_DEBUG(x)
Helpers for checking error return status codes and reporting errors.
Handle class for reading from StoreGate.
TileContainer< TileL2 > TileL2Container
static const InterfaceID IID_ITileL2Builder("TileL2Builder", 1, 0)
AthAlgTool(const std::string &type, const std::string &name, const IInterface *parent)
Constructor with parameters:
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
const ServiceHandle< StoreGateSvc > & detStore() const
float sinTh() const
for algorithm working in transverse Energy
bool is_valid() const
Check if id is in a valid state.
static unsigned int getDrawerIdx(unsigned int ros, unsigned int drawer)
Returns a drawer hash.
CaloDetDescrElement * get_cell_element(unsigned int cell_hash) const
@ BARREL_POS
Definition TileHWID.h:68
@ EXTBAR_NEG
Definition TileHWID.h:71
@ BARREL_NEG
Definition TileHWID.h:69
@ EXTBAR_POS
Definition TileHWID.h:70
Helper class for TileCal offline identifiers.
Definition TileID.h:67
float m_sinThRound[4][48]
void MaskBad(int partition, float *E, int *gain, bool *bad) const
function which does bad channel masking: if one channel of a cell is bad, energy from second channel ...
TileL2Builder(const std::string &type, const std::string &name, const IInterface *parent)
SG::ReadHandleKey< TileRawChannelContainer > m_rawChannelContainerKey
TileRawChannelContainer in event store.
virtual ~TileL2Builder() override
void MTagLB(int partition, int drawer, float *EMeV, std::vector< float > &EtaMuons, std::vector< float > &EMuons0, std::vector< float > &EMuons1, std::vector< float > &EMuons2, std::vector< unsigned int > &qf, std::vector< unsigned int > &extraWord) const
Muon tagging function for LB superdrawers as processed at the ROD DSPs.
float m_cosThRound[4][48]
virtual StatusCode finalize() override
float m_cosTh[4][48]
static const InterfaceID & interfaceID()
TileFragHash m_hashFunc
void MTagEB(int partition, int drawer, float *EMeV, std::vector< float > &EtaMuons, std::vector< float > &EMuons0, std::vector< float > &EMuons1, std::vector< float > &EMuons2, std::vector< unsigned int > &qf, std::vector< unsigned int > &extraWord) const
Muon tagging function for EB superdrawers as processed at the ROD DSPs.
void SumE(int partition, int drawer, float *E, std::vector< float > &sumE) const
SumE function for one superdrawer as processed at the ROD DSPs.
const TileHWID * m_tileHWID
Pointer to TileHWID.
virtual StatusCode initialize() override
float m_sinTh[4][48]
SG::ReadCondHandleKey< TileEMScale > m_emScaleKey
Name of TileEMScale in condition store.
bool m_connected[4][48]
SG::ReadCondHandleKey< TileBadChannels > m_badChannelsKey
Name of TileBadChannels in condition store.
virtual StatusCode process(int fragmin, int fragmax, TileL2Container *l2Container) const
int m_channelPairs[4][48]
Helper class for TileCal offline identifiers of ancillary testbeam detectors and MBTS.
bool is_tiletb(const Identifier &id) const
Test ID if it is TileTBID.
Definition TileTBID.cxx:87
int sample(const Identifier &id) const
int tower(const Identifier &id) const
Identifier pmt_id(const Identifier &any_id) const
const std::string process