]> git.uio.no Git - u/mrichter/AliRoot.git/blob - PWG/EMCAL/AliEmcalTriggerMaker.cxx
Merge remote-tracking branch 'origin/flatdev' into mergeFlat2Master
[u/mrichter/AliRoot.git] / PWG / EMCAL / AliEmcalTriggerMaker.cxx
1 // $Id: AliEmcalTriggerMaker.cxx 64593 2013-10-18 10:23:58Z loizides $
2 //
3 // Class to make emcal particles in AOD/ESD events.
4 //
5 // Author: J.Kral
6
7 #include <TClonesArray.h>
8 #include <iostream>
9
10 #include "AliLog.h"
11 #include "AliEmcalTriggerPatchInfo.h"
12 #include "AliEmcalTriggerSetupInfo.h"
13
14 #include "AliEmcalTriggerMaker.h"
15 #include "AliEMCALTriggerTypes.h"
16 #include "AliEMCALGeometry.h"
17
18 #include "AliVCaloTrigger.h"
19 #include "AliAODCaloTrigger.h"
20 #include "AliVCaloCells.h"
21 #include "AliVVZERO.h"
22
23 ClassImp(AliEmcalTriggerMaker)
24
25 using namespace std;
26
27 //________________________________________________________________________
28 AliEmcalTriggerMaker::AliEmcalTriggerMaker() : 
29   AliAnalysisTaskEmcal("AliEmcalTriggerMaker",kFALSE),
30   fCaloTriggersOutName("EmcalTriggers"),
31   fCaloTriggerSetupOutName("EmcalTriggersSetup"),
32   fV0InName("AliAODVZERO"),
33   fCaloTriggersOut(0),
34   fCaloTriggerSetupOut(0),
35   fSimpleOfflineTriggers(0),
36   fV0(0),
37   fITrigger(0)
38 {
39   // Constructor.
40   for( int i = 0; i < 4; i++ )
41     for( int j = 0; j < 3; j++ )
42       fThresholdConstants[i][j] = 0;
43 }
44
45 //________________________________________________________________________
46 AliEmcalTriggerMaker::AliEmcalTriggerMaker(const char *name) : 
47   AliAnalysisTaskEmcal(name,kFALSE),
48   fCaloTriggersOutName("EmcalTriggers"),
49   fCaloTriggerSetupOutName("EmcalTriggersSetup"),
50   fV0InName("AliAODVZERO"),
51   fCaloTriggersOut(0),
52   fCaloTriggerSetupOut(0),
53   fSimpleOfflineTriggers(0),
54   fV0(0),
55   fITrigger(0)
56 {
57   // Constructor.
58   for( int i = 0; i < 4; i++ )
59     for( int j = 0; j < 3; j++ )
60       fThresholdConstants[i][j] = 0;
61 }
62
63 //________________________________________________________________________
64 AliEmcalTriggerMaker::~AliEmcalTriggerMaker()
65 {
66   // Destructor.
67 }
68
69 //________________________________________________________________________
70 void AliEmcalTriggerMaker::ExecOnce()
71 {
72   // Init the analysis.
73
74   AliAnalysisTaskEmcal::ExecOnce();
75
76   if (!fInitialized)
77     return;
78
79   if (!fCaloTriggersOutName.IsNull()) {
80     fCaloTriggersOut = new TClonesArray("AliEmcalTriggerPatchInfo");
81     fCaloTriggersOut->SetName(fCaloTriggersOutName);
82
83     if (!(InputEvent()->FindListObject(fCaloTriggersOutName))) {
84       InputEvent()->AddObject(fCaloTriggersOut);
85     }
86     else {
87       fInitialized = kFALSE;
88       AliFatal(Form("%s: Container with same name %s already present. Aborting", GetName(), fCaloTriggersOutName.Data()));
89       return;
90     }
91   }
92
93   if (!fCaloTriggerSetupOutName.IsNull()) {
94     fCaloTriggerSetupOut = new AliEmcalTriggerSetupInfo();
95     fCaloTriggerSetupOut->SetName(fCaloTriggerSetupOutName);
96
97     if (!(InputEvent()->FindListObject(fCaloTriggerSetupOutName))) {
98       InputEvent()->AddObject(fCaloTriggerSetupOut);
99     }
100     else {
101       fInitialized = kFALSE;
102       AliFatal(Form("%s: Container with same name %s already present. Aborting", GetName(), fCaloTriggerSetupOutName.Data()));
103       return;
104     }
105   }
106
107   if ( ! fV0InName.IsNull()) {
108     fV0 = (AliVVZERO*)InputEvent()->FindListObject( fV0InName );
109   }
110
111   // container for simple offline trigger processing
112   fSimpleOfflineTriggers = new AliAODCaloTrigger();
113   fSimpleOfflineTriggers->Allocate( 0 );
114 }
115
116 //________________________________________________________________________
117 Bool_t AliEmcalTriggerMaker::Run() 
118 {
119   // Create the emcal particles
120
121   Short_t cellId;
122   Int_t globCol, globRow, v0[2];
123   Int_t absId, adcAmp, tBits;
124   Int_t i, j, nCell, iCell;
125   Double_t amp;
126   ULong64_t v0S, thresh;
127   Bool_t isOfflineSimple;
128   
129   AliEmcalTriggerPatchInfo *trigger, *triggerMainJet, *triggerMainGamma;
130   AliEmcalTriggerPatchInfo *triggerMainJetSimple, *triggerMainGammaSimple;
131
132   // delete patch array, clear setup object
133   fCaloTriggersOut->Delete();
134   fCaloTriggerSetupOut->Clean();
135
136   if( !fCaloTriggers ){
137     AliError(Form("Calo triggers container %s not available.", fCaloTriggersName.Data()));
138     return kTRUE;
139   }
140   if( !fCaloCells ){
141     AliError(Form("Calo cells container %s not available.", fCaloCellsName.Data()));
142     return kTRUE;
143   }
144   if( !fCaloCells ){
145     AliError(Form("V0 container %s not available.", fV0InName.Data()));
146     return kTRUE;
147   }
148   
149   // do not process, if sooner than 11h period
150   // 160683 ??
151   if( InputEvent()->GetRunNumber() < 167693 )
152     return kTRUE;
153  
154 //   // do not process any MC, since no MC was generated with correct
155 //   // EMCal trigger L1 jet trigger simulation, yet
156 //   // productions will be enabled, once some correct once are produced
157 //   if( MCEvent() != 0 )
158 //     return kTRUE;
159   
160   // must reset before usage, or the class will fail 
161   fCaloTriggers->Reset();
162
163         // first run over the patch array to compose a map of 2x2 patch energies
164   // which is then needed to construct the full patch ADC energy
165   // class is not empty
166   if( fCaloTriggers->GetEntries() > 0 ){
167                 
168                 // zero the array
169                 for( i = 0; i < 48; i++ )
170                         for( j = 0; j < 64; j++ )
171                                 fPatchADC[i][j] = 0;
172                 
173     // go throuth the trigger channels
174     while( fCaloTriggers->Next() ){
175       // get position in global 2x2 tower coordinates
176       // A0 left bottom (0,0)
177       fCaloTriggers->GetPosition( globCol, globRow );
178
179       // for some strange reason some ADC amps are initialized in reconstruction
180       // as -1, neglect those :\\ wth
181       fCaloTriggers->GetL1TimeSum( adcAmp );
182                         if( adcAmp > -1 )
183                                 fPatchADC[globCol][globRow] = adcAmp;
184       
185                 } // patches
186         } // array not empty
187   
188   // fill the array for offline trigger processing
189   // using calibrated cell energies
190   for( i = 0; i < 48; i++ )
191     for( j = 0; j < 64; j++ )
192       fPatchADCSimple[i][j] = 0;
193
194   // fill the patch ADCs from cells
195   nCell = fCaloCells->GetNumberOfCells();
196   
197   for( iCell = 0; iCell < nCell; iCell++ ){
198     // get the cell info, based in index in array
199     cellId = fCaloCells->GetCellNumber( iCell );
200     amp = fCaloCells->GetAmplitude( iCell );
201     
202     // get position
203     fGeom->GetFastORIndexFromCellIndex( cellId, absId );
204     fGeom->GetPositionInEMCALFromAbsFastORIndex( absId, globCol, globRow );
205     
206     // add
207     fPatchADCSimple[globCol][globRow] += amp/kEMCL1ADCtoGeV;
208   }
209
210   // dig out common data (thresholds)
211   // 0 - jet high, 1 - gamma high, 2 - jet low, 3 - gamma low
212   fCaloTriggerSetupOut->SetThresholds( fCaloTriggers->GetL1Threshold( 0 ),
213                                        fCaloTriggers->GetL1Threshold( 1 ),
214                                        fCaloTriggers->GetL1Threshold( 2 ),
215                                        fCaloTriggers->GetL1Threshold( 3 ));
216
217   // get the V0 value and compute and set the offline thresholds
218   // get V0, compute thresholds and save them as global parameters
219   v0[0] = fV0->GetTriggerChargeA();
220   v0[1] = fV0->GetTriggerChargeC();
221   v0S = v0[0] + v0[1];
222   
223   fSimpleOfflineTriggers->SetL1V0( v0 );
224   
225   for( i = 0; i < 4; i++ ){
226     // A*V0^2/2^32+B*V0/2^16+C
227     thresh = ( ((ULong64_t)fThresholdConstants[i][0]) * v0S * v0S ) >> 32;
228     thresh += ( ((ULong64_t)fThresholdConstants[i][1]) * v0S ) >> 16;
229     thresh += ((ULong64_t)fThresholdConstants[i][2]);
230     fSimpleOfflineTriggers->SetL1Threshold( i, thresh );
231   }
232   
233   // save the thresholds in output object
234   fCaloTriggerSetupOut->SetThresholdsSimple( fSimpleOfflineTriggers->GetL1Threshold( 0 ),
235                                        fSimpleOfflineTriggers->GetL1Threshold( 1 ),
236                                        fSimpleOfflineTriggers->GetL1Threshold( 2 ),
237                                        fSimpleOfflineTriggers->GetL1Threshold( 3 ));
238   
239   // run the trigger
240   RunSimpleOfflineTrigger();
241
242   // reset for re-run
243   fCaloTriggers->Reset();
244   fSimpleOfflineTriggers->Reset();
245
246   // class is not empty
247   if( fCaloTriggers->GetEntries() > 0 ||  fSimpleOfflineTriggers->GetEntries() > 0 ){
248  
249     fITrigger = 0;
250                 triggerMainGamma = 0;
251                 triggerMainJet = 0;
252                 triggerMainGammaSimple = 0;
253                 triggerMainJetSimple = 0;
254
255     // go throuth the trigger channels, real first, then offline
256     while( NextTrigger( isOfflineSimple ) ){
257       
258                         // process jet
259                         trigger = ProcessPatch( 0, isOfflineSimple );
260                         
261                         // save main jet triggers in event
262                         if( trigger != 0 ){
263                                 // check if more energetic than others for main patch marking
264                                 if( ! isOfflineSimple ){
265                                         if( triggerMainJet == 0 )
266                                                 triggerMainJet = trigger;
267                                         else if( triggerMainJet->GetPatchE() < trigger->GetPatchE() )
268                                                 triggerMainJet = trigger;
269                                 }
270                                 else{
271                                         if( triggerMainJetSimple == 0 )
272                                                 triggerMainJetSimple = trigger;
273                                         else if( triggerMainJetSimple->GetPatchE() < trigger->GetPatchE() )
274                                                 triggerMainJetSimple = trigger;
275                                 }
276                         }
277       
278                         // process gamma
279                         trigger = ProcessPatch( 1, isOfflineSimple );
280                         
281                         // save main gamma triggers in event
282                         if( trigger != 0 ){
283                                 // check if more energetic than others for main patch marking
284                                 if( ! isOfflineSimple ){
285                                         if( triggerMainGamma == 0 )
286                                                 triggerMainGamma = trigger;
287                                         else if( triggerMainGamma->GetPatchE() < trigger->GetPatchE() )
288                                                 triggerMainGamma = trigger;
289                                 }
290                                 else{
291                                         if( triggerMainGammaSimple == 0 )
292                                                 triggerMainGammaSimple = trigger;
293                                         else if( triggerMainGammaSimple->GetPatchE() < trigger->GetPatchE() )
294                                                 triggerMainGammaSimple = trigger;
295                                 }
296                         }
297
298 //       cout << " pi:" << trigger->GetPhiMin() << " px:" << trigger->GetPhiMax();
299 //       cout << " pg:" << trigger->GetPhiGeo() << " " << (trigger->GetPhiMin()+trigger->GetPhiMax()) / 2.;
300 //       cout << " pc:" << trigger->GetPhiCM();
301 //       cout << " ei:" << trigger->GetEtaMin() << " ex:" << trigger->GetEtaMax();
302 //       cout << " eg:" << trigger->GetEtaGeo() << " " << (trigger->GetEtaMin()+trigger->GetEtaMax()) / 2.;
303 //       cout << " ec:" << trigger->GetEtaCM();
304 //       cout << " e:" << trigger->GetPatchE();
305 //       cout << " jl:" << trigger->IsJetLow() << " jh:" << trigger->IsJetHigh() << endl;
306       
307     } // triggers
308     
309     // mark the most energetic patch as main
310     // for real and also simple offline
311     if( triggerMainJet != 0 ){
312       tBits = triggerMainJet->GetTriggerBits();
313       // main trigger flag
314       tBits = tBits | ( 1 << 24 );
315       triggerMainJet->SetTriggerBits( tBits );
316     }
317     if( triggerMainJetSimple != 0 ){
318       tBits = triggerMainJetSimple->GetTriggerBits();
319       // main trigger flag
320       tBits = tBits | ( 1 << 24 );
321       triggerMainJetSimple->SetTriggerBits( tBits );
322     }
323     if( triggerMainGamma != 0 ){
324       tBits = triggerMainGamma->GetTriggerBits();
325       // main trigger flag
326       tBits = tBits | ( 1 << 24 );
327       triggerMainGamma->SetTriggerBits( tBits );
328     }
329     if( triggerMainGammaSimple != 0 ){
330       tBits = triggerMainGammaSimple->GetTriggerBits();
331       // main trigger flag
332       tBits = tBits | ( 1 << 24 );
333       triggerMainGammaSimple->SetTriggerBits( tBits );
334     }
335     
336   } // there are some triggers
337
338   return kTRUE;
339 }
340
341 //________________________________________________________________________
342 AliEmcalTriggerPatchInfo* AliEmcalTriggerMaker::ProcessPatch( Int_t type, Bool_t isOfflineSimple ){
343
344         
345   Int_t globCol, globRow, tBits, cellAbsId[4];
346   Int_t absId, adcAmp;
347   Int_t i, j, k, cmCol, cmRow, cmiCellCol, cmiCellRow;
348   Double_t amp, ca, cmiCol, cmiRow;
349   
350   TVector3 centerGeo, center1, center2, centerMass, edge1, edge2, vertex, cellCoor;
351   
352   AliEmcalTriggerPatchInfo *trigger;
353
354         // check if jet trigger low or high
355         if( ! isOfflineSimple )
356                 fCaloTriggers->GetTriggerBits( tBits );
357         else
358                 fSimpleOfflineTriggers->GetTriggerBits( tBits );
359         
360         if(( type == 0 && ! IsEJE( tBits )) || ( type == 1 && ! IsEGA( tBits )))
361                 return 0;
362         
363         // save primary vertex in vector
364         vertex.SetXYZ( fVertex[0], fVertex[1], fVertex[2] );
365
366         // get position in global 2x2 tower coordinates
367         // A0 left bottom (0,0)
368         if( ! isOfflineSimple )
369                 fCaloTriggers->GetPosition( globCol, globRow );
370         else
371                 fSimpleOfflineTriggers->GetPosition( globCol, globRow );
372
373         // get the absolute trigger ID
374         fGeom->GetAbsFastORIndexFromPositionInEMCAL( globCol, globRow, absId );
375         // convert to the 4 absId of the cells composing the trigger channel
376         fGeom->GetCellIndexFromFastORIndex( absId, cellAbsId );
377         
378         // get low left edge (eta max, phi min)
379         fGeom->GetGlobal( cellAbsId[0], edge1 );
380         
381         // sum the available energy in the 32/32 window of cells
382         // step over trigger channels and get all the corresponding cells
383         // make CM
384         amp = 0;
385         cmiCol = 0;
386         cmiRow = 0;
387         adcAmp = 0;
388         if( IsEJE( tBits ) && type == 0 ){
389                 for( i = 0; i < 16; i++ ){
390                         for( j = 0; j < 16; j++ ){
391                                 // get the 4 cells composing the trigger channel
392                                 fGeom->GetAbsFastORIndexFromPositionInEMCAL( globCol+i, globRow+j, absId );
393                                 fGeom->GetCellIndexFromFastORIndex( absId, cellAbsId );
394                                 // add amplitudes and find patch edges
395                                 for( k = 0; k < 4; k++ ){
396                                         ca = fCaloCells->GetCellAmplitude( cellAbsId[k] );
397                                         fGeom->GetGlobal( cellAbsId[k], cellCoor );
398                                         amp += ca;
399                                         cmiCol += ca*(Double_t)i;
400                                         cmiRow += ca*(Double_t)j;
401                                 }
402                                 // add the STU ADCs in the patch
403                                 if( ! isOfflineSimple )
404                                         adcAmp += fPatchADC[globCol+i][globRow+j];
405                                 else
406                                         adcAmp += fPatchADCSimple[globCol+i][globRow+j];
407                         }
408                 } // 32x32 cell window
409         }
410         
411         if( IsEGA( tBits ) && type == 1 ){
412                 for( i = 0; i < 2; i++ ){
413                         for( j = 0; j < 2; j++ ){
414                                 // get the 4 cells composing the trigger channel
415                                 fGeom->GetAbsFastORIndexFromPositionInEMCAL( globCol+i, globRow+j, absId );
416                                 fGeom->GetCellIndexFromFastORIndex( absId, cellAbsId );
417                                 // add amplitudes and find patch edges
418                                 for( k = 0; k < 4; k++ ){
419                                         ca = fCaloCells->GetCellAmplitude( cellAbsId[k] );
420                                         fGeom->GetGlobal( cellAbsId[k], cellCoor );
421                                         amp += ca;
422                                         cmiCol += ca*(Double_t)i;
423                                         cmiRow += ca*(Double_t)j;
424                                 }
425                                 // add the STU ADCs in the patch
426                                 if( ! isOfflineSimple )
427                                         adcAmp += fPatchADC[globCol+i][globRow+j];
428                                 else
429                                         adcAmp += fPatchADCSimple[globCol+i][globRow+j];
430                         }
431                 } // 4x4 cell window
432         }
433         if( amp == 0 ){
434                 AliDebug(2,"EMCal trigger patch with 0 energy.");
435                 return 0;
436         }
437         
438         // get the CM and patch index
439         cmiCol /= amp;
440         cmiRow /= amp;
441         cmCol = globCol + (Int_t)cmiCol;
442         cmRow = globRow + (Int_t)cmiRow;
443
444         // get the patch and corresponding cells
445         fGeom->GetAbsFastORIndexFromPositionInEMCAL( cmCol, cmRow, absId );
446         fGeom->GetCellIndexFromFastORIndex( absId, cellAbsId );
447
448         // find which out of the 4 cells is closest to CM and get it's position
449         cmiCellCol = TMath::Nint( cmiCol * 2. );
450         cmiCellRow = TMath::Nint( cmiRow * 2. );
451         fGeom->GetGlobal( cellAbsId[(cmiCellRow%2)*2 + cmiCellCol%2], centerMass );
452         
453         // get up right edge (eta min, phi max)
454         // get the absolute trigger ID
455         if( type == 0 )
456                 fGeom->GetAbsFastORIndexFromPositionInEMCAL( globCol+15, globRow+15, absId );
457         else if( type == 1)
458                 fGeom->GetAbsFastORIndexFromPositionInEMCAL( globCol+1, globRow+1, absId );
459         // convert to the 4 absId of the cells composing the trigger channel
460         fGeom->GetCellIndexFromFastORIndex( absId, cellAbsId );
461
462         fGeom->GetGlobal( cellAbsId[3], edge2 );
463         
464         // get the geometrical center as an average of two diagonally
465         // adjacent patches in the center
466         // picking two diagonally closest cells from the patches
467         if( type == 0 )
468                 fGeom->GetAbsFastORIndexFromPositionInEMCAL( globCol+7, globRow+7, absId );
469         else if( type == 1 )
470                 fGeom->GetAbsFastORIndexFromPositionInEMCAL( globCol, globRow, absId );
471
472         fGeom->GetCellIndexFromFastORIndex( absId, cellAbsId );
473         fGeom->GetGlobal( cellAbsId[3], center1 );
474         
475         if( type == 0 )
476                 fGeom->GetAbsFastORIndexFromPositionInEMCAL( globCol+8, globRow+8, absId );
477         else if( type == 1 )
478                 fGeom->GetAbsFastORIndexFromPositionInEMCAL( globCol+1, globRow+1, absId );
479
480         fGeom->GetCellIndexFromFastORIndex( absId, cellAbsId );
481         fGeom->GetGlobal( cellAbsId[0], center2 );
482         
483         centerGeo = center1;
484         centerGeo += center2;
485         centerGeo *= 0.5;
486         
487         // relate all to primary vertex
488         centerGeo -= vertex;
489         centerMass -= vertex;
490         edge1 -= vertex;
491         edge2 -= vertex;
492         
493         // fix tbits .. remove the unwanted type triggers
494         if( type == 0 )
495                 tBits = tBits & ~( 1 << (kTriggerTypeEnd + kL1GammaLow) | 1 << (kTriggerTypeEnd + kL1GammaHigh) | 1 << (kL1GammaLow) | 1 << (kL1GammaHigh));
496         else if( type == 1 )
497                 tBits = tBits & ~( 1 << (kTriggerTypeEnd + kL1JetLow) | 1 << (kTriggerTypeEnd + kL1JetHigh) | 1 << (kL1JetLow) | 1 << (kL1JetHigh));
498
499         // save the trigger object
500         new ((*fCaloTriggersOut)[fITrigger])AliEmcalTriggerPatchInfo();
501         trigger = (AliEmcalTriggerPatchInfo*)fCaloTriggersOut->At( fITrigger );
502         fITrigger++;
503         
504         Int_t isMC = MCEvent() ? 1 : 0;
505         Int_t offSet = (1 - isMC) * kTriggerTypeEnd;
506
507         trigger->SetCenterGeo( centerGeo, amp );
508         trigger->SetCenterMass( centerMass, amp );
509         trigger->SetEdge1( edge1, amp );
510         trigger->SetEdge2( edge2, amp );
511         trigger->SetADCAmp( adcAmp );
512         trigger->SetTriggerBits( tBits );
513         trigger->SetOffSet(offSet);
514         trigger->SetEdgeCell( globCol*2, globRow*2 ); // from triggers to cells
515         
516         return trigger;
517         
518 }
519
520
521 //________________________________________________________________________
522 void AliEmcalTriggerMaker::RunSimpleOfflineTrigger() 
523 {
524   // runs simple offline trigger algorithm
525   
526   // it creates separate patches for jet and gamma triggers
527   // on the same positions (different from STU reconstruction behavior)
528   // TODO:: change to merge
529
530   Int_t i, j, k, l, tBits, tSum;
531   TArrayI tBitsArray, rowArray, colArray;
532   
533   // 0 thresholds = no processing
534   if( fCaloTriggerSetupOut->GetThresholdJetLowSimple() == 0 &&
535     fCaloTriggerSetupOut->GetThresholdJetHighSimple() == 0 )
536     return;
537   
538   // run the trigger algo, stepping by 8 towers (= 4 trigger channels)
539   for( i = 0; i < 32; i += 4 ){
540     for( j = 0; j < 48; j += 4 ){
541       
542       tSum = 0;
543       tBits = 0;
544       
545       // window
546       for( k = 0; k < 16; k++ )
547         for( l = 0; l < 16; l++ )
548           tSum += (ULong64_t)fPatchADCSimple[i+k][j+l];
549       
550       // check thresholds
551       if( tSum > fCaloTriggerSetupOut->GetThresholdJetLowSimple() )
552         tBits = tBits | ( 1 << ( kTriggerTypeEnd + kL1JetLow ));
553       if( tSum > fCaloTriggerSetupOut->GetThresholdJetHighSimple() )
554         tBits = tBits | ( 1 << ( kTriggerTypeEnd + kL1JetHigh ));
555       
556       // add trigger values
557       if( tBits != 0 ){
558         // add offline bit
559         tBits = tBits | ( 1 << 25 );
560         
561         tBitsArray.Set( tBitsArray.GetSize() + 1 );
562         colArray.Set( colArray.GetSize() + 1 );
563         rowArray.Set( rowArray.GetSize() + 1 );
564         
565         tBitsArray[tBitsArray.GetSize()-1] = tBits;
566         colArray[colArray.GetSize()-1] = i;
567         rowArray[rowArray.GetSize()-1] = j;
568       }
569     }
570   } // trigger algo
571   
572   // 4x4 trigger algo, stepping by 2 towers (= 1 trigger channel)
573   for( i = 0; i < 46; i ++ ){
574     for( j = 0; j < 62; j ++ ){
575       
576       tSum = 0;
577       tBits = 0;
578       
579       // window
580       for( k = 0; k < 2; k++ )
581         for( l = 0; l < 2; l++ )
582           tSum += (ULong64_t)fPatchADCSimple[i+k][j+l];
583       
584       // check thresholds
585       if( tSum > fCaloTriggerSetupOut->GetThresholdGammaLowSimple() )
586         tBits = tBits | ( 1 << ( kTriggerTypeEnd + kL1GammaLow ));
587       if( tSum > fCaloTriggerSetupOut->GetThresholdGammaHighSimple() )
588         tBits = tBits | ( 1 << ( kTriggerTypeEnd + kL1GammaHigh ));
589       
590       // add trigger values
591       if( tBits != 0 ){
592         // add offline bit
593         tBits = tBits | ( 1 << 25 );
594         
595         tBitsArray.Set( tBitsArray.GetSize() + 1 );
596         colArray.Set( colArray.GetSize() + 1 );
597         rowArray.Set( rowArray.GetSize() + 1 );
598         
599         tBitsArray[tBitsArray.GetSize()-1] = tBits;
600         colArray[colArray.GetSize()-1] = i;
601         rowArray[rowArray.GetSize()-1] = j;
602       }
603     }
604   } // trigger algo
605   
606   
607   // save in object
608   fSimpleOfflineTriggers->DeAllocate();
609   fSimpleOfflineTriggers->Allocate( tBitsArray.GetSize() );
610
611   for( i = 0; i < tBitsArray.GetSize(); i++ ){
612     fSimpleOfflineTriggers->Add( colArray[i], rowArray[i], 0, 0, 0, 0, 0, tBitsArray[i] );
613   }
614   
615 }
616
617 //________________________________________________________________________
618 Bool_t AliEmcalTriggerMaker::NextTrigger( Bool_t &isOfflineSimple ) 
619 {
620   // get next trigger
621   
622   Bool_t loopContinue;
623   
624   loopContinue = fCaloTriggers->Next();
625   isOfflineSimple = kFALSE;
626
627   if( ! loopContinue ){
628     loopContinue = fSimpleOfflineTriggers->Next();
629     isOfflineSimple = kTRUE;
630   }
631   
632   return loopContinue;
633 }