Line data Source code
1 : /**************************************************************************
2 : * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3 : * *
4 : * Author: The ALICE Off-line Project. *
5 : * Contributors are mentioned in the code where appropriate. *
6 : * *
7 : * Permission to use, copy, modify and distribute this software and its *
8 : * documentation strictly for non-commercial purposes is hereby granted *
9 : * without fee, provided that the above copyright notice appears in all *
10 : * copies and that both the copyright notice and this permission notice *
11 : * appear in the supporting documentation. The authors make no claims *
12 : * about the suitability of this software for any purpose. It is *
13 : * provided "as is" without express or implied warranty. *
14 : **************************************************************************/
15 :
16 : /*
17 :
18 :
19 : EMCal trigger electronics manager L0/L1
20 : can handle both simulated digits and raw data
21 : Author: R. GUERNANE LPSC Grenoble CNRS/IN2P3
22 : */
23 :
24 : #include "AliEMCALTriggerElectronics.h"
25 : #include "AliEMCALTriggerTRU.h"
26 : #include "AliEMCALTriggerSTU.h"
27 : #include "AliEMCALGeometry.h"
28 : #include "AliRunLoader.h"
29 : #include "AliEMCAL.h"
30 : #include "AliRun.h"
31 : #include "AliEMCALTriggerDCSConfig.h"
32 : #include "AliEMCALTriggerData.h"
33 : #include "AliEMCALDigit.h"
34 : #include "AliCaloRawStreamV3.h"
35 : #include "AliEMCALTriggerSTURawStream.h"
36 : #include "AliEMCALDigit.h"
37 : #include "AliEMCALTriggerRawDigit.h"
38 : #include "AliEMCALTriggerPatch.h"
39 : #include "AliEMCALTriggerSTUDCSConfig.h"
40 :
41 : #include <TVector2.h>
42 :
43 : namespace
44 : {
45 : const Int_t kNTRU = 30; // TODO: kNTRU should be set to / replaced by fGeometry->GetNTotalTRU() (total number of TRU for a given geom) after adding 1 STU for DCAL
46 : }
47 :
48 42 : ClassImp(AliEMCALTriggerElectronics)
49 :
50 : //__________________
51 2 : AliEMCALTriggerElectronics::AliEMCALTriggerElectronics(const AliEMCALTriggerDCSConfig *dcsConf) : TObject(),
52 6 : fTRU(new TClonesArray("AliEMCALTriggerTRU",52)),
53 2 : fSTU(0x0),
54 2 : fGeometry(0)
55 10 : {
56 : // Ctor
57 :
58 2 : TVector2 rSize;
59 :
60 2 : rSize.Set( 24., 4. );
61 :
62 2 : AliRunLoader *rl = AliRunLoader::Instance();
63 7 : if (rl->GetAliRun() && rl->GetAliRun()->GetDetector("EMCAL")) {
64 5 : AliEMCAL *emcal = dynamic_cast<AliEMCAL*>(rl->GetAliRun()->GetDetector("EMCAL"));
65 3 : if (emcal) fGeometry = emcal->GetGeometry();
66 1 : }
67 :
68 2 : if (!fGeometry) {
69 2 : fGeometry = AliEMCALGeometry::GetInstance(AliEMCALGeometry::GetDefaultGeometryName());
70 2 : AliError("Cannot access geometry, create a new default one!");
71 : }
72 :
73 : // 32 TRUs
74 124 : for (Int_t i = 0; i < kNTRU; i++) {
75 120 : if(i>=(fGeometry->GetNTotalTRU())) continue; // i <= kNTRU < 62. Prevents fTRU to go out of bonds with EMCALFirstYEARV1 of EMCALCompleteV1 (NTRU<32) TODO: fix the logic
76 120 : AliEMCALTriggerTRUDCSConfig *truConf = dcsConf->GetTRUDCSConfig(fGeometry->GetOnlineIndexFromTRUIndex(i));
77 240 : if (truConf) new ((*fTRU)[i]) AliEMCALTriggerTRU(truConf, rSize, i % 2);
78 60 : }
79 :
80 2 : rSize.Set( 48., 64. );
81 :
82 : // 1 STU
83 2 : AliEMCALTriggerSTUDCSConfig* stuConf = dcsConf->GetSTUDCSConfig();
84 6 : fSTU = new AliEMCALTriggerSTU(stuConf, rSize);
85 :
86 2 : TString str = "map";
87 124 : for (Int_t i = 0; i < kNTRU; i++) {
88 120 : AliEMCALTriggerTRU *iTRU = static_cast<AliEMCALTriggerTRU*>(fTRU->At(i));
89 60 : if (!iTRU) continue;
90 :
91 120 : fSTU->Build(str,
92 : i,
93 60 : iTRU->Map(),
94 60 : iTRU->RegionSize()
95 : );
96 60 : }
97 4 : }
98 :
99 : //________________
100 : AliEMCALTriggerElectronics::~AliEMCALTriggerElectronics()
101 12 : {
102 : // Dtor
103 :
104 2 : fTRU->Delete();
105 4 : delete fSTU;
106 6 : }
107 :
108 : //__________________
109 : void AliEMCALTriggerElectronics::Digits2Trigger(TClonesArray* digits, const Int_t V0M[], AliEMCALTriggerData* data)
110 : {
111 : // Digits to trigger
112 :
113 16 : Int_t pos, px, py, id;
114 :
115 8 : Int_t region[48][64], posMap[48][64];
116 50704 : for (Int_t i = 0; i < 48; i++) for (Int_t j = 0; j < 64; j++)
117 : {
118 24576 : region[i][j] = 0;
119 24576 : posMap[i][j] = -1;
120 : }
121 :
122 84 : for (Int_t i = 0; i < digits->GetEntriesFast(); i++)
123 : {
124 34 : AliEMCALTriggerRawDigit* digit = (AliEMCALTriggerRawDigit*)digits->At(i);
125 :
126 34 : id = digit->GetId();
127 :
128 34 : Int_t iTRU, iADC;
129 :
130 34 : Bool_t isOK1 = fGeometry->GetTRUFromAbsFastORIndex(id, iTRU, iADC);
131 :
132 36 : if (!isOK1 || iTRU > kNTRU-1) continue;
133 :
134 2112 : for (Int_t j = 0; j < digit->GetNSamples(); j++)
135 : {
136 1024 : Int_t time, amp;
137 1024 : Bool_t isOK2 = digit->GetTimeSample(j, time, amp);
138 :
139 2048 : if (isOK1 && isOK2 && amp) {
140 687 : AliDebug(999, Form("=== TRU# %2d ADC# %2d time# %2d signal %d ===", iTRU, iADC, time, amp));
141 :
142 229 : AliEMCALTriggerTRU * etr = (static_cast<AliEMCALTriggerTRU*>(fTRU->At(iTRU)));
143 229 : if (etr) {
144 458 : if (data->GetMode())
145 229 : etr->SetADC(iADC, time, 4 * amp);
146 : else
147 229 : etr->SetADC(iADC, time, amp);
148 : }
149 229 : }
150 1024 : }
151 :
152 64 : if (fGeometry->GetPositionInEMCALFromAbsFastORIndex(id, px, py)) posMap[px][py] = i;
153 66 : }
154 :
155 : Int_t iL0 = 0;
156 :
157 8 : Int_t timeL0[kNTRU] = {0}, timeL0min = 999;
158 :
159 496 : for (Int_t i = 0; i < kNTRU; i++)
160 : {
161 240 : AliEMCALTriggerTRU *iTRU = static_cast<AliEMCALTriggerTRU*>(fTRU->At(i));
162 240 : if (!iTRU) continue;
163 :
164 720 : AliDebug(999, Form("===========< TRU %2d >============", i));
165 :
166 240 : if (iTRU->L0()) // L0 recomputation: *ALWAYS* done from FALTRO
167 : {
168 14 : iL0++;
169 :
170 14 : timeL0[i] = iTRU->GetL0Time();
171 :
172 14 : if (!timeL0[i]) AliWarning(Form("TRU# %d has 0 trigger time",i));
173 :
174 21 : if (timeL0[i] < timeL0min) timeL0min = timeL0[i];
175 :
176 14 : data->SetL0Trigger(0, i, 1); // TRU# i has issued a L0
177 14 : }
178 : else
179 226 : data->SetL0Trigger(0, i, 0);
180 240 : }
181 :
182 24 : AliDebug(999, Form("=== %2d TRU (out of %2d) has issued a L0 / Min L0 time: %d", iL0, fTRU->GetEntriesFast(), timeL0min));
183 :
184 : AliEMCALTriggerRawDigit* dig = 0x0;
185 :
186 12 : if (iL0 && (!data->GetMode() || !fSTU->GetDCSConfig()->GetRawData()))
187 : {
188 : // Update digits after L0 calculation
189 248 : for (Int_t i = 0; i < kNTRU; i++)
190 : {
191 120 : AliEMCALTriggerTRU *iTRU = static_cast<AliEMCALTriggerTRU*>(fTRU->At(i));
192 120 : if (!iTRU) continue;
193 :
194 120 : Int_t reg[24][4];
195 34800 : for (int j = 0; j < 24; j++) for (int k = 0; k < 4; k++) reg[j][k] = 0;
196 :
197 120 : iTRU->GetL0Region(timeL0min, reg);
198 :
199 6000 : for (int j = 0; j < iTRU->RegionSize()->X(); j++)
200 : {
201 28800 : for (int k = 0; k < iTRU->RegionSize()->Y(); k++)
202 : {
203 11538 : if (reg[j][k]
204 11520 : &&
205 30 : fGeometry->GetAbsFastORIndexFromPositionInTRU(i, j, k, id)
206 30 : &&
207 18 : fGeometry->GetPositionInEMCALFromAbsFastORIndex(id, px, py))
208 : {
209 18 : pos = posMap[px][py];
210 :
211 18 : if (pos == -1)
212 : {
213 : // Add a new digit
214 18 : posMap[px][py] = digits->GetEntriesFast();
215 :
216 18 : new((*digits)[digits->GetEntriesFast()]) AliEMCALTriggerRawDigit(id, 0x0, 0);
217 :
218 18 : dig = (AliEMCALTriggerRawDigit*)digits->At(digits->GetEntriesFast() - 1);
219 18 : }
220 : else
221 : {
222 0 : dig = (AliEMCALTriggerRawDigit*)digits->At(pos);
223 : }
224 :
225 : // 14b to 12b STU time sums
226 18 : reg[j][k] >>= 2;
227 :
228 18 : dig->SetL1TimeSum(reg[j][k]);
229 18 : }
230 : }
231 : }
232 120 : }
233 4 : }
234 :
235 12 : if (iL0 && !data->GetMode())
236 : {
237 248 : for (Int_t i = 0; i < kNTRU; i++)
238 : {
239 120 : AliEMCALTriggerTRU *iTRU = static_cast<AliEMCALTriggerTRU*>(fTRU->At(i));
240 120 : if (!iTRU) continue;
241 :
242 360 : AliDebug(999, Form("=== TRU# %2d found %d patches", i, (iTRU->Patches()).GetEntriesFast()));
243 :
244 120 : TIter next(&iTRU->Patches());
245 608 : while (AliEMCALTriggerPatch* p = (AliEMCALTriggerPatch*)next())
246 : {
247 64 : p->Position(px, py);
248 :
249 : // Local 2 Global
250 98 : if (fGeometry->GetAbsFastORIndexFromPositionInTRU(i, px, py, id)
251 64 : &&
252 68 : fGeometry->GetPositionInEMCALFromAbsFastORIndex(id, px, py)) p->SetPosition(px, py);
253 :
254 256 : if (AliDebugLevel()) p->Print("");
255 :
256 64 : Int_t peaks = p->Peaks();
257 :
258 192 : Int_t sizeX = (Int_t) ((iTRU->PatchSize())->X() * (iTRU->SubRegionSize())->X());
259 192 : Int_t sizeY = (Int_t) ((iTRU->PatchSize())->Y() * (iTRU->SubRegionSize())->Y());
260 :
261 640 : for (Int_t j = 0; j < sizeX * sizeY; j++)
262 : {
263 256 : if (peaks & (1 << j))
264 : {
265 75 : pos = posMap[px + j % sizeX][py + j / sizeX];
266 :
267 75 : if (pos == -1) {
268 : // Add a new digit
269 18 : posMap[px + j % sizeX][py + j / sizeX] = digits->GetEntriesFast();
270 :
271 36 : new((*digits)[digits->GetEntriesFast()]) AliEMCALTriggerRawDigit(id, 0x0, 0);
272 :
273 27 : dig = (AliEMCALTriggerRawDigit*)digits->At(digits->GetEntriesFast() - 1);
274 9 : } else {
275 132 : dig = (AliEMCALTriggerRawDigit*)digits->At(pos);
276 : }
277 :
278 252 : if (dig) dig->SetL0Time(p->Time());
279 : }
280 : }
281 :
282 64 : pos = posMap[px][py];
283 :
284 64 : if (pos == -1) {
285 : // Add a new digit
286 80 : posMap[px][py] = digits->GetEntriesFast();
287 :
288 160 : new((*digits)[digits->GetEntriesFast()]) AliEMCALTriggerRawDigit(id, 0x0, 0);
289 :
290 120 : dig = (AliEMCALTriggerRawDigit*)digits->At(digits->GetEntriesFast() - 1);
291 :
292 40 : }
293 : else
294 : {
295 48 : dig = (AliEMCALTriggerRawDigit*)digits->At(pos);
296 : }
297 :
298 128 : if (dig) dig->SetTriggerBit(kL0, 0);
299 64 : }
300 120 : }
301 4 : }
302 :
303 : // Prepare STU for L1 calculation
304 784 : for (int i = 0; i < (fSTU->RegionSize())->X(); i++) {
305 49920 : for (int j = 0; j < (fSTU->RegionSize())->Y(); j++) {
306 :
307 24576 : pos = posMap[i][j];
308 :
309 24576 : if (pos >= 0) {
310 :
311 99 : AliEMCALTriggerRawDigit *digit = (AliEMCALTriggerRawDigit*)digits->At(pos);
312 :
313 216 : if (digit && digit->GetL1TimeSum() > -1) region[i][j] = digit->GetL1TimeSum();
314 99 : }
315 : }
316 : }
317 :
318 24 : AliDebug(999,"==================== STU ====================");
319 24 : if (AliDebugLevel() >= 999) fSTU->Scan();
320 24 : AliDebug(999,"==============================================");
321 :
322 8 : fSTU->SetRegion(region);
323 :
324 8 : if (data->GetMode())
325 : {
326 24 : for (int ithr = 0; ithr < 2; ithr++) {
327 24 : AliDebug(999, Form(" THR %d / EGA %d / EJE %d", ithr, data->GetL1GammaThreshold(ithr), data->GetL1JetThreshold(ithr)));
328 :
329 8 : fSTU->SetThreshold(kL1GammaHigh + ithr, data->GetL1GammaThreshold(ithr));
330 8 : fSTU->SetThreshold(kL1JetHigh + ithr, data->GetL1JetThreshold( ithr));
331 : }
332 4 : }
333 : else
334 : {
335 24 : for (int ithr = 0; ithr < 2; ithr++) {
336 : //
337 8 : fSTU->ComputeThFromV0(kL1GammaHigh + ithr, V0M);
338 8 : data->SetL1GammaThreshold(ithr, fSTU->GetThreshold(kL1GammaHigh + ithr));
339 :
340 8 : fSTU->ComputeThFromV0(kL1JetHigh + ithr, V0M);
341 8 : data->SetL1JetThreshold(ithr, fSTU->GetThreshold(kL1JetHigh + ithr) );
342 :
343 24 : AliDebug(999, Form("STU THR %d EGA %d EJE %d", ithr, fSTU->GetThreshold(kL1GammaHigh + ithr), fSTU->GetThreshold(kL1JetHigh + ithr)));
344 : }
345 : }
346 :
347 48 : for (int ithr = 0; ithr < 2; ithr++) {
348 : //
349 16 : fSTU->Reset();
350 :
351 16 : fSTU->L1(kL1GammaHigh + ithr);
352 :
353 : TIterator* nP = 0x0;
354 :
355 16 : nP = (fSTU->Patches()).MakeIterator();
356 :
357 48 : AliDebug(999, Form("=== STU found %d gamma patches", (fSTU->Patches()).GetEntriesFast()));
358 :
359 136 : while (AliEMCALTriggerPatch* p = (AliEMCALTriggerPatch*)nP->Next())
360 : {
361 104 : p->Position(px, py);
362 :
363 312 : if (AliDebugLevel()) p->Print("");
364 :
365 104 : if (fGeometry->GetAbsFastORIndexFromPositionInEMCAL(px, py, id))
366 : {
367 104 : if (posMap[px][py] == -1)
368 : {
369 17 : posMap[px][py] = digits->GetEntriesFast();
370 :
371 : // Add a new digit
372 17 : new((*digits)[digits->GetEntriesFast()]) AliEMCALTriggerRawDigit(id, 0x0, 0);
373 :
374 17 : dig = (AliEMCALTriggerRawDigit*)digits->At(digits->GetEntriesFast() - 1);
375 17 : }
376 : else
377 : {
378 87 : dig = (AliEMCALTriggerRawDigit*)digits->At(posMap[px][py]);
379 : }
380 :
381 312 : if (AliDebugLevel()) dig->Print("");
382 :
383 208 : if (dig) dig->SetTriggerBit(kL1GammaHigh + ithr, 0);
384 : }
385 104 : }
386 :
387 16 : fSTU->Reset();
388 :
389 16 : fSTU->L1(kL1JetHigh + ithr);
390 :
391 16 : nP = (fSTU->Patches()).MakeIterator();
392 :
393 48 : AliDebug(999, Form("=== STU found %d jet patches", (fSTU->Patches()).GetEntriesFast()));
394 :
395 96 : while (AliEMCALTriggerPatch* p = (AliEMCALTriggerPatch*)nP->Next())
396 : {
397 64 : p->Position(px, py);
398 :
399 192 : if (AliDebugLevel()) p->Print("");
400 :
401 64 : if (fGeometry->GetAbsFastORIndexFromPositionInEMCAL(px, py, id))
402 : {
403 64 : if (posMap[px][py] == -1)
404 : {
405 24 : posMap[px][py] = digits->GetEntriesFast();
406 :
407 : // Add a new digit
408 24 : new((*digits)[digits->GetEntriesFast()]) AliEMCALTriggerRawDigit(id, 0x0, 0);
409 :
410 24 : dig = (AliEMCALTriggerRawDigit*)digits->At(digits->GetEntriesFast() - 1);
411 24 : }
412 : else
413 : {
414 40 : dig = (AliEMCALTriggerRawDigit*)digits->At(posMap[px][py]);
415 : }
416 :
417 192 : if (AliDebugLevel()) dig->Print("");
418 :
419 128 : if (dig) dig->SetTriggerBit(kL1JetHigh + ithr, 0);
420 : }
421 64 : }
422 : }
423 :
424 : // Now reset the electronics for a fresh start with next event
425 8 : Reset();
426 8 : }
427 :
428 : //__________________
429 : void AliEMCALTriggerElectronics::Reset()
430 : {
431 : // Reset
432 :
433 16 : TIter nextTRU(fTRU);
434 992 : while ( AliEMCALTriggerTRU *TRU = (AliEMCALTriggerTRU*)nextTRU() ) TRU->Reset();
435 :
436 8 : fSTU->Reset();
437 8 : }
|