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