AliPhysics  5b5fbb3 (5b5fbb3)
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 
38 ClassImp(AliEmcalTriggerMaker)
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"),
86  fTriggerBitConfig(NULL),
90  fV0(0),
91  fPatchAmplitudes(NULL),
92  fPatchADCSimple(NULL),
93  fPatchADC(NULL),
94  fLevel0TimeMap(NULL),
95  fITrigger(0),
96  fDoQA(doQA),
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 (!fLocalInitialized)
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  fLocalInitialized = 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  fLocalInitialized = 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.
Bool_t fLocalInitialized
whether or not the task has been already initialized
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="")
Fill a 2D histogram within the container.
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="")
Create a new TH2 within the container.
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
Get the list of histograms.
Definition: THistManager.h:671
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="")
Create a new TH1 within the container.
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="")
Fill a 1D histogram within the container.
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
Double_t fVertex[3]
!event vertex
Container class for histograms.
Definition: THistManager.h:99
virtual void ExecOnce()
Perform steps needed to initialize the analysis.
Int_t GetRunNumber(TString)
Definition: PlotMuonQA.C:2235
AliVCaloTrigger * fCaloTriggers
!calo triggers
void UserCreateOutputObjects()
Main initialization function on the worker.
bool Bool_t
Definition: External.C:53
AliEMCALTriggerDataGrid< char > * fLevel0TimeMap
! Map needed to store the level0 times
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