ATLAS Offline Software
Loading...
Searching...
No Matches
TileDigitsToTTL1.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
5//*****************************************************************************
6// Filename : TileDigitsToTTL1.cxx
7// Author : Pedro Amaral following example from TileHitToTTL1
8// Created : Feb, 2005
9//
10// DESCRIPTION:
11// Created to emulate the Tile Level 1 Trigger Towers (TTL1), which are
12// hardware sums of the Tile channels/pmts, from 4 to 6 channels per tower.
13// The towers are read out in N time slices, with N=9 as a default.
14// Each TileDigit contains the corresponding N slices.
15// The resulting TTL1 object should be used by L1Calo simulation
16// This is the "data" (ie, digits) version of the simulation (ie, hit) algorithm
17// Output object TTL1 should be in units of mV.
18//
19// For each digit, the first time sample (0) is taken as pedestal, and subtracted
20// from all the digits. This assumes that the pedestal is introduced by the digitizer
21// The digits are then converted from ADC counts to pCb.
22// Then digits with the same eta, within the same drawer are summed, time sample
23// by time sample. ie, sum is done in charge.
24// In the end, the pCb are converted back to mV.
25// And noise of the adder (in mV) is added.
26//
27// HISTORY:
28//
29// BUGS:
30//
31//*****************************************************************************
32
33// Tile includes
34#include "TileDigitsToTTL1.h"
39
40// Calo includes
43
44// Atlas includes
48
49//CLHEP includes
50#include <CLHEP/Random/Randomize.h>
51
52//C++ STL includes
53#include <vector>
54#include <memory>
55
56
57//
58// Constructor
59//
60TileDigitsToTTL1::TileDigitsToTTL1(const std::string& name, ISvcLocator* pSvcLocator)
61 : AthAlgorithm(name, pSvcLocator)
62{
63}
64
65//
66// Alg standard initialize function
67//
69
70 // retrieve CaloLVL1_ID, TileID, TileHWID helpers and TileIfno from det store
71
72 CHECK( detStore()->retrieve(m_TT_ID) );
73 CHECK( detStore()->retrieve(m_tileID) );
74 CHECK( detStore()->retrieve(m_tileHWID) );
75
76 //=== get TileCondToolEmscale
77 CHECK( m_tileToolEmscale.retrieve() );
78
79 CHECK( detStore()->retrieve(m_tileInfo, m_infoName) );
80
81 ATH_CHECK(m_digitsContainerKey.initialize());
82 ATH_CHECK(m_ttl1ContainerKey.initialize());
83
84 ATH_MSG_INFO( "TileDigitsToTTL1 initialisation completed" );
85
86 return StatusCode::SUCCESS;
87}
88
89/*==========================================================================*/
90//
91// Begin Execution Phase.
92//
94
95 ATH_MSG_DEBUG( "Executing TileDigitsToTTL1" );
96
97 /*......................................................*/
98 // Step 2: Get all global parameters that will be needed for processing.
99 int nSamp = m_tileInfo->NdigitSamples(); // number of time slices for each chan
100 int iTrig = m_tileInfo->ItrigSample(); // index of the triggering time slice
101
102 /* Get TileNoise flag from TileInfo (true => generate noise in TileDigits) */
103 bool tileNoise = m_tileInfo->TileNoise();
104 /* Get TileZeroSuppress flag from TileInfo
105 (true => apply threshold to Digits) */
106 bool tileThresh = m_tileInfo->TileZeroSuppress();
107 // declare array for random number generation for noise in samples.
108 double Rndm[16]; // Can't use variable size array
109
110 ATH_MSG_DEBUG( "nSamp=" << nSamp
111 << ", iTrig=" << iTrig
112 << ", tileNoise=" << ((tileNoise) ? "true" : "false")
113 << ", tileThresh=" << ((tileThresh) ? "true" : "false") );
114
115 /*......................................................*/
116 // step 3: Get digit container from TES and create TTL1 container
117 /* Note that digit container has 256 collections (one for each drawer),
118 but TTL1 container has no collections and no structure. */
120 ATH_CHECK( digitsContainer.isValid() );
121
123 ATH_CHECK( ttl1Container.record(std::make_unique<TileTTL1Container>()) );
124 ATH_MSG_DEBUG( "TileTTL1Container registered successfully (" << m_ttl1ContainerKey.key() << ")" );
125
126 /*......................................................*/
127 // Step 4: Create temporary arrays for processing signals.
128 /* Create array for all TT amplitudes in a single drawer. */
129 Identifier ttId[16]; // array of TT identifiers in a single drawer
130 bool ttDigit[16]; // array of TT occupancy in a single drawer
131 int nTT; // number of digit towers in this drawer.
132 int nDigit; // number of digits in this drawer.
133 int nIgnore; // number of ignored digits in this drawer.
134 int nTTTot = 0; // total number of digit towers.
135 int nDigitTot = 0; // total number of digits.
136 int nIgnoreTot = 0; // total number of ignored digits.
137 float ttAmpTot = 0; // total energy in good level-1 towers.
138 float ttAmpTotIg = 0.; // total energy in "ignored" level-1 towers.
139 int minieta, maxieta, posneg;
140
141 /* Create array for the nSamp time-samples of a single tower. */
142 std::vector<float> ttL1samples(nSamp);
143
144 /*......................................................*/
145 // Step 5: Begin loop over all collections (collection = electronic drawer).
146 for (const TileDigitsCollection* digitsCollection : *digitsContainer) {
147
148 HWIdentifier drawer_id = m_tileHWID->drawer_id(digitsCollection->identify());
149 int ros = m_tileHWID->ros(drawer_id);
150 int drawer = m_tileHWID->drawer(drawer_id);
151 int drawerIdx = TileCalibUtils::getDrawerIdx(ros, drawer);
152
153 switch (ros) {
155 posneg = +1;
156 minieta = 0;
157 maxieta = 8;
158 break;
160 posneg = -1;
161 minieta = 0;
162 maxieta = 8;
163 break;
165 posneg = +1;
166 minieta = 9;
167 maxieta = 14;
168 break;
170 posneg = -1;
171 minieta = 9;
172 maxieta = 14;
173 break;
174 default:
175 posneg = minieta = maxieta = 0;
176 }
177
178 /* Zero temporary array of trigger tower amplitudes (TTL1amp) for this collection. */
179 memset(ttDigit, 0, sizeof(ttDigit));
180 std::vector<std::vector<float> > myttAmp(16);
181 for (int ii = 0; ii < 16; ++ii)
182 myttAmp[ii].resize(nSamp);
183
184 nTT = nIgnore = nDigit = 0;
185
186 /*......................................................*/
187 // Step 6: Iterate over all digits in this collection, summing amps for each tower.
188 for (const TileDigits* tile_digits : *digitsCollection) {
189
190 // get digits
191 std::vector<float> samples = tile_digits->samples();
192 // get number of time samples & compare with
193 // int nSamp = m_tileInfo->NdigitSamples();
194 int nSamp2 = samples.size();
195 if (nSamp2 != nSamp) {
196 ATH_MSG_ERROR( "nSamp from TileInfo=" << nSamp
197 << " nSamp from digits= " << nSamp2 );
198 }
199 /* Get digit HWIdentifier (= channel_id) */
200 HWIdentifier adcId = tile_digits->adc_HWID();
201 int channel = m_tileHWID->channel(adcId);
202 int adc = m_tileHWID->adc(adcId);
203 // Subtract pedestal, that is samples[0] and convert from ADC counts to pCb.
204 float pedestal = samples[0];
205 for (int jsamp = 0; jsamp < nSamp; ++jsamp) {
206
207 samples[jsamp] = m_tileToolEmscale->channelCalib(drawerIdx, channel, adc,
209
210 }
211 Identifier pmt_id = tile_digits->pmt_ID();
212 if (pmt_id.is_valid()) {
213
214 /* Get TT Identifier for this pmt */
215 Identifier tt_id = tile_digits->tt_ID();
216 /* Get eta-phi indices of TTL1 for this channel. */
217 int ieta = m_TT_ID->eta(tt_id);
218 int iphi = m_TT_ID->phi(tt_id); // (same as module).
219 if (iphi != drawer)
220 ATH_MSG_ERROR( "drawer=" << drawer << ", iphi=" << iphi );
221
222 if (ttDigit[ieta]) { // already exists - just add charge for each sample
223 for (int jsamp = 0; jsamp < nSamp; ++jsamp) {
224 myttAmp[ieta][jsamp] += samples[jsamp];
225 }
226 } else { // digit in new TT
227 ttId[ieta] = tt_id;
228 ttDigit[ieta] = true;
229 for (int jsamp = 0; jsamp < nSamp; ++jsamp) {
230 myttAmp[ieta][jsamp] = samples[jsamp];
231 }
232 if (ieta >= minieta && ieta <= maxieta)
233 ++nTT; // count only valid TT
234 }
235 ++nDigit;
236 if (ieta < minieta || ieta > maxieta)
237 ++nIgnore;
238
239 //Sum cell energy for comparison to other algos.
240 // convert pCb to MeV
241 float e = m_tileToolEmscale->channelCalib(drawerIdx, channel, adc,
243
244 if (ieta >= minieta && ieta <= maxieta) {
245 ttAmpTot += e;
246 } else {
247 ttAmpTotIg += e;
248 }
249
250 if (msgLvl(MSG::VERBOSE)) {
251 /* Diagnostic checks: */
252 int side = m_tileID->side(pmt_id);
253 int tower = m_tileID->tower(pmt_id);
254 int sample = m_tileID->sample(pmt_id);
255 int pmt = m_tileID->pmt(pmt_id);
256 int channel = m_tileHWID->channel(adcId);
257
258 msg(MSG::VERBOSE) << "New Digit:"
259 << " ros=" << ros
260 << ", drawer=" << drawer
261 << ", ch=" << channel
262 << ", side=" << side
263 << ", tower=" << tower
264 << ", sample=" << sample
265 << ", pmt=" << pmt
266 << ", e=" << e
267 << ", ie=" << ieta
268 << ", ip=" << iphi;
269
270 if (ieta >= minieta && ieta <= maxieta)
271 msg(MSG::VERBOSE) << endmsg;
272 else
273 msg(MSG::VERBOSE) << " Outside limits" << endmsg;
274 }
275
276 } else {
277 ATH_MSG_VERBOSE( "Tile Channel with no tt_id" );
278 }
279 } // end loop over digits in this drawer.
280
281 nTTTot += nTT;
282 nDigitTot += nDigit;
283 nIgnoreTot += nIgnore;
284
285 ATH_MSG_VERBOSE( " Statistics for"
286 << " ROS=" << ros
287 << ", drawer=" << drawer
288 << "; posneg=" << posneg
289 << ", minieta=" << minieta
290 << ", maxieta=" << maxieta
291 << "; nTT=" << nTT
292 << ", nDigit=" << nDigit
293 << ", nIgnore=" << nIgnore );
294
295 /*......................................................*/
296 // Step 7: We now have all the TTL1 amplitudes for this drawer.
297 // Loop over towers to produce the electronics signals (= time samples).
298 // If tileNoise is requested, generate random numbers to give noise
299 for (int ieta = minieta; ieta <= maxieta; ++ieta) {
300 int iphi = drawer;
301 bool Good = ttDigit[ieta];
302 if (tileNoise)
303 Good = true;
304
305 if (Good) {
306 if (!ttDigit[ieta])
307 ttId[ieta] = m_TT_ID->tower_id(posneg, 1, 0, ieta, drawer);
308
309 float ttL1Calib = m_tileInfo->TTL1Calib(ttId[ieta]);
310 for (int jsamp = 0; jsamp < nSamp; ++jsamp) {
311 myttAmp[ieta][jsamp] *= ttL1Calib; // convert pCb to mV
312 }
313
314 /* Include shaping fuction, pedestal, and noise. */
315 if (tileNoise)
316 CLHEP::RandGauss::shootArray(nSamp, Rndm);
317 float ttL1Ped = m_tileInfo->TTL1Ped(ttId[ieta]);
318 float ttL1NoiseSigma = m_tileInfo->TTL1NoiseSigma(ttId[ieta]);
319 for (int jsamp = 0; jsamp < nSamp; ++jsamp) {
320 ttL1samples[jsamp] = myttAmp[ieta][jsamp] + ttL1Ped;
321 if (tileNoise)
322 ttL1samples[jsamp] += ttL1NoiseSigma * Rndm[jsamp];
323 } // end loop over samples
324 if (tileThresh) {
325 float ttL1Thresh = m_tileInfo->TTL1Thresh(ttId[ieta]);
326 if (ttL1samples[iTrig] - ttL1Ped < ttL1Thresh)
327 Good = false;
328 }
329 } // end first "Good" section.
330 /* Create the new TTL1 object and store in TTL1Container. */
331 if (Good) {
332 ATH_MSG_DEBUG( " TTL1: "
333 << " ros=" << ros
334 << ", ieta=" << ieta
335 << ", iphi=" << iphi
336 << ", digitTrue=" << ttDigit[ieta]
337 << ", Good=" << Good
338 << ", amp0=" << myttAmp[ieta][iTrig]
339 << ", digitIn=" << ttL1samples[iTrig] );
340
341 /*
342 The following lines are commented out.
343
344 if (msgLvl(MSG::VERBOSE)) {
345 msg(MSG::VERBOSE) << " ttL1Digits=";
346 for (int jsamp = 0; jsamp < nSamp; ++jsamp) {
347 msg(MSG::VERBOSE) << ttL1samples[jsamp] << " ";
348 }
349 msg(MSG::VERBOSE) << endmsg;
350
351 msg(MSG::VERBOSE) << " Rndm=";
352 for (int jsamp = 0; jsamp < nSamp; ++jsamp) {
353 msg(MSG::VERBOSE) << Rndm[jsamp] << " ";
354 }
355 msg(MSG::VERBOSE) << endmsg;
356 }
357 The preceding lines are commented out.
358 */
359
360 ttl1Container->push_back(std::make_unique<TileTTL1>(ttId[ieta], ttL1samples));
361 } // end second "Good" section.
362 } // end loop over towers
363 } // end loop over collections
364
365
366 // Execution completed.
367 ATH_MSG_DEBUG( "TileDigitsToTTL1 execution completed." );
368 ATH_MSG_DEBUG( " nTTTot=" << nTTTot
369 << " nDigitTot=" << nDigitTot
370 << " nIgnoreTot=" << nIgnoreTot
371 << " ttAmpTot=" << ttAmpTot
372 << " ttAmpTotIg=" << ttAmpTotIg
373 << " =>eneTot=" << ttAmpTot + ttAmpTotIg );
374
375 return StatusCode::SUCCESS;
376}
377
379
380 ATH_MSG_INFO( "TileDigitsToTTL1::finalize() end" );
381
382 return StatusCode::SUCCESS;
383}
384
#define endmsg
#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.
#define CHECK(...)
Evaluate an expression and check for errors.
Handle class for reading from StoreGate.
Handle class for recording to StoreGate.
AthAlgorithm(const std::string &name, ISvcLocator *pSvcLocator)
Constructor with parameters:
const ServiceHandle< StoreGateSvc > & detStore() const
bool msgLvl(const MSG::Level lvl) const
MsgStream & msg() const
bool is_valid() const
Check if id is in a valid state.
virtual bool isValid() override final
Can the handle be successfully dereferenced?
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
static unsigned int getDrawerIdx(unsigned int ros, unsigned int drawer)
Returns a drawer hash.
const TileHWID * m_tileHWID
TileDigitsToTTL1(const std::string &name, ISvcLocator *pSvcLocator)
virtual StatusCode finalize() override
virtual StatusCode execute() override
ToolHandle< TileCondToolEmscale > m_tileToolEmscale
StringProperty m_infoName
SG::ReadHandleKey< TileDigitsContainer > m_digitsContainerKey
const CaloLVL1_ID * m_TT_ID
const TileID * m_tileID
virtual StatusCode initialize() override
const TileInfo * m_tileInfo
SG::WriteHandleKey< TileTTL1Container > m_ttl1ContainerKey
@ BARREL_POS
Definition TileHWID.h:68
@ EXTBAR_NEG
Definition TileHWID.h:71
@ BARREL_NEG
Definition TileHWID.h:69
@ EXTBAR_POS
Definition TileHWID.h:70