AliPhysics  97a96ce (97a96ce)
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
AliEmcalTriggerMaker.cxx
Go to the documentation of this file.
1 /**************************************************************************
2  * Copyright(c) 1998-2013, 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 #include <TClonesArray.h>
16 #include <TArrayI.h>
17 #include <THashList.h>
18 #include "AliAODCaloTrigger.h"
19 #include "AliEMCALGeometry.h"
20 #include "AliEmcalTriggerMaker.h"
22 #include "AliEMCALTriggerConstants.h"
23 #include "AliEMCALTriggerDataGrid.h"
24 #include "AliEMCALTriggerPatchInfo.h"
25 #include "AliLog.h"
26 #include "AliVCaloCells.h"
27 #include "AliVCaloTrigger.h"
28 #include "AliVVZERO.h"
29 #include "THistManager.h"
30 #include "TString.h"
31 
32 #include <array>
33 #include <bitset>
34 #include <iostream>
35 #include <string>
36 
39 
40 
42 using namespace std;
43 
44 const int AliEmcalTriggerMaker::kColsEta = 48;
45 
46 const TString AliEmcalTriggerMaker::fgkTriggerTypeNames[5] = {"EJE", "EGA", "EL0", "REJE", "REGA"};
47 
52  AliAnalysisTaskEmcal("AliEmcalTriggerMaker",kFALSE),
53  fCaloTriggersOutName("EmcalTriggers"),
54  fCaloTriggerSetupOutName("EmcalTriggersSetup"),
55  fV0InName("AliAODVZERO"),
56  fUseTriggerBitConfig(kNewConfig),
57  fTriggerBitConfig(NULL),
58  fCaloTriggersOut(0),
59  fCaloTriggerSetupOut(0),
60  fSimpleOfflineTriggers(0),
61  fV0(0),
62  fPatchAmplitudes(NULL),
63  fPatchADCSimple(NULL),
64  fPatchADC(NULL),
65  fLevel0TimeMap(NULL),
66  fITrigger(0),
67  fDoQA(kFALSE),
68  fRejectOffAcceptancePatches(kFALSE),
69  fQAHistos(NULL),
70  fDebugLevel(0)
71 {
72  memset(fThresholdConstants, 0, sizeof(Int_t) * 12);
73 }
74 
81  AliAnalysisTaskEmcal(name,doQA),
82  fCaloTriggersOutName("EmcalTriggers"),
83  fCaloTriggerSetupOutName("EmcalTriggersSetup"),
84  fV0InName("AliAODVZERO"),
85  fUseTriggerBitConfig(kNewConfig),
86  fTriggerBitConfig(NULL),
87  fCaloTriggersOut(0),
88  fCaloTriggerSetupOut(0),
89  fSimpleOfflineTriggers(0),
90  fV0(0),
91  fPatchAmplitudes(NULL),
92  fPatchADCSimple(NULL),
93  fPatchADC(NULL),
94  fLevel0TimeMap(NULL),
95  fITrigger(0),
96  fDoQA(doQA),
97  fRejectOffAcceptancePatches(kFALSE),
98  fQAHistos(NULL),
99  fDebugLevel(0)
100 {
101  // Constructor.
102  memset(fThresholdConstants, 0, sizeof(Int_t) * 12);
103 }
104 
109 {
111 }
112 
117 {
119 
120  if (!fInitialized)
121  return;
122 
123  if(!fTriggerBitConfig){
124  switch(fUseTriggerBitConfig){
125  case kNewConfig:
126  fTriggerBitConfig = new AliEMCALTriggerBitConfigNew();
127  break;
128  case kOldConfig:
129  fTriggerBitConfig = new AliEMCALTriggerBitConfigOld();
130  break;
131  }
132  }
133 
134  if (!fCaloTriggersOutName.IsNull()) {
135  fCaloTriggersOut = new TClonesArray("AliEMCALTriggerPatchInfo");
137 
138  if (!(InputEvent()->FindListObject(fCaloTriggersOutName))) {
139  InputEvent()->AddObject(fCaloTriggersOut);
140  }
141  else {
142  fInitialized = kFALSE;
143  AliFatal(Form("%s: Container with same name %s already present. Aborting", GetName(), fCaloTriggersOutName.Data()));
144  return;
145  }
146  }
147 
148  if (!fCaloTriggerSetupOutName.IsNull()) {
151 
152  if (!(InputEvent()->FindListObject(fCaloTriggerSetupOutName))) {
153  InputEvent()->AddObject(fCaloTriggerSetupOut);
154  }
155  else {
156  fInitialized = kFALSE;
157  AliFatal(Form("%s: Container with same name %s already present. Aborting", GetName(), fCaloTriggerSetupOutName.Data()));
158  return;
159  }
160  }
161 
162  if ( ! fV0InName.IsNull()) {
163  fV0 = (AliVVZERO*)InputEvent()->FindListObject(fV0InName);
164  }
165 
166 
167  // Allocate containers for the ADC values
168  int nrows = fGeom->GetNTotalTRU() * 2;
169  std::cout << "Allocating channel grid with 48 columns in eta and " << nrows << " rows in phi" << std::endl;
170  fPatchAmplitudes->Allocate(48, nrows);
171  fPatchADC->Allocate(48, nrows);
172  fPatchADCSimple->Allocate(48, nrows);
173  fLevel0TimeMap->Allocate(48, nrows);
174 
175  // container for simple offline trigger processing
176  fSimpleOfflineTriggers = new AliAODCaloTrigger();
177  fSimpleOfflineTriggers->Allocate(0);
178 }
179 
184 {
186 
187  // Create data structure for energy measurements;
192 
193  if(fDoQA && fOutput){
194  fQAHistos = new THistManager("TriggerQA");
195  std::array<std::string, 3> patchtypes = {"Online", "Offline", "Recalc"};
196 
197  for(int itype = 0; itype < 5; itype++){
198  for(const auto & patchtype : patchtypes){
199  fQAHistos->CreateTH2(Form("RCPos%s%s", fgkTriggerTypeNames[itype].Data(), patchtype.c_str()), Form("Lower edge position of %s %s patches (col-row);iEta;iPhi", patchtype.c_str(), fgkTriggerTypeNames[itype].Data()), 48, -0.5, 47.5, 104, -0.5, 103.5);
200  fQAHistos->CreateTH2(Form("EPCentPos%s%s", fgkTriggerTypeNames[itype].Data(), patchtype.c_str()), Form("Center position of the %s %s trigger patches;#eta;#phi", patchtype.c_str(), fgkTriggerTypeNames[itype].Data()), 20, -0.8, 0.8, 700, 0., 7.);
201  fQAHistos->CreateTH2(Form("PatchADCvsE%s%s", fgkTriggerTypeNames[itype].Data(), patchtype.c_str()), Form("Patch ADC value for trigger type %s %s;Trigger ADC;FEE patch energy (GeV)", patchtype.c_str(), fgkTriggerTypeNames[itype].Data()), 2000, 0., 2000, 200, 0., 200);
202  }
203  }
204  fQAHistos->CreateTH1("triggerBitsAll", "Trigger bits for all incoming patches;bit nr", 64, -0.5, 63.5);
205  fQAHistos->CreateTH1("triggerBitsSel", "Trigger bits for reconstructed patches;bit nr", 64, -0.5, 63.5);
207  PostData(1, fOutput);
208  }
209 }
210 
216 {
217  AliEMCALTriggerPatchInfo *trigger(nullptr), *triggerMainJet(nullptr),
218  *triggerMainGamma(nullptr), *triggerMainLevel0(nullptr),
219  *triggerMainJetSimple(nullptr), *triggerMainGammaSimple(nullptr),
220  *triggerMainJetRecalc(nullptr), *triggerMainGammaRecalc(nullptr);
221 
222  // delete patch array, clear setup object
223  fCaloTriggersOut->Delete();
225 
226  if (!fCaloTriggers) {
227  AliError(Form("Calo triggers container %s not available.", fCaloTriggersName.Data()));
228  return kTRUE;
229  }
230  if (!fCaloCells) {
231  AliError(Form("Calo cells container %s not available.", fCaloCellsName.Data()));
232  return kTRUE;
233  }
234  if (!fCaloCells) {
235  AliError(Form("V0 container %s not available.", fV0InName.Data()));
236  return kTRUE;
237  }
238 
239  // do not process, if sooner than 11h period
240  // 160683 ??
241  if( InputEvent()->GetRunNumber() < 167693 )
242  return kTRUE;
243 
244 // // do not process any MC, since no MC was generated with correct
245 // // EMCal trigger L1 jet trigger simulation, yet
246 // // productions will be enabled, once some correct once are produced
247 // if( MCEvent() != 0 )
248 // return kTRUE;
249 
250  // must reset before usage, or the class will fail
251  fCaloTriggers->Reset();
252 
253  // zero the arrays
254  fPatchAmplitudes->Reset();
255  fPatchADC->Reset();
256  fPatchADCSimple->Reset();
257  fLevel0TimeMap->Reset();
258 
259  // first run over the patch array to compose a map of 2x2 patch energies
260  // which is then needed to construct the full patch ADC energy
261  // class is not empty
262  if (fCaloTriggers->GetEntries() > 0) {
263 
264  // go throuth the trigger channels
265  while (fCaloTriggers->Next()) {
266  // get position in global 2x2 tower coordinates
267  // A0 left bottom (0,0)
268  Int_t globCol=-1, globRow=-1;
269  fCaloTriggers->GetPosition(globCol, globRow);
270  // exclude channel completely if it is masked as hot channel
271  if(fBadChannels.HasChannel(globCol, globRow)) continue;
272  // for some strange reason some ADC amps are initialized in reconstruction
273  // as -1, neglect those
274  Int_t adcAmp=-1;
275  fCaloTriggers->GetL1TimeSum(adcAmp);
276  if (adcAmp>-1)
277  (*fPatchADC)(globCol,globRow) = adcAmp;
278 
279  // Handling for L0 triggers
280  // For the ADC value we use fCaloTriggers->GetAmplitude()
281  // In data, all patches which have 4 TRUs with proper level0 times are
282  // valid trigger patches. Therefore we need to check all neighbors for
283  // the level0 times, not only the bottom left. In order to obtain this
284  // information, a lookup table with the L0 times for each TRU is created
285  Float_t amplitude(0);
286  fCaloTriggers->GetAmplitude(amplitude);
287  if(amplitude < 0) amplitude = 0;
288  (*fPatchAmplitudes)(globCol,globRow) = amplitude;
289  Int_t nl0times(0);
290  fCaloTriggers->GetNL0Times(nl0times);
291  if(nl0times){
292  TArrayI l0times(nl0times);
293  fCaloTriggers->GetL0Times(l0times.GetArray());
294  for(int itime = 0; itime < nl0times; itime++){
295  if(l0times[itime] >7 && l0times[itime] < 10){
296  (*fLevel0TimeMap)(globCol,globRow) = static_cast<Char_t>(l0times[itime]);
297  break;
298  }
299  }
300  }
301  } // patches
302  } // array not empty
303 
304  // fill the patch ADCs from cells
305  Int_t nCell = fCaloCells->GetNumberOfCells();
306  for(Int_t iCell = 0; iCell < nCell; ++iCell) {
307  // get the cell info, based in index in array
308  Short_t cellId = fCaloCells->GetCellNumber(iCell);
309  Double_t amp = fCaloCells->GetAmplitude(iCell);
310  // get position
311  Int_t absId=-1;
312  fGeom->GetFastORIndexFromCellIndex(cellId, absId);
313  Int_t globCol=-1, globRow=-1;
314  fGeom->GetPositionInEMCALFromAbsFastORIndex(absId, globCol, globRow);
315  // add
316  (*fPatchADCSimple)(globCol,globRow) += amp/EMCALTrigger::kEMCL1ADCtoGeV;
317  }
318 
319  // dig out common data (thresholds)
320  // 0 - jet high, 1 - gamma high, 2 - jet low, 3 - gamma low
322  fCaloTriggers->GetL1Threshold(1),
323  fCaloTriggers->GetL1Threshold(2),
324  fCaloTriggers->GetL1Threshold(3));
325 
326  // get the V0 value and compute and set the offline thresholds
327  // get V0, compute thresholds and save them as global parameters
328  Int_t v0[2];
329  v0[0] = fV0->GetTriggerChargeA();
330  v0[1] = fV0->GetTriggerChargeC();
331  ULong64_t v0S = v0[0] + v0[1];
332  fSimpleOfflineTriggers->SetL1V0(v0);
333 
334  for (Int_t i = 0; i < 4; ++i) {
335  // A*V0^2/2^32+B*V0/2^16+C
336  ULong64_t thresh = ( ((ULong64_t)fThresholdConstants[i][0]) * v0S * v0S ) >> 32;
337  thresh += ( ((ULong64_t)fThresholdConstants[i][1]) * v0S ) >> 16;
338  thresh += ((ULong64_t)fThresholdConstants[i][2]);
339  fSimpleOfflineTriggers->SetL1Threshold(i,thresh);
340  }
341 
342  // save the thresholds in output object
344  fSimpleOfflineTriggers->GetL1Threshold(1),
345  fSimpleOfflineTriggers->GetL1Threshold(2),
346  fSimpleOfflineTriggers->GetL1Threshold(3));
347 
348  // run the trigger
350 
351  // reset for re-run
352  fCaloTriggers->Reset();
353  fSimpleOfflineTriggers->Reset();
354 
355  // class is not empty
356  if (fCaloTriggers->GetEntries() > 0 || fSimpleOfflineTriggers->GetEntries() > 0) {
357  fITrigger = 0;
358 
359  // go throuth the trigger channels, real first, then offline
360  Bool_t isOfflineSimple=0;
361  while (NextTrigger(isOfflineSimple)) {
362  if(isOfflineSimple){
363  // process jet offline
364  trigger = ProcessPatch(kTMEMCalJet, kTMOffline);
365  // save main jet triggers in event
366  if (trigger != 0) {
367  // check if more energetic than others for main patch marking
368  if (triggerMainJetSimple == 0 || (triggerMainJetSimple->GetPatchE() < trigger->GetPatchE()))
369  triggerMainJetSimple = trigger;
370  }
371 
372  // process jet recalc
373  trigger = ProcessPatch(kTMEMCalJet, kTMRecalc);
374  // save main jet triggers in event
375  if (trigger != 0) {
376  // check if more energetic than others for main patch marking
377  if (triggerMainJetRecalc == 0 || (triggerMainJetRecalc->GetPatchE() < trigger->GetPatchE()))
378  triggerMainJetRecalc = trigger;
379  }
380 
381  // process gamma offline
383  // save main gamma triggers in event
384  if (trigger != 0) {
385  // check if more energetic than others for main patch marking
386  if (triggerMainGammaSimple == 0 || (triggerMainGammaSimple->GetPatchE() < trigger->GetPatchE()))
387  triggerMainGammaSimple = trigger;
388  }
389 
390  // process gamma recalc
392  // save main gamma triggers in event
393  if (trigger != 0) {
394  // check if more energetic than others for main patch marking
395  if (triggerMainGammaRecalc == 0 || (triggerMainGammaRecalc->GetPatchE() < trigger->GetPatchE()))
396  triggerMainGammaRecalc = trigger;
397  }
398 
399  } else {
400  // process jet
401  trigger = ProcessPatch(kTMEMCalJet, kTMOnline);
402  // save main jet triggers in event
403  if (trigger != 0) {
404  // check if more energetic than others for main patch marking
405  if(triggerMainJet == 0 || (triggerMainJet->GetPatchE() < trigger->GetPatchE()))
406  triggerMainJet = trigger;
407  }
408 
410  // save main gamma triggers in event
411  if (trigger != 0) {
412  // check if more energetic than others for main patch marking
413  if (triggerMainGamma == 0 || (triggerMainGamma->GetPatchE() < trigger->GetPatchE()))
414  triggerMainGamma = trigger;
415  }
417  // save main level0 trigger in the event
418  if (trigger) {
419  if (!triggerMainLevel0 || (triggerMainLevel0->GetPatchE() < trigger->GetPatchE()))
420  triggerMainLevel0 = trigger;
421  }
422  }
423  } // triggers
424 
425  // mark the most energetic patch as main
426  // for real and also simple offline
427  if (triggerMainJet != 0) {
428  Int_t tBits = triggerMainJet->GetTriggerBits();
429  // main trigger flag
430  tBits = tBits | ( 1 << kMainTriggerBitNum );
431  triggerMainJet->SetTriggerBits( tBits );
432  }
433  if (triggerMainJetSimple != 0) {
434  Int_t tBits = triggerMainJetSimple->GetTriggerBits();
435  // main trigger flag
436  tBits = tBits | ( 1 << kMainTriggerBitNum );
437  triggerMainJetSimple->SetTriggerBits(tBits);
438  }
439  if (triggerMainJetRecalc != 0) {
440  Int_t tBits = triggerMainJetRecalc->GetTriggerBits();
441  // main trigger flag
442  tBits = tBits | ( 1 << kMainTriggerBitNum );
443  triggerMainJetRecalc->SetTriggerBits(tBits);
444  }
445  if (triggerMainGamma != 0) {
446  Int_t tBits = triggerMainGamma->GetTriggerBits();
447  // main trigger flag
448  tBits = tBits | ( 1 << kMainTriggerBitNum );
449  triggerMainGamma->SetTriggerBits( tBits );
450  }
451  if (triggerMainGammaSimple != 0) {
452  Int_t tBits = triggerMainGammaSimple->GetTriggerBits();
453  // main trigger flag
454  tBits = tBits | ( 1 << kMainTriggerBitNum );
455  triggerMainGammaSimple->SetTriggerBits( tBits );
456  }
457  if (triggerMainGammaRecalc != 0) {
458  Int_t tBits = triggerMainGammaRecalc->GetTriggerBits();
459  // main trigger flag
460  tBits = tBits | ( 1 << kMainTriggerBitNum );
461  triggerMainGammaRecalc->SetTriggerBits( tBits );
462  }
463  if(triggerMainLevel0){
464  Int_t tBits = triggerMainLevel0->GetTriggerBits();
465  // main trigger flag
466  tBits |= (1 << kMainTriggerBitNum);
467  triggerMainLevel0->SetTriggerBits(tBits);
468  }
469  } // there are some triggers
470 
471  // Diagnostics
472  int npatchOnline = 0;
473  for(TIter patchIter = TIter(fCaloTriggersOut).Begin(); patchIter != TIter::End(); ++patchIter){
474  AliEMCALTriggerPatchInfo *mypatch = static_cast<AliEMCALTriggerPatchInfo *>(*patchIter);
475  if(mypatch->IsOfflineSimple()) continue;
476  AliDebug(1,Form("Patch with bits: %s, types: JH[%s], JL[%s], GH[%s], GL[%s], L0[%s]",
477  std::bitset<sizeof(int)*4>(mypatch->GetTriggerBits()).to_string().c_str(),
478  (mypatch->IsJetHigh() ? "y" : "n"), (mypatch->IsJetLow() ? "y" : "n"),
479  (mypatch->IsGammaHigh() ? "y" : "n"), (mypatch->IsGammaLow() ? "y" : "n"),(mypatch->IsLevel0() ? "y" : "n")));
480  npatchOnline++;
481  }
482  AliDebug(1, Form("Number of online patches: %d", npatchOnline));
483 
484  return kTRUE;
485 }
486 
495 {
496  // get trigger bits and position in global 2x2 tower coordinates
497  // A0 left bottom (0,0)
498  Int_t tBits=-1, globCol=-1, globRow=-1;
499  if (patchSource == kTMOnline){
500  fCaloTriggers->GetTriggerBits(tBits);
501  fCaloTriggers->GetPosition(globCol,globRow);
502  } else {
503  fSimpleOfflineTriggers->GetTriggerBits(tBits);
504  fSimpleOfflineTriggers->GetPosition(globCol, globRow);
505  }
506 
507  if(globCol < 0 || globRow < 0){
508  TString debugpatchtype;
509  switch(patchSource){
510  case kTMOnline: debugpatchtype = "Online patches"; break;
511  case kTMOffline: debugpatchtype = "Offline patches"; break;
512  case kTMRecalc: debugpatchtype = "Recalc patches"; break;
513  };
514  AliErrorStream() << "Invalid patch position(" << globCol << "," << globRow << ") for " << debugpatchtype << std::endl;
515  }
516 
517  if(fDoQA){
518  for(unsigned int ibit = 0; ibit < sizeof(tBits)*8; ibit++) {
519  if(tBits & (1 << ibit)){
520  fQAHistos->FillTH1("triggerBitsAll", ibit);
521  }
522  }
523  }
524 
525  if ((type == kTMEMCalJet && !IsEJE( tBits )) ||
526  (type == kTMEMCalGamma && !IsEGA( tBits )) ||
527  (type == kTMEMCalLevel0 && !(CheckForL0(*fCaloTriggers))))
528  return 0;
529 
530  if((patchSource == kTMOffline && !IsOfflineSimple(tBits)) ||
531  (patchSource == kTMRecalc && !IsRecalc(tBits)))
532  return 0;
533 
534  // save primary vertex in vector
535  TVector3 vertex;
536  vertex.SetXYZ(fVertex[0], fVertex[1], fVertex[2]);
537 
538  // Markus: For the moment reject jet patches with a row larger than 44 to overcome
539  // an issue with patches containing inactive TRUs
540  // (last 2 supermodules inactive but still included in the reconstruction)
541  Int_t runno = InputEvent()->GetRunNumber();
542  if(runno > 176000 && runno <= 197692){
543  // Valid only for 2012 geometry
544  if((type == kTMEMCalJet && IsEJE( tBits )) && (globRow > 44)) { // Hard coded number in order to be insensitive to changes in the geometry
545  AliDebug(1, Form("Jet patch in inactive area: row[%d]", globRow));
546  return NULL;
547  }
548  }
549 
551  int patchsize = 2;
552  const int kRowsPhi = fGeom->GetNTotalTRU() * 2;
553  if(type == kTMEMCalJet) patchsize = 16;
554  if((globCol + patchsize >= kColsEta) || (globCol + patchsize >= kRowsPhi)){
555  AliError(Form("Invalid patch position for patch type %s: Col[%d], Row[%d] - patch rejected", fgkTriggerTypeNames[type].Data(), globCol, globRow));
556  return NULL;
557  }
558  }
559 
560  // get the absolute trigger ID
561  Int_t absId=-1;
562  fGeom->GetAbsFastORIndexFromPositionInEMCAL(globCol, globRow, absId);
563  // convert to the 4 absId of the cells composing the trigger channel
564  Int_t cellAbsId[4]={-1,-1,-1,-1};
565  fGeom->GetCellIndexFromFastORIndex(absId, cellAbsId);
566 
567  // get low left edge (eta max, phi min)
568  TVector3 edge1;
569  fGeom->GetGlobal(cellAbsId[0], edge1);
570  Int_t colEdge1 = globCol, rowEdge1 = globRow, absIdEdge1 = absId, cellIdEdge1 = cellAbsId[0]; // Used in warning for invalid patch position
571 
572  // sum the available energy in the 32/32 window of cells
573  // step over trigger channels and get all the corresponding cells
574  // make CM
575  Float_t amp = 0;
576  Float_t cmiCol = 0;
577  Float_t cmiRow = 0;
578  Int_t adcAmp = 0;
579  Double_t adcOfflineAmp = 0;
580  int nfastor = (type == kTMEMCalJet) ? 16 : 2; // 32x32 cell window for L1 Jet trigger, 4x4 for L1 Gamma or L0 trigger
581  for (Int_t i = 0; i < nfastor; ++i) {
582  for (Int_t j = 0; j < nfastor; ++j) {
583  // get the 4 cells composing the trigger channel
584  fGeom->GetAbsFastORIndexFromPositionInEMCAL(globCol+i, globRow+j, absId);
585  fGeom->GetCellIndexFromFastORIndex(absId, cellAbsId);
586  // add amplitudes and find patch edges
587  for (Int_t k = 0; k < 4; ++k) {
588  Float_t ca = fCaloCells->GetCellAmplitude(cellAbsId[k]);
589  //fGeom->GetGlobal(cellAbsId[k], cellCoor);
590  amp += ca;
591  cmiCol += ca*(Float_t)i;
592  cmiRow += ca*(Float_t)j;
593  }
594  // add the STU ADCs in the patch (in case of L1) or the TRU Amplitude (in case of L0)
595  if(type == kTMEMCalLevel0){
596  try {
597  adcAmp += static_cast<Int_t>((*fPatchAmplitudes)(globCol+i,globRow+j) * 4); // precision loss in case of global integer field
599  if(fDebugLevel){
600  std::cerr << e.what() << std::endl;
601  }
602  }
603  } else {
604  try {
605  adcAmp += (*fPatchADC)(globCol+i,globRow+j);
607  if(fDebugLevel){
608  std::cerr << e.what() << std::endl;
609  }
610  }
611  }
612 
613  try{
614  adcOfflineAmp += (*fPatchADCSimple)(globCol+i,globRow+j);
616  if(fDebugLevel){
617  std::cerr << e.what() << std::endl;
618  }
619  }
620  }
621  }
622 
623  if (amp == 0) {
624  AliDebug(2,"EMCal trigger patch with 0 energy.");
625  return 0;
626  }
627 
628  // get the CM and patch index
629  cmiCol /= amp;
630  cmiRow /= amp;
631  Int_t cmCol = globCol + (Int_t)cmiCol;
632  Int_t cmRow = globRow + (Int_t)cmiRow;
633 
634  // get the patch and corresponding cells
635  fGeom->GetAbsFastORIndexFromPositionInEMCAL( cmCol, cmRow, absId );
636  fGeom->GetCellIndexFromFastORIndex( absId, cellAbsId );
637 
638  // find which out of the 4 cells is closest to CM and get it's position
639  Int_t cmiCellCol = TMath::Nint(cmiCol * 2.);
640  Int_t cmiCellRow = TMath::Nint(cmiRow * 2.);
641  TVector3 centerMass;
642  fGeom->GetGlobal(cellAbsId[(cmiCellRow%2)*2 + cmiCellCol%2], centerMass);
643 
644  // get up right edge (eta min, phi max)
645  // get the absolute trigger ID
646  Int_t posOffset=-1;
647  switch(type){
648  case kTMEMCalJet:
649  posOffset = 15;
650  break;
651  case kTMEMCalGamma:
652  posOffset = 1;
653  break;
654  case kTMEMCalLevel0:
655  posOffset = 1;
656  break;
657  default:
658  posOffset = 0;
659  break;
660  };
661  fGeom->GetAbsFastORIndexFromPositionInEMCAL(globCol+posOffset, globRow+posOffset, absId);
662  fGeom->GetCellIndexFromFastORIndex(absId, cellAbsId);
663  TVector3 edge2;
664  fGeom->GetGlobal(cellAbsId[3], edge2);
665  Int_t colEdge2 = globCol+posOffset, rowEdge2 = globRow+posOffset, absIdEdge2 = absId, cellIdEdge2 = cellAbsId[3]; // Used in warning for invalid patch position
666 
667  // get the geometrical center as an average of two diagonally
668  // adjacent patches in the center
669  // picking two diagonally closest cells from the patches
670  switch(type){
671  case kTMEMCalJet:
672  posOffset = 7;
673  break;
674  case kTMEMCalGamma:
675  posOffset = 0;
676  break;
677  case kTMEMCalLevel0:
678  posOffset = 0;
679  break;
680  default:
681  posOffset = 0;
682  break;
683  };
684  fGeom->GetAbsFastORIndexFromPositionInEMCAL(globCol+posOffset, globRow+posOffset, absId);
685  fGeom->GetCellIndexFromFastORIndex(absId, cellAbsId);
686  TVector3 center1;
687  fGeom->GetGlobal(cellAbsId[3], center1);
688 
689  switch(type){
690  case kTMEMCalJet:
691  posOffset = 8;
692  break;
693  case kTMEMCalGamma:
694  posOffset = 1;
695  break;
696  case kTMEMCalLevel0:
697  posOffset = 1;
698  break;
699  };
700  fGeom->GetAbsFastORIndexFromPositionInEMCAL(globCol+posOffset, globRow+posOffset, absId);
701  fGeom->GetCellIndexFromFastORIndex(absId, cellAbsId);
702  TVector3 center2;
703  fGeom->GetGlobal(cellAbsId[0], center2);
704 
705  TVector3 centerGeo(center1);
706  centerGeo += center2;
707  centerGeo *= 0.5;
708 
709  // relate all to primary vertex
710  TVector3 edge1tmp = edge1, edge2tmp = edge2; // Used in warning for invalid patch position
711  centerGeo -= vertex;
712  centerMass -= vertex;
713  edge1 -= vertex;
714  edge2 -= vertex;
715  // Check for invalid patch positions
716  if(!(edge1[0] || edge1[1] || edge1[2])){
717  AliWarning(Form("Inconsistency in patch position for edge1: [%f|%f|%f]", edge1[0], edge1[1], edge1[2]));
718  AliWarning("Original vectors:");
719  AliWarning(Form("edge1: [%f|%f|%f]", edge1tmp[0], edge1tmp[1], edge1tmp[2]));
720  AliWarning(Form("vertex: [%f|%f|%f]", vertex[0], vertex[1], vertex[2]));
721  AliWarning(Form("Col: %d, Row: %d, FABSID: %d, Cell: %d", colEdge1, rowEdge1, absIdEdge1, cellIdEdge1));
722  AliWarning(Form("Offline: %s", (patchSource == kTMOffline || patchSource == kTMRecalc) ? "yes" : "no"));
723  }
724  if(!(edge2[0] || edge2[1] || edge2[2])){
725  AliWarning(Form("Inconsistency in patch position for edge2: [%f|%f|%f]", edge2[0], edge2[1], edge2[2]));
726  AliWarning("Original vectors:");
727  AliWarning(Form("edge2: [%f|%f|%f]", edge2tmp[0], edge2tmp[1], edge2tmp[2]));
728  AliWarning(Form("vertex: [%f|%f|%f]", vertex[0], vertex[1], vertex[2]));
729  AliWarning(Form("Col: %d, Row: %d, FABSID: %d, Cell: %d", colEdge2, rowEdge2, absIdEdge2, cellIdEdge2));
730  AliWarning(Form("Offline: %s", (patchSource == kTMOffline || patchSource == kTMRecalc) ? "yes" : "no"));
731  }
732 
733  Int_t isMC = MCEvent() ? 1 : 0;
734  Int_t offSet = (1 - isMC) * fTriggerBitConfig->GetTriggerTypesEnd();
735 
736  // fix tbits .. remove the unwanted type triggers
737  // for Jet and Gamma triggers we remove also the level 0 bit since it will be stored in the level 0 patch
738  // for level 0 we remove all gamma and jet trigger bits
739  if(patchSource == kTMOnline){
740  switch(type){
741  case kTMEMCalJet:
742  tBits = tBits & ~( 1 << (fTriggerBitConfig->GetTriggerTypesEnd() + fTriggerBitConfig->GetGammaLowBit()) | 1 << (fTriggerBitConfig->GetTriggerTypesEnd() + fTriggerBitConfig->GetGammaHighBit()) |
743  1 << (fTriggerBitConfig->GetGammaLowBit()) | 1 << (fTriggerBitConfig->GetGammaHighBit()) |
744  1 << (fTriggerBitConfig->GetTriggerTypesEnd() + fTriggerBitConfig->GetLevel0Bit()) | 1 << (fTriggerBitConfig->GetLevel0Bit()));
745  break;
746  case kTMEMCalGamma:
747  tBits = tBits & ~( 1 << (fTriggerBitConfig->GetTriggerTypesEnd() + fTriggerBitConfig->GetJetLowBit()) | 1 << (fTriggerBitConfig->GetTriggerTypesEnd() + fTriggerBitConfig->GetJetHighBit()) |
748  1 << (fTriggerBitConfig->GetJetLowBit()) | 1 << (fTriggerBitConfig->GetJetHighBit()) |
749  1 << (fTriggerBitConfig->GetTriggerTypesEnd() + fTriggerBitConfig->GetLevel0Bit()) | 1 << (fTriggerBitConfig->GetLevel0Bit()));
750  break;
751  case kTMEMCalLevel0:
752  // Explicitly set the level 0 bit to overcome the masking out
753  tBits |= 1 << (offSet + fTriggerBitConfig->GetLevel0Bit());
754  tBits = tBits & ~( 1 << (fTriggerBitConfig->GetTriggerTypesEnd() + fTriggerBitConfig->GetJetLowBit()) | 1 << (fTriggerBitConfig->GetTriggerTypesEnd() + fTriggerBitConfig->GetJetHighBit()) |
755  1 << (fTriggerBitConfig->GetJetLowBit()) | 1 << (fTriggerBitConfig->GetJetHighBit()) | 1 << (fTriggerBitConfig->GetTriggerTypesEnd() + fTriggerBitConfig->GetGammaLowBit()) |
756  1 << (fTriggerBitConfig->GetTriggerTypesEnd() + fTriggerBitConfig->GetGammaHighBit()) | 1 << (fTriggerBitConfig->GetGammaLowBit()) | 1 << (fTriggerBitConfig->GetGammaHighBit()));
757  break;
758  default: // recalculated patches don't need any action
759  break;
760  };
761  }
762 
763  // Remove online bits from offline and recalc patches
764  if(patchSource == kTMRecalc){
765  tBits = tBits & kRecalcBitmask;
766  // remove gamma bits from jet patches && vice versa
767  if(type == kTMEMCalJet)
768  tBits = tBits & (1 << (kRecalcOffset + fTriggerBitConfig->GetJetLowBit()) | 1 << (kRecalcOffset + fTriggerBitConfig->GetJetHighBit()));
769  else
770  tBits = tBits & (1 << (kRecalcOffset + fTriggerBitConfig->GetGammaLowBit()) | 1 << (kRecalcOffset + fTriggerBitConfig->GetGammaHighBit()));
771  } else if(patchSource == kTMOffline){
772  tBits = tBits & kOfflineBitmask;
773  // remove gamma bits from jet patches && vice versa
774  if(type == kTMEMCalJet)
775  tBits = tBits & (1 << (kOfflineOffset + fTriggerBitConfig->GetJetLowBit()) | 1 << (kOfflineOffset + fTriggerBitConfig->GetJetHighBit()));
776  else
777  tBits = tBits & (1 << (kOfflineOffset + fTriggerBitConfig->GetGammaLowBit()) | 1 << (kOfflineOffset + fTriggerBitConfig->GetGammaHighBit()));
778  }
779 
780  // save the trigger object
781  AliEMCALTriggerPatchInfo *trigger =
782  new ((*fCaloTriggersOut)[fITrigger]) AliEMCALTriggerPatchInfo();
783  fITrigger++;
784  trigger->SetTriggerBitConfig(fTriggerBitConfig);
785  trigger->SetCenterGeo(centerGeo, amp);
786  trigger->SetCenterMass(centerMass, amp);
787  trigger->SetEdge1(edge1, amp);
788  trigger->SetEdge2(edge2, amp);
789  trigger->SetADCAmp(adcAmp);
790  trigger->SetADCOfflineAmp(Int_t(adcOfflineAmp));
791  trigger->SetTriggerBits(tBits);
792  trigger->SetOffSet(offSet);
793  trigger->SetCol0(globCol);
794  trigger->SetRowStart(globRow);
795  trigger->SetEdgeCell(globCol*2, globRow*2); // from triggers to cells
796  //if(isOfflineSimple)trigger->SetOfflineSimple();
797  if(fDoQA){
798  TString patchtype;
799  switch(patchSource){
800  case kTMOnline: patchtype = "Online"; break;
801  case kTMOffline: patchtype = "Offline"; break;
802  case kTMRecalc: patchtype = "Recalc"; break;
803  };
804  fQAHistos->FillTH2(Form("RCPos%s%s", fgkTriggerTypeNames[type].Data(), patchtype.Data()), globCol, globRow);
805  fQAHistos->FillTH2(Form("EPCentPos%s%s", fgkTriggerTypeNames[type].Data(), patchtype.Data()), centerGeo.Eta(), centerGeo.Phi());
806  fQAHistos->FillTH2(Form("PatchADCvsE%s%s", fgkTriggerTypeNames[type].Data(), patchtype.Data()), (patchSource == kTMOffline) ? adcOfflineAmp : adcAmp, trigger->GetPatchE());
807  // Redo checking of found trigger bits after masking of unwanted triggers
808  for(unsigned int ibit = 0; ibit < sizeof(tBits)*8; ibit++) {
809  if(tBits & (1 << ibit)){
810  fQAHistos->FillTH1("triggerBitsSel", ibit);
811  }
812  }
813  }
814  return trigger;
815 }
816 
826 {
827 
828  // @TODO: inefficient implementation: Array needs to be
829  // copied for every new patch
830  TArrayI tBitsArray(4), rowArray(4), colArray(4);
831 
832  // First entries are for flagging the main patches
833  // Logics:
834  // 0. Recalc jet
835  // 1. Offline jet
836  // 2. Recalc gamma
837  // 3. Offline gamma
838  // Afterwards come all other entries. Attention:
839  // In order to prevent multiple counting the the patch information
840  // is written to the trigger stream only from index 4 on
841 
842  // Max Recalc jet bit
843  tBitsArray[0] = 0;
844  colArray[0] = -1;
845  rowArray[0] = -1;
846 
847  // Max offline jet patch
848  tBitsArray[1] = 0;
849  colArray[1] = -1;
850  rowArray[1] = -1;
851 
852  // Max recalc gamma patch
853  tBitsArray[2] = 0;
854  colArray[2] = -1;
855  rowArray[2] = -1;
856 
857  // Max offline gamma patch
858  tBitsArray[3] = 0;
859  colArray[3] = -1;
860  rowArray[3] = -1;
861 
862  Double_t maxPatchADCoffline = -1;
863  Int_t maxPatchADC = -1;
864  // run the trigger algo, stepping by 8 towers (= 4 trigger channels)
865  Int_t maxCol = 48;
866  Int_t maxRow = fGeom->GetNTotalTRU()*2;
867  // Markus:
868  // temp fix for the number of TRUs in the 2011 PbPb data to 30
869  // @TODO: Fix in the geometry in the OCDB
870  int runnumber = InputEvent()->GetRunNumber();
871  if(runnumber > 139517 && runnumber <= 170593) maxRow = 60;
872  Int_t isMC = MCEvent() ? 1 : 0;
873  Int_t bitOffSet = (1 - isMC) * fTriggerBitConfig->GetTriggerTypesEnd();
874  for (Int_t i = 0; i <= (maxCol-16); i += 4) {
875  for (Int_t j = 0; j <= (maxRow-16); j += 4) {
876  Double_t tSumOffline = 0;
877  Int_t tSum = 0;
878  Int_t tBits = 0;
879  // window
880  for (Int_t k = 0; k < 16; ++k) {
881  for (Int_t l = 0; l < 16; ++l) {
882  tSumOffline += (*fPatchADCSimple)(i+k,j+l);
883  tSum += static_cast<ULong64_t>((*fPatchADC)(i+k,j+l));
884  }
885  }
886 
887  if (tSum > maxPatchADC) { // Mark highest Jet patch
888  maxPatchADC = tSum;
889  colArray[0] = i;
890  rowArray[0] = j;
891  }
892 
893  if (tSumOffline > maxPatchADCoffline) { // Mark highest Jet patch
894  maxPatchADCoffline = tSumOffline;
895  colArray[1] = i;
896  rowArray[1] = j;
897  }
898 
899  // check thresholds
900  // first we check the offline energy compared to thresholds and set the offline bits accordingly
901  // second we check the recalc energy compared to thresholds and set the recalc bits accordingly
902  if (tSumOffline > fCaloTriggerSetupOut->GetThresholdJetLowSimple()){
903  // Set the trigger bit for jet low - it is needed by the ProcessPatch function
904  // in order to handle jet patches - for offline and recalc patches these bits will
905  // be removed later
906  tBits = tBits | ( 1 << ( bitOffSet + fTriggerBitConfig->GetJetLowBit() ));
907  // Add offline bit - it will be handled by the ProcessPatch function
908  tBits = tBits | ( 1 << (kOfflineOffset + fTriggerBitConfig->GetJetLowBit()) );
909  }
910  if (tSumOffline > fCaloTriggerSetupOut->GetThresholdJetHighSimple()){
911  // Set the trigger bit for jet high - it is needed by the ProcessPatch function
912  // in order to handle jet patches - for offline and recalc patches these bits will
913  // be removed later
914  tBits = tBits | ( 1 << ( bitOffSet + fTriggerBitConfig->GetJetHighBit() ));
915  // Add offline bit - it will be handled by the ProcessPatch function
916  tBits = tBits | ( 1 << (kOfflineOffset + fTriggerBitConfig->GetJetHighBit()) );
917  }
919  // Set the trigger bit for jet low - it is needed by the ProcessPatch function
920  // in order to handle jet patches - for offline and recalc patches these bits will
921  // be removed later
922  tBits = tBits | ( 1 << ( bitOffSet + fTriggerBitConfig->GetJetLowBit() ));
923  // Add recalc bit - it will be handled by the ProcessPatch function
924  tBits = tBits | ( 1 << (kRecalcOffset + fTriggerBitConfig->GetJetLowBit()) );
925  }
927  // Set the trigger bit for jet high - it is needed by the ProcessPatch function
928  // in order to handle jet patches - for offline and recalc patches these bits will
929  // be removed later
930  tBits = tBits | ( 1 << ( bitOffSet + fTriggerBitConfig->GetJetHighBit() ));
931  // Add recalc bit - it will be handled by the ProcessPatch function
932  tBits = tBits | ( 1 << (kRecalcOffset + fTriggerBitConfig->GetJetHighBit()) );
933  }
934 
935  // add trigger values
936  if (tBits != 0) {
937  tBitsArray.Set( tBitsArray.GetSize() + 1 );
938  colArray.Set( colArray.GetSize() + 1 );
939  rowArray.Set( rowArray.GetSize() + 1 );
940  tBitsArray[tBitsArray.GetSize()-1] = tBits;
941  colArray[colArray.GetSize()-1] = i;
942  rowArray[rowArray.GetSize()-1] = j;
943  }
944  }
945  } // trigger algo
946 
947  // Set trigger bits for the maximum patch
948  if (maxPatchADC > fCaloTriggerSetupOut->GetThresholdJetLowSimple()){
949  // Set the trigger bit for jet low - it is needed by the ProcessPatch function
950  // in order to handle jet patches - for offline and recalc patches these bits will
951  // be removed later
952  tBitsArray[0] = tBitsArray[0] | ( 1 << ( bitOffSet + fTriggerBitConfig->GetJetLowBit() ));
953  // Add recalc bit - it will be handled by the ProcessPatch function
954  tBitsArray[0] = tBitsArray[0] | ( 1 << (kRecalcOffset + fTriggerBitConfig->GetJetLowBit()) );
955  }
956  if (maxPatchADC > fCaloTriggerSetupOut->GetThresholdJetHighSimple()){
957  // Set the trigger bit for jet high - it is needed by the ProcessPatch function
958  // in order to handle jet patches - for offline and recalc patches these bits will
959  // be removed later
960  tBitsArray[0] = tBitsArray[0] | ( 1 << ( bitOffSet + fTriggerBitConfig->GetJetHighBit() ));
961  // Add recalc bit - it will be handled by the ProcessPatch function
962  tBitsArray[0] = tBitsArray[0] | ( 1 << (kRecalcOffset + fTriggerBitConfig->GetJetHighBit()) );
963  }
964  if(maxPatchADCoffline > fCaloTriggerSetupOut->GetThresholdJetLowSimple()){
965  // Set the trigger bit for jet low - it is needed by the ProcessPatch function
966  // in order to handle jet patches - for offline and recalc patches these bits will
967  // be removed later
968  tBitsArray[1] = tBitsArray[1] | ( 1 << ( bitOffSet + fTriggerBitConfig->GetJetLowBit() ));
969  // Add offline bit - it will be handled by the ProcessPatch function
970  tBitsArray[1] = tBitsArray[1] | ( 1 << (kOfflineOffset + fTriggerBitConfig->GetJetLowBit()) );
971  }
972  if (maxPatchADCoffline > fCaloTriggerSetupOut->GetThresholdJetHighSimple()){
973  // Set the trigger bit for jet high - it is needed by the ProcessPatch function
974  // in order to handle jet patches - for offline and recalc patches these bits will
975  // be removed later
976  tBitsArray[1] = tBitsArray[1] | ( 1 << ( bitOffSet + fTriggerBitConfig->GetJetHighBit() ));
977  // Add offline bit - it will be handled by the ProcessPatch function
978  tBitsArray[1] = tBitsArray[1] | ( 1 << (kOfflineOffset + fTriggerBitConfig->GetJetHighBit()) );
979  }
980 
981 
982 
983  // 4x4 trigger algo, stepping by 2 towers (= 1 trigger channel)
984  maxPatchADC = -1;
985  maxPatchADCoffline = -1;
986 
987  for (Int_t i = 0; i <= (maxCol-2); ++i) {
988  for (Int_t j = 0; j <= (maxRow-2); ++j) {
989  Int_t tSum = 0;
990  Double_t tSumOffline = 0;
991  Int_t tBits = 0;
992 
993  // window
994  for (Int_t k = 0; k < 2; ++k) {
995  for (Int_t l = 0; l < 2; ++l) {
996  tSumOffline += (*fPatchADCSimple)(i+k,j+l);
997  tSum += static_cast<ULong64_t>((*fPatchADC)(i+k,j+l));
998  }
999  }
1000 
1001  if (tSum > maxPatchADC) { // Mark highest Gamma patch
1002  maxPatchADC = tSum;
1003  colArray[2] = i;
1004  rowArray[2] = j;
1005  }
1006  if (tSumOffline > maxPatchADCoffline) { // Mark highest Gamma patch
1007  maxPatchADCoffline = tSumOffline;
1008  colArray[3] = i;
1009  rowArray[3] = j;
1010  }
1011 
1012  // check thresholds
1013  if (tSumOffline > fCaloTriggerSetupOut->GetThresholdGammaLowSimple()){
1014  // Set the trigger bit for gamma low - it is needed by the ProcessPatch function
1015  // in order to handle gamma patches - for offline and recalc patches these bits will
1016  // be removed later
1017  tBits = tBits | ( 1 << ( bitOffSet + fTriggerBitConfig->GetGammaLowBit() ));
1018  // Add offline bit - it will be handled by the ProcessPatch function
1019  tBits = tBits | ( 1 << (kOfflineOffset + fTriggerBitConfig->GetGammaLowBit()) );
1020  }
1021  if (tSumOffline > fCaloTriggerSetupOut->GetThresholdGammaHighSimple()){
1022  // Set the trigger bit for gamma high - it is needed by the ProcessPatch function
1023  // in order to handle gamma patches - for offline and recalc patches these bits will
1024  // be removed later
1025  tBits = tBits | ( 1 << ( bitOffSet + fTriggerBitConfig->GetGammaHighBit() ));
1026  // Add offline bit - it will be handled by the ProcessPatch function
1027  tBits = tBits | ( 1 << (kOfflineOffset + fTriggerBitConfig->GetGammaHighBit()) );
1028  }
1030  // Set the trigger bit for gamma low - it is needed by the ProcessPatch function
1031  // in order to handle gamma patches - for offline and recalc patches these bits will
1032  // be removed later
1033  tBits = tBits | ( 1 << ( bitOffSet + fTriggerBitConfig->GetGammaLowBit() ));
1034  // Add recalc bit - it will be handled by the ProcessPatch function
1035  tBits = tBits | ( 1 << (kRecalcOffset + fTriggerBitConfig->GetGammaLowBit()) );
1036  }
1038  // Set the trigger bit for gamma high - it is needed by the ProcessPatch function
1039  // in order to handle gamma patches - for offline and recalc patches these bits will
1040  // be removed later
1041  tBits = tBits | ( 1 << ( bitOffSet + fTriggerBitConfig->GetGammaHighBit() ));
1042  // Add recalc bit - it will be handled by the ProcessPatch function
1043  tBits = tBits | ( 1 << (kRecalcOffset + fTriggerBitConfig->GetGammaHighBit()) );
1044  }
1045 
1046  // add trigger values
1047  if (tBits != 0) {
1048  tBitsArray.Set( tBitsArray.GetSize() + 1 );
1049  colArray.Set( colArray.GetSize() + 1 );
1050  rowArray.Set( rowArray.GetSize() + 1 );
1051  tBitsArray[tBitsArray.GetSize()-1] = tBits;
1052  colArray[colArray.GetSize()-1] = i;
1053  rowArray[rowArray.GetSize()-1] = j;
1054  }
1055  }
1056  } // trigger algo
1057 
1058  // Set bits for the maximum patch
1059  if (maxPatchADC > fCaloTriggerSetupOut->GetThresholdGammaLowSimple()){
1060  // Set the trigger bit for gamma low - it is needed by the ProcessPatch function
1061  // in order to handle gamma patches - for offline and recalc patches these bits will
1062  // be removed later
1063  tBitsArray[2] = tBitsArray[2] | ( 1 << ( bitOffSet + fTriggerBitConfig->GetGammaLowBit() ));
1064  // Add recalc bit - it will be handled by the ProcessPatch function
1065  tBitsArray[2] = tBitsArray[2] | ( 1 << (kRecalcOffset + fTriggerBitConfig->GetGammaLowBit()) );
1066  }
1067  if (maxPatchADC > fCaloTriggerSetupOut->GetThresholdGammaHighSimple()){
1068  // Set the trigger bit for gamma high - it is needed by the ProcessPatch function
1069  // in order to handle gamma patches - for offline and recalc patches these bits will
1070  // be removed later
1071  tBitsArray[2] = tBitsArray[2] | ( 1 << ( bitOffSet + fTriggerBitConfig->GetGammaHighBit() ));
1072  // Add recalc bit - it will be handled by the ProcessPatch function
1073  tBitsArray[2] = tBitsArray[2] | ( 1 << (kRecalcOffset + fTriggerBitConfig->GetGammaHighBit()) );
1074  }
1075  if (maxPatchADCoffline > fCaloTriggerSetupOut->GetThresholdGammaLowSimple()){
1076  // Set the trigger bit for gamma low - it is needed by the ProcessPatch function
1077  // in order to handle gamma patches - for offline and recalc patches these bits will
1078  // be removed later
1079  tBitsArray[3] = tBitsArray[3] | ( 1 << ( bitOffSet + fTriggerBitConfig->GetGammaLowBit() ));
1080  // Add offline bit - it will be handled by the ProcessPatch function
1081  tBitsArray[3] = tBitsArray[3] | ( 1 << (kOfflineOffset + fTriggerBitConfig->GetGammaLowBit()) );
1082  }
1083  if (maxPatchADCoffline > fCaloTriggerSetupOut->GetThresholdGammaHighSimple()){
1084  // Set the trigger bit for gamma high - it is needed by the ProcessPatch function
1085  // in order to handle gamma patches - for offline and recalc patches these bits will
1086  // be removed later
1087  tBitsArray[3] = tBitsArray[3] | ( 1 << ( bitOffSet + fTriggerBitConfig->GetGammaHighBit() ));
1088  // Add offline bit - it will be handled by the ProcessPatch function
1089  tBitsArray[3] = tBitsArray[3] | ( 1 << (kOfflineOffset + fTriggerBitConfig->GetGammaHighBit()) );
1090  }
1091 
1092  // save in object
1093  fSimpleOfflineTriggers->DeAllocate();
1094  if(tBitsArray.GetSize() - 4 > 0){
1095  fSimpleOfflineTriggers->Allocate(tBitsArray.GetSize() - 4);
1096  for (Int_t i = 4; i < tBitsArray.GetSize(); ++i){
1097  fSimpleOfflineTriggers->Add(colArray[i],rowArray[i], 0, 0, 0, 0, 0, tBitsArray[i]);
1098  }
1099  }
1100 
1101  // @TODO: Implement QA of the main patches
1102 }
1103 
1110 {
1111 
1112  isOfflineSimple = kFALSE;
1113  Bool_t loopContinue = fCaloTriggers->Next();
1114  if (!loopContinue) {
1115  loopContinue = fSimpleOfflineTriggers->Next();
1116  isOfflineSimple = kTRUE;
1117  }
1118  return loopContinue;
1119 }
1120 
1127 Bool_t AliEmcalTriggerMaker::CheckForL0(const AliVCaloTrigger& trg) const {
1128  Int_t row(-1), col(-1); trg.GetPosition(col, row);
1129  if(col < 0 || row < 0){
1130  AliError(Form("Patch outside range [col %d, row %d]", col, row));
1131  return kFALSE;
1132  }
1133  Int_t truref(-1), trumod(-1), absFastor(-1), adc(-1);
1134  fGeom->GetAbsFastORIndexFromPositionInEMCAL(col, row, absFastor);
1135  fGeom->GetTRUFromAbsFastORIndex(absFastor, truref, adc);
1136  int nvalid(0);
1137  const int kNRowsPhi = fGeom->GetNTotalTRU() * 2;
1138  for(int ipos = 0; ipos < 2; ipos++){
1139  if(row + ipos >= kNRowsPhi) continue; // boundary check
1140  for(int jpos = 0; jpos < 2; jpos++){
1141  if(col + jpos >= kColsEta) continue; // boundary check
1142  // Check whether we are in the same TRU
1143  trumod = -1;
1144  fGeom->GetAbsFastORIndexFromPositionInEMCAL(col+jpos, row+ipos, absFastor);
1145  fGeom->GetTRUFromAbsFastORIndex(absFastor, trumod, adc);
1146  if(trumod != truref) continue;
1147  if(col + jpos >= kColsEta) AliError(Form("Boundary error in col [%d, %d + %d]", col + jpos, col, jpos));
1148  if(row + ipos >= kNRowsPhi) AliError(Form("Boundary error in row [%d, %d + %d]", row + ipos, row, ipos));
1149  Char_t l0times = (*fLevel0TimeMap)(col + jpos,row + ipos);
1150  if(l0times > 7 && l0times < 10) nvalid++;
1151  }
1152  }
1153  if (nvalid != 4) return false;
1154  return true;
1155 }
Bool_t fRejectOffAcceptancePatches
Switch for rejection of patches outside the acceptance.
TString fCaloTriggersOutName
name of output track array
AliEMCALTriggerPatchInfo * ProcessPatch(TriggerMakerTriggerType_t type, TriggerMakerPatchSource_t patchSource)
double Double_t
Definition: External.C:58
Class to make array of trigger patch objects in AOD/ESD events.
Old configuration, no distinction between high and low threshold.
AliEMCALTriggerDataGrid< double > * fPatchADCSimple
! patch map for simple offline trigger
TriggerMakerBitConfig_t fUseTriggerBitConfig
type of trigger config
Base task in the EMCAL framework.
TriggerMakerTriggerType_t
Definition of different trigger patch types.
Bool_t fDoQA
Fill QA histograms.
void FillTH2(const char *hname, double x, double y, double weight=1., Option_t *opt="")
char Char_t
Definition: External.C:18
Int_t fITrigger
! trigger counter
static const int kColsEta
Number of columns in eta direction.
New configuration, distiction between high and low threshold.
static const TString fgkTriggerTypeNames[5]
Histogram name tags.
const AliEMCALTriggerBitConfig * fTriggerBitConfig
Trigger bit configuration, aliroot-dependent.
TH2 * CreateTH2(const char *name, const char *title, int nbinsx, double xmin, double xmax, int nbinsy, double ymin, double ymax, Option_t *opt="")
int Int_t
Definition: External.C:63
Trigger bit indicating the main (highest energy) trigger patch of a given type per event...
AliEMCALTriggerDataGrid< float > * fPatchAmplitudes
! TRU Amplitudes (for L0)
THashList * GetListOfHistograms() const
Definition: THistManager.h:504
Bool_t IsEGA(Int_t tBits) const
float Float_t
Definition: External.C:68
AliEMCALGeometry * fGeom
!emcal geometry
TString fCaloTriggersName
name of calo triggers collection
Bool_t IsOfflineSimple(Int_t tBits) const
TH1 * CreateTH1(const char *name, const char *title, int nbins, double xmin, double xmax, Option_t *opt="")
Int_t fThresholdConstants[4][3]
simple offline trigger thresholds constants
Bool_t IsEJE(Int_t tBits) const
AliEMCALTriggerChannelContainer fBadChannels
Container of bad channels.
TString fCaloCellsName
name of calo cell collection
TString fV0InName
name of output track array
Bool_t IsRecalc(Int_t tBits) const
Int_t fDebugLevel
void FillTH1(const char *hname, double x, double weight=1., Option_t *opt="")
Manager for constants used in the trigger maker.
AliEmcalTriggerSetupInfo * fCaloTriggerSetupOut
! trigger setup
Bool_t Data(TH1F *h, Double_t *rangefit, Bool_t writefit, Double_t &sgn, Double_t &errsgn, Double_t &bkg, Double_t &errbkg, Double_t &sgnf, Double_t &errsgnf, Double_t &sigmafit, Int_t &status)
Int_t fDebugLevel
Debug lebel;.
short Short_t
Definition: External.C:23
AliVCaloCells * fCaloCells
!cells
AliVVZERO * fV0
! V0 object
AliAODCaloTrigger * fSimpleOfflineTriggers
! simple offline trigger
Bool_t isMC
EMCAL trigger patch maker.
AliEmcalList * fOutput
!output list
TClonesArray * fCaloTriggersOut
! trigger array out
THistManager * fQAHistos
! Histograms for QA
ClassImp(AliAnalysisTaskCRC) AliAnalysisTaskCRC
Double_t fVertex[3]
!event vertex
Container class for histograms for the high- charged particle analysis.
Definition: THistManager.h:43
Int_t GetRunNumber(TString)
Definition: PlotMuonQA.C:2235
AliVCaloTrigger * fCaloTriggers
!calo triggers
bool Bool_t
Definition: External.C:53
AliEMCALTriggerDataGrid< char > * fLevel0TimeMap
! Map needed to store the level0 times
Bool_t fInitialized
whether or not the task has been already initialized
TString fCaloTriggerSetupOutName
name of output track array
Settings manager for the trigger patch algorithmThis class contains the main settings (trigger thresh...
void SetThresholdsSimple(Int_t i0, Int_t i1, Int_t i2, Int_t i3)
Bitmask for Offline simple patches.
Bool_t NextTrigger(Bool_t &isOfflineSimple)
void SetThresholds(Int_t i0, Int_t i1, Int_t i2, Int_t i3)
Bool_t CheckForL0(const AliVCaloTrigger &trg) const
AliEMCALTriggerDataGrid< int > * fPatchADC
! ADC values map