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