AliPhysics  vAN-20151012 (2287573)
 All Classes Namespaces Files Functions Variables Enumerations Enumerator Macros
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 "AliEMCALTriggerTypes.h"
23 #include "AliLog.h"
24 #include "AliVCaloCells.h"
25 #include "AliVCaloTrigger.h"
26 #include "AliVVZERO.h"
27 #include "AliEmcalTriggerMaker.h"
28 
29 #include "THistManager.h"
30 #include "TString.h"
31 
32 #include <bitset>
33 
36 ClassImp(AliEmcalTriggerMaker::AliEmcalTriggerChannelPosition)
37 ClassImp(AliEmcalTriggerMaker::AliEmcalTriggerChannelContainer)
39 
40 using namespace std;
41 
42 const TString AliEmcalTriggerMaker::fgkTriggerTypeNames[5] = {"EJE", "EGA", "EL0", "REJE", "REGA"};
43 
48  AliAnalysisTaskEmcal("AliEmcalTriggerMaker",kFALSE),
49  fCaloTriggersOutName("EmcalTriggers"),
50  fCaloTriggerSetupOutName("EmcalTriggersSetup"),
51  fV0InName("AliAODVZERO"),
52  fUseTriggerBitConfig(kNewConfig),
53  fTriggerBitConfig(NULL),
54  fCaloTriggersOut(0),
55  fCaloTriggerSetupOut(0),
56  fSimpleOfflineTriggers(0),
57  fV0(0),
58  fITrigger(0),
59  fRejectOffAcceptancePatches(kFALSE),
60  fDoQA(kFALSE),
61  fQAHistos(NULL)
62 {
68  memset(fThresholdConstants, 0, sizeof(Int_t) * 12);
69  memset(fPatchADCSimple, 0, sizeof(Double_t) * kPatchCols * kPatchRows);
70  memset(fPatchADC, 0, sizeof(Int_t) * kPatchCols * kPatchRows);
71  memset(fPatchAmplitudes, 0, sizeof(Float_t) * kPatchCols * kPatchRows);
72  memset(fLevel0TimeMap, 0, sizeof(Char_t) * kPatchCols * kPatchRows);
73 }
74 
80 AliEmcalTriggerMaker::AliEmcalTriggerMaker(const char *name, Bool_t doQA) :
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  fITrigger(0),
92  fRejectOffAcceptancePatches(kFALSE),
93  fDoQA(doQA),
94  fQAHistos(NULL)
95 {
96  // Constructor.
102  memset(fThresholdConstants, 0, sizeof(Int_t) * 12);
103  memset(fPatchAmplitudes, 0, sizeof(Float_t) * kPatchCols * kPatchRows);
104  memset(fPatchADCSimple, 0, sizeof(Double_t) * kPatchCols * kPatchRows);
105  memset(fPatchADC, 0, sizeof(Int_t) * kPatchCols * kPatchRows);
106  memset(fLevel0TimeMap, 0, sizeof(Char_t) * kPatchCols * kPatchRows);
107 }
108 
113 {
115 }
116 
121 {
123 
124  if (!fInitialized)
125  return;
126 
127  if(!fTriggerBitConfig){
128  switch(fUseTriggerBitConfig){
129  case kNewConfig:
131  break;
132  case kOldConfig:
134  break;
135  }
136  }
137 
138  if (!fCaloTriggersOutName.IsNull()) {
139  fCaloTriggersOut = new TClonesArray("AliEmcalTriggerPatchInfo");
141 
142  if (!(InputEvent()->FindListObject(fCaloTriggersOutName))) {
143  InputEvent()->AddObject(fCaloTriggersOut);
144  }
145  else {
146  fInitialized = kFALSE;
147  AliFatal(Form("%s: Container with same name %s already present. Aborting", GetName(), fCaloTriggersOutName.Data()));
148  return;
149  }
150  }
151 
152  if (!fCaloTriggerSetupOutName.IsNull()) {
155 
156  if (!(InputEvent()->FindListObject(fCaloTriggerSetupOutName))) {
157  InputEvent()->AddObject(fCaloTriggerSetupOut);
158  }
159  else {
160  fInitialized = kFALSE;
161  AliFatal(Form("%s: Container with same name %s already present. Aborting", GetName(), fCaloTriggerSetupOutName.Data()));
162  return;
163  }
164  }
165 
166  if ( ! fV0InName.IsNull()) {
167  fV0 = (AliVVZERO*)InputEvent()->FindListObject(fV0InName);
168  }
169 
170  // container for simple offline trigger processing
171  fSimpleOfflineTriggers = new AliAODCaloTrigger();
172  fSimpleOfflineTriggers->Allocate(0);
173 }
174 
179 {
181 
182  if(fDoQA && fOutput){
183  fQAHistos = new THistManager("TriggerQA");
184  const char *patchtypes[2] = {"Online", "Offline"};
185 
186  for(int itype = 0; itype < 5; itype++){
187  for(const char **patchtype = patchtypes; patchtype < patchtypes + 2; ++patchtype){
188  fQAHistos->CreateTH2(Form("RCPos%s%s", fgkTriggerTypeNames[itype].Data(), *patchtype), Form("Lower edge position of %s %s patches (col-row);iEta;iPhi", *patchtype, fgkTriggerTypeNames[itype].Data()), 48, -0.5, 47.5, 64, -0.5, 63.5);
189  fQAHistos->CreateTH2(Form("EPCentPos%s%s", fgkTriggerTypeNames[itype].Data(), *patchtype), Form("Center position of the %s %s trigger patches;#eta;#phi", *patchtype, fgkTriggerTypeNames[itype].Data()), 20, -0.8, 0.8, 100, 1., 4.);
190  fQAHistos->CreateTH2(Form("PatchADCvsE%s%s", fgkTriggerTypeNames[itype].Data(), *patchtype), Form("Patch ADC value for trigger type %s %s;Trigger ADC;FEE patch energy (GeV)", *patchtype, fgkTriggerTypeNames[itype].Data()), 2000, 0., 2000, 200, 0., 200);
191  }
192  }
193  fQAHistos->CreateTH1("triggerBitsAll", "Trigger bits for all incoming patches;bit nr", 64, -0.5, 63.5);
194  fQAHistos->CreateTH1("triggerBitsSel", "Trigger bits for reconstructed patches;bit nr", 64, -0.5, 63.5);
195  fOutput->Add(fQAHistos->GetListOfHistograms());
196  PostData(1, fOutput);
197  }
198 }
199 
205 {
206  AliEmcalTriggerPatchInfo *trigger, *triggerMainJet, *triggerMainGamma, *triggerMainLevel0;
207  AliEmcalTriggerPatchInfo *triggerMainJetSimple, *triggerMainGammaSimple;
208 
209  // delete patch array, clear setup object
210  fCaloTriggersOut->Delete();
212 
213  if (!fCaloTriggers) {
214  AliError(Form("Calo triggers container %s not available.", fCaloTriggersName.Data()));
215  return kTRUE;
216  }
217  if (!fCaloCells) {
218  AliError(Form("Calo cells container %s not available.", fCaloCellsName.Data()));
219  return kTRUE;
220  }
221  if (!fCaloCells) {
222  AliError(Form("V0 container %s not available.", fV0InName.Data()));
223  return kTRUE;
224  }
225 
226  // do not process, if sooner than 11h period
227  // 160683 ??
228  if( InputEvent()->GetRunNumber() < 167693 )
229  return kTRUE;
230 
231 // // do not process any MC, since no MC was generated with correct
232 // // EMCal trigger L1 jet trigger simulation, yet
233 // // productions will be enabled, once some correct once are produced
234 // if( MCEvent() != 0 )
235 // return kTRUE;
236 
237  // must reset before usage, or the class will fail
238  fCaloTriggers->Reset();
239 
240  // zero the arrays
241  memset(fPatchADC, 0, sizeof(Int_t) * kPatchCols * kPatchRows);
242  memset(fPatchAmplitudes, 0, sizeof(Float_t) * kPatchCols * kPatchRows);
243  memset(fLevel0TimeMap, 0, sizeof(Char_t) * kPatchCols * kPatchRows);
244 
245  // first run over the patch array to compose a map of 2x2 patch energies
246  // which is then needed to construct the full patch ADC energy
247  // class is not empty
248  if (fCaloTriggers->GetEntries() > 0) {
249 
250  // go throuth the trigger channels
251  while (fCaloTriggers->Next()) {
252  // get position in global 2x2 tower coordinates
253  // A0 left bottom (0,0)
254  Int_t globCol=-1, globRow=-1;
255  fCaloTriggers->GetPosition(globCol, globRow);
256  // exclude channel completely if it is masked as hot channel
257  if(fBadChannels.HasChannel(globCol, globRow)) continue;
258  // for some strange reason some ADC amps are initialized in reconstruction
259  // as -1, neglect those
260  Int_t adcAmp=-1;
261  fCaloTriggers->GetL1TimeSum(adcAmp);
262  if (adcAmp>-1)
263  fPatchADC[globCol][globRow] = adcAmp;
264 
265  // Handling for L0 triggers
266  // For the ADC value we use fCaloTriggers->GetAmplitude()
267  // In data, all patches which have 4 TRUs with proper level0 times are
268  // valid trigger patches. Therefore we need to check all neighbors for
269  // the level0 times, not only the bottom left. In order to obtain this
270  // information, a lookup table with the L0 times for each TRU is created
271  Float_t amplitude(0);
272  fCaloTriggers->GetAmplitude(amplitude);
273  if(amplitude < 0) amplitude = 0;
274  fPatchAmplitudes[globCol][globRow] = amplitude;
275  Int_t nl0times(0);
276  fCaloTriggers->GetNL0Times(nl0times);
277  if(nl0times){
278  TArrayI l0times(nl0times);
279  fCaloTriggers->GetL0Times(l0times.GetArray());
280  for(int itime = 0; itime < nl0times; itime++){
281  if(l0times[itime] >7 && l0times[itime] < 10){
282  fLevel0TimeMap[globCol][globRow] = static_cast<Char_t>(l0times[itime]);
283  break;
284  }
285  }
286  }
287  } // patches
288  } // array not empty
289 
290  // fill the array for offline trigger processing
291  // using calibrated cell energies
292  memset(fPatchADCSimple, 0, sizeof(Double_t) * kPatchRows * kPatchCols); // This works, but in principle cannot assume that the representation for 0 in a double really consists of only zeros...
293 
294  // fill the patch ADCs from cells
295  Int_t nCell = fCaloCells->GetNumberOfCells();
296  for(Int_t iCell = 0; iCell < nCell; ++iCell) {
297  // get the cell info, based in index in array
298  Short_t cellId = fCaloCells->GetCellNumber(iCell);
299  Double_t amp = fCaloCells->GetAmplitude(iCell);
300  // get position
301  Int_t absId=-1;
302  fGeom->GetFastORIndexFromCellIndex(cellId, absId);
303  Int_t globCol=-1, globRow=-1;
304  fGeom->GetPositionInEMCALFromAbsFastORIndex(absId, globCol, globRow);
305  // add
306  fPatchADCSimple[globCol][globRow] += amp/kEMCL1ADCtoGeV;
307  }
308 
309  // dig out common data (thresholds)
310  // 0 - jet high, 1 - gamma high, 2 - jet low, 3 - gamma low
312  fCaloTriggers->GetL1Threshold(1),
313  fCaloTriggers->GetL1Threshold(2),
314  fCaloTriggers->GetL1Threshold(3));
315 
316  // get the V0 value and compute and set the offline thresholds
317  // get V0, compute thresholds and save them as global parameters
318  Int_t v0[2];
319  v0[0] = fV0->GetTriggerChargeA();
320  v0[1] = fV0->GetTriggerChargeC();
321  ULong64_t v0S = v0[0] + v0[1];
322  fSimpleOfflineTriggers->SetL1V0(v0);
323 
324  for (Int_t i = 0; i < 4; ++i) {
325  // A*V0^2/2^32+B*V0/2^16+C
326  ULong64_t thresh = ( ((ULong64_t)fThresholdConstants[i][0]) * v0S * v0S ) >> 32;
327  thresh += ( ((ULong64_t)fThresholdConstants[i][1]) * v0S ) >> 16;
328  thresh += ((ULong64_t)fThresholdConstants[i][2]);
329  fSimpleOfflineTriggers->SetL1Threshold(i,thresh);
330  }
331 
332  // save the thresholds in output object
334  fSimpleOfflineTriggers->GetL1Threshold(1),
335  fSimpleOfflineTriggers->GetL1Threshold(2),
336  fSimpleOfflineTriggers->GetL1Threshold(3));
337 
338  // run the trigger
340 
341  // reset for re-run
342  fCaloTriggers->Reset();
343  fSimpleOfflineTriggers->Reset();
344 
345  // class is not empty
346  if (fCaloTriggers->GetEntries() > 0 || fSimpleOfflineTriggers->GetEntries() > 0) {
347  fITrigger = 0;
348  triggerMainGamma = 0;
349  triggerMainJet = 0;
350  triggerMainGammaSimple = 0;
351  triggerMainJetSimple = 0;
352  triggerMainLevel0 = 0;
353 
354  // go throuth the trigger channels, real first, then offline
355  Bool_t isOfflineSimple=0;
356  while (NextTrigger(isOfflineSimple)) {
357  // process jet
359  trigger = ProcessPatch(kTMEMCalJet, isOfflineSimple);
360  // save main jet triggers in event
361  if (trigger != 0) {
362  // check if more energetic than others for main patch marking
363  if (!isOfflineSimple) {
364  if (triggerMainJet == 0 || (triggerMainJet->GetPatchE() < trigger->GetPatchE()))
365  triggerMainJet = trigger;
366  } else {
367  if (triggerMainJetSimple == 0 || (triggerMainJetSimple->GetPatchE() < trigger->GetPatchE()))
368  triggerMainJetSimple = trigger;
369  }
370  }
371  }
372 
373  // process gamma
375  trigger = ProcessPatch(kTMEMCalGamma, isOfflineSimple);
376  // save main gamma triggers in event
377  if (trigger != 0) {
378  // check if more energetic than others for main patch marking
379  if (!isOfflineSimple) {
380  if (triggerMainGamma == 0 || (triggerMainGamma->GetPatchE() < trigger->GetPatchE()))
381  triggerMainGamma = trigger;
382  } else {
383  if (triggerMainGammaSimple == 0 || (triggerMainGammaSimple->GetPatchE() < trigger->GetPatchE()))
384  triggerMainGammaSimple = trigger;
385  }
386  }
387  }
388 
389  // level 0 triggers (only in case of online patches)
390  if(!isOfflineSimple){
392  trigger = ProcessPatch(kTMEMCalLevel0, kFALSE);
393  // save main level0 trigger in the event
394  if (trigger) {
395  if (!triggerMainLevel0 || (triggerMainLevel0->GetPatchE() < trigger->GetPatchE()))
396  triggerMainLevel0 = trigger;
397  }
398  }
399  }
400 
401  // Recalculated triggers (max patches without threshold)
403  ProcessPatch(kTMEMCalRecalcJet, isOfflineSimple);
405  ProcessPatch(kTMEMCalRecalcGamma, isOfflineSimple);
406  } // triggers
407 
408  // mark the most energetic patch as main
409  // for real and also simple offline
410  if (triggerMainJet != 0) {
411  Int_t tBits = triggerMainJet->GetTriggerBits();
412  // main trigger flag
413  tBits = tBits | ( 1 << AliEmcalTriggerPatchInfo::kMainTriggerBitNum );
414  triggerMainJet->SetTriggerBits( tBits );
415  }
416  if (triggerMainJetSimple != 0) {
417  Int_t tBits = triggerMainJetSimple->GetTriggerBits();
418  // main trigger flag
419  tBits = tBits | ( 1 << AliEmcalTriggerPatchInfo::kMainTriggerBitNum );
420  triggerMainJetSimple->SetTriggerBits(tBits);
421  }
422  if (triggerMainGamma != 0) {
423  Int_t tBits = triggerMainGamma->GetTriggerBits();
424  // main trigger flag
425  tBits = tBits | ( 1 << AliEmcalTriggerPatchInfo::kMainTriggerBitNum );
426  triggerMainGamma->SetTriggerBits( tBits );
427  }
428  if (triggerMainGammaSimple != 0) {
429  Int_t tBits = triggerMainGammaSimple->GetTriggerBits();
430  // main trigger flag
431  tBits = tBits | ( 1 << AliEmcalTriggerPatchInfo::kMainTriggerBitNum );
432  triggerMainGammaSimple->SetTriggerBits( tBits );
433  }
434  if(triggerMainLevel0){
435  Int_t tBits = triggerMainLevel0->GetTriggerBits();
436  // main trigger flag
438  triggerMainLevel0->SetTriggerBits(tBits);
439  }
440  } // there are some triggers
441 
442  // Diagnostics
443  int npatchOnline = 0;
444  for(TIter patchIter = TIter(fCaloTriggersOut).Begin(); patchIter != TIter::End(); ++patchIter){
445  AliEmcalTriggerPatchInfo *mypatch = static_cast<AliEmcalTriggerPatchInfo *>(*patchIter);
446  if(mypatch->IsOfflineSimple()) continue;
447  AliDebug(1,Form("Patch with bits: %s, types: JH[%s], JL[%s], GH[%s], GL[%s], L0[%s]",
448  std::bitset<sizeof(int)*4>(mypatch->GetTriggerBits()).to_string().c_str(),
449  (mypatch->IsJetHigh() ? "y" : "n"), (mypatch->IsJetLow() ? "y" : "n"),
450  (mypatch->IsGammaHigh() ? "y" : "n"), (mypatch->IsGammaLow() ? "y" : "n"),(mypatch->IsLevel0() ? "y" : "n")));
451  npatchOnline++;
452  }
453  AliDebug(1, Form("Number of online patches: %d", npatchOnline));
454 
455  return kTRUE;
456 }
457 
466 {
467  Int_t tBits=-1;
468  if (!isOfflineSimple)
469  fCaloTriggers->GetTriggerBits(tBits);
470  else
471  fSimpleOfflineTriggers->GetTriggerBits(tBits);
472 
473  if(fDoQA){
474  for(unsigned int ibit = 0; ibit < sizeof(tBits)*8; ibit++) {
475  if(tBits & (1 << ibit)){
476  fQAHistos->FillTH1("triggerBitsAll", ibit);
477  }
478  }
479  }
480 
481  if ((type == kTMEMCalJet && !IsEJE( tBits )) ||
482  (type == kTMEMCalGamma && !IsEGA( tBits )) ||
483  (type == kTMEMCalLevel0 && !(CheckForL0(*fCaloTriggers))) ||
484  (type == kTMEMCalRecalcJet && (tBits & (1 << AliEmcalTriggerPatchInfo::kRecalcJetBitNum))==0) ||
485  (type == kTMEMCalRecalcGamma && (tBits & (1 << AliEmcalTriggerPatchInfo::kRecalcGammaBitNum))==0) )
486  return 0;
487 
488  // save primary vertex in vector
489  TVector3 vertex;
490  vertex.SetXYZ(fVertex[0], fVertex[1], fVertex[2]);
491 
492  // get position in global 2x2 tower coordinates
493  // A0 left bottom (0,0)
494  Int_t globCol=-1, globRow=-1;
495  if (!isOfflineSimple)
496  fCaloTriggers->GetPosition(globCol,globRow);
497  else
498  fSimpleOfflineTriggers->GetPosition(globCol, globRow);
499 
500  // Markus: For the moment reject jet patches with a row larger than 44 to overcome
501  // an issue with patches containing inactive TRUs
502  // (last 2 supermodules inactive but still included in the reconstruction)
503  Int_t runno = InputEvent()->GetRunNumber();
504  if(runno > 176000 && runno <= 197692){
505  // Valid only for 2012 geometry
506  if((type == kTMEMCalJet && IsEJE( tBits )) && (globRow > 44)) { // Hard coded number in order to be insensitive to changes in the geometry
507  AliDebug(1, Form("Jet patch in inactive area: row[%d]", globRow));
508  return NULL;
509  }
510  }
511 
513  int patchsize = 2;
514  if(type == kTMEMCalJet || type == kTMEMCalRecalcJet) patchsize = 16;
515  if((globCol + patchsize >= kPatchCols) || (globCol + patchsize >= kPatchRows)){
516  AliError(Form("Invalid patch position for patch type %s: Col[%d], Row[%d] - patch rejected", fgkTriggerTypeNames[type].Data(), globCol, globRow));
517  return NULL;
518  }
519  }
520 
521  // get the absolute trigger ID
522  Int_t absId=-1;
523  fGeom->GetAbsFastORIndexFromPositionInEMCAL(globCol, globRow, absId);
524  // convert to the 4 absId of the cells composing the trigger channel
525  Int_t cellAbsId[4]={-1,-1,-1,-1};
526  fGeom->GetCellIndexFromFastORIndex(absId, cellAbsId);
527 
528  // get low left edge (eta max, phi min)
529  TVector3 edge1;
530  fGeom->GetGlobal(cellAbsId[0], edge1);
531  Int_t colEdge1 = globCol, rowEdge1 = globRow, absIdEdge1 = absId, cellIdEdge1 = cellAbsId[0]; // Used in warning for invalid patch position
532 
533  // sum the available energy in the 32/32 window of cells
534  // step over trigger channels and get all the corresponding cells
535  // make CM
536  Float_t amp = 0;
537  Float_t cmiCol = 0;
538  Float_t cmiRow = 0;
539  Int_t adcAmp = 0;
540  Double_t adcOfflineAmp = 0;
541  int nfastor = (type == kTMEMCalJet || type == kTMEMCalRecalcJet) ? 16 : 2; // 32x32 cell window for L1 Jet trigger, 4x4 for L1 Gamma or L0 trigger
542  for (Int_t i = 0; i < nfastor; ++i) {
543  for (Int_t j = 0; j < nfastor; ++j) {
544  // get the 4 cells composing the trigger channel
545  fGeom->GetAbsFastORIndexFromPositionInEMCAL(globCol+i, globRow+j, absId);
546  fGeom->GetCellIndexFromFastORIndex(absId, cellAbsId);
547  // add amplitudes and find patch edges
548  for (Int_t k = 0; k < 4; ++k) {
549  Float_t ca = fCaloCells->GetCellAmplitude(cellAbsId[k]);
550  //fGeom->GetGlobal(cellAbsId[k], cellCoor);
551  amp += ca;
552  cmiCol += ca*(Float_t)i;
553  cmiRow += ca*(Float_t)j;
554  }
555  // add the STU ADCs in the patch (in case of L1) or the TRU Amplitude (in case of L0)
556  if(type == kTMEMCalLevel0){
557  adcAmp += static_cast<Int_t>(fPatchAmplitudes[globCol+i][globRow+j] * 4); // precision loss in case of global integer field
558  } else {
559  adcAmp += fPatchADC[globCol+i][globRow+j];
560  }
561 
562  adcOfflineAmp += fPatchADCSimple[globCol+i][globRow+j];
563  }
564  }
565 
566  if (amp == 0) {
567  AliDebug(2,"EMCal trigger patch with 0 energy.");
568  return 0;
569  }
570 
571  // get the CM and patch index
572  cmiCol /= amp;
573  cmiRow /= amp;
574  Int_t cmCol = globCol + (Int_t)cmiCol;
575  Int_t cmRow = globRow + (Int_t)cmiRow;
576 
577  // get the patch and corresponding cells
578  fGeom->GetAbsFastORIndexFromPositionInEMCAL( cmCol, cmRow, absId );
579  fGeom->GetCellIndexFromFastORIndex( absId, cellAbsId );
580 
581  // find which out of the 4 cells is closest to CM and get it's position
582  Int_t cmiCellCol = TMath::Nint(cmiCol * 2.);
583  Int_t cmiCellRow = TMath::Nint(cmiRow * 2.);
584  TVector3 centerMass;
585  fGeom->GetGlobal(cellAbsId[(cmiCellRow%2)*2 + cmiCellCol%2], centerMass);
586 
587  // get up right edge (eta min, phi max)
588  // get the absolute trigger ID
589  Int_t posOffset=-1;
590  switch(type){
591  case kTMEMCalJet:
592  case kTMEMCalRecalcJet:
593  posOffset = 15;
594  break;
595  case kTMEMCalGamma:
596  case kTMEMCalRecalcGamma:
597  posOffset = 1;
598  break;
599  case kTMEMCalLevel0:
600  posOffset = 1;
601  break;
602  default:
603  posOffset = 0;
604  break;
605  };
606  fGeom->GetAbsFastORIndexFromPositionInEMCAL(globCol+posOffset, globRow+posOffset, absId);
607  fGeom->GetCellIndexFromFastORIndex(absId, cellAbsId);
608  TVector3 edge2;
609  fGeom->GetGlobal(cellAbsId[3], edge2);
610  Int_t colEdge2 = globCol+posOffset, rowEdge2 = globRow+posOffset, absIdEdge2 = absId, cellIdEdge2 = cellAbsId[3]; // Used in warning for invalid patch position
611 
612  // get the geometrical center as an average of two diagonally
613  // adjacent patches in the center
614  // picking two diagonally closest cells from the patches
615  switch(type){
616  case kTMEMCalJet:
617  case kTMEMCalRecalcJet:
618  posOffset = 7;
619  break;
620  case kTMEMCalGamma:
621  case kTMEMCalRecalcGamma:
622  posOffset = 0;
623  break;
624  case kTMEMCalLevel0:
625  posOffset = 0;
626  break;
627  default:
628  posOffset = 0;
629  break;
630  };
631  fGeom->GetAbsFastORIndexFromPositionInEMCAL(globCol+posOffset, globRow+posOffset, absId);
632  fGeom->GetCellIndexFromFastORIndex(absId, cellAbsId);
633  TVector3 center1;
634  fGeom->GetGlobal(cellAbsId[3], center1);
635 
636  switch(type){
637  case kTMEMCalJet:
638  case kTMEMCalRecalcJet:
639  posOffset = 8;
640  break;
641  case kTMEMCalGamma:
642  case kTMEMCalRecalcGamma:
643  posOffset = 1;
644  break;
645  case kTMEMCalLevel0:
646  posOffset = 1;
647  break;
648  };
649  fGeom->GetAbsFastORIndexFromPositionInEMCAL(globCol+posOffset, globRow+posOffset, absId);
650  fGeom->GetCellIndexFromFastORIndex(absId, cellAbsId);
651  TVector3 center2;
652  fGeom->GetGlobal(cellAbsId[0], center2);
653 
654  TVector3 centerGeo(center1);
655  centerGeo += center2;
656  centerGeo *= 0.5;
657 
658  // relate all to primary vertex
659  TVector3 edge1tmp = edge1, edge2tmp = edge2; // Used in warning for invalid patch position
660  centerGeo -= vertex;
661  centerMass -= vertex;
662  edge1 -= vertex;
663  edge2 -= vertex;
664  // Check for invalid patch positions
665  if(!(edge1[0] || edge1[1] || edge1[2])){
666  AliWarning(Form("Inconsistency in patch position for edge1: [%f|%f|%f]", edge1[0], edge1[1], edge1[2]));
667  AliWarning("Original vectors:");
668  AliWarning(Form("edge1: [%f|%f|%f]", edge1tmp[0], edge1tmp[1], edge1tmp[2]));
669  AliWarning(Form("vertex: [%f|%f|%f]", vertex[0], vertex[1], vertex[2]));
670  AliWarning(Form("Col: %d, Row: %d, FABSID: %d, Cell: %d", colEdge1, rowEdge1, absIdEdge1, cellIdEdge1));
671  AliWarning(Form("Offline: %s", isOfflineSimple ? "yes" : "no"));
672  }
673  if(!(edge2[0] || edge2[1] || edge2[2])){
674  AliWarning(Form("Inconsistency in patch position for edge2: [%f|%f|%f]", edge2[0], edge2[1], edge2[2]));
675  AliWarning("Original vectors:");
676  AliWarning(Form("edge2: [%f|%f|%f]", edge2tmp[0], edge2tmp[1], edge2tmp[2]));
677  AliWarning(Form("vertex: [%f|%f|%f]", vertex[0], vertex[1], vertex[2]));
678  AliWarning(Form("Col: %d, Row: %d, FABSID: %d, Cell: %d", colEdge2, rowEdge2, absIdEdge2, cellIdEdge2));
679  AliWarning(Form("Offline: %s", isOfflineSimple ? "yes" : "no"));
680  }
681 
682  Int_t isMC = MCEvent() ? 1 : 0;
683  Int_t offSet = (1 - isMC) * fTriggerBitConfig->GetTriggerTypesEnd();
684 
685  // fix tbits .. remove the unwanted type triggers
686  // for Jet and Gamma triggers we remove also the level 0 bit since it will be stored in the level 0 patch
687  // for level 0 we remove all gamma and jet trigger bits
688  switch(type){
689  case kTMEMCalJet:
693  break;
694  case kTMEMCalGamma:
698  break;
699  case kTMEMCalLevel0:
700  // Explicitly set the level 0 bit to overcome the masking out
701  tBits |= 1 << (offSet + fTriggerBitConfig->GetLevel0Bit());
705  break;
706  default: // recalculated patches don't need any action
707  break;
708  };
709 
710  // save the trigger object
711  AliEmcalTriggerPatchInfo *trigger =
712  new ((*fCaloTriggersOut)[fITrigger]) AliEmcalTriggerPatchInfo();
713  fITrigger++;
715  trigger->SetCenterGeo(centerGeo, amp);
716  trigger->SetCenterMass(centerMass, amp);
717  trigger->SetEdge1(edge1, amp);
718  trigger->SetEdge2(edge2, amp);
719  trigger->SetADCAmp(adcAmp);
720  trigger->SetADCOfflineAmp(Int_t(adcOfflineAmp));
721  trigger->SetTriggerBits(tBits);
722  trigger->SetOffSet(offSet);
723  trigger->SetEdgeCell(globCol*2, globRow*2); // from triggers to cells
724  //if(isOfflineSimple)trigger->SetOfflineSimple();
725  if(fDoQA){
726  TString patchtype = isOfflineSimple ? "Offline" : "Online";
727  fQAHistos->FillTH2(Form("RCPos%s%s", fgkTriggerTypeNames[type].Data(), patchtype.Data()), globCol, globRow);
728  fQAHistos->FillTH2(Form("EPCentPos%s%s", fgkTriggerTypeNames[type].Data(), patchtype.Data()), centerGeo.Eta(), centerGeo.Phi());
729  fQAHistos->FillTH2(Form("PatchADCvsE%s%s", fgkTriggerTypeNames[type].Data(), patchtype.Data()), isOfflineSimple ? adcOfflineAmp : adcAmp, trigger->GetPatchE());
730  // Redo checking of found trigger bits after masking of unwanted triggers
731  for(unsigned int ibit = 0; ibit < sizeof(tBits)*8; ibit++) {
732  if(tBits & (1 << ibit)){
733  fQAHistos->FillTH1("triggerBitsSel", ibit);
734  }
735  }
736  }
737  return trigger;
738 }
739 
749 {
750 
751  TArrayI tBitsArray(4), rowArray(4), colArray(4);
752 
753  // First entries are for recalculated patches
754 
755  tBitsArray[0] = 1 << AliEmcalTriggerPatchInfo::kRecalcJetBitNum;
756  colArray[0] = -1;
757  rowArray[0] = -1;
758 
760  colArray[1] = -1;
761  rowArray[1] = -1;
762 
764  colArray[2] = -1;
765  rowArray[2] = -1;
766 
768  colArray[3] = -1;
769  rowArray[3] = -1;
770 
771  Double_t maxPatchADCoffline = -1;
772  Int_t maxPatchADC = -1;
773  // run the trigger algo, stepping by 8 towers (= 4 trigger channels)
774  Int_t maxCol = 48;
775  Int_t maxRow = fGeom->GetNTotalTRU()*2;
776  // Markus:
777  // temp fix for the number of TRUs in the 2011 PbPb data to 30
778  // @TODO: Fix in the geometry in the OCDB
779  int runnumber = InputEvent()->GetRunNumber();
780  if(runnumber > 139517 && runnumber <= 170593) maxRow = 60;
781  Int_t isMC = MCEvent() ? 1 : 0;
782  Int_t bitOffSet = (1 - isMC) * fTriggerBitConfig->GetTriggerTypesEnd();
783  for (Int_t i = 0; i <= (maxCol-16); i += 4) {
784  for (Int_t j = 0; j <= (maxRow-16); j += 4) {
785  Double_t tSumOffline = 0;
786  Int_t tSum = 0;
787  Int_t tBits = 0;
788  // window
789  for (Int_t k = 0; k < 16; ++k) {
790  for (Int_t l = 0; l < 16; ++l) {
791  tSumOffline += fPatchADCSimple[i+k][j+l];
792  tSum += (ULong64_t)fPatchADC[i+k][j+l];
793  }
794  }
795 
796  if (tSum > maxPatchADC) { // Mark highest Jet patch
797  maxPatchADC = tSum;
798  colArray[0] = i;
799  rowArray[0] = j;
800  }
801 
802  if (tSumOffline > maxPatchADCoffline) { // Mark highest Jet patch
803  maxPatchADCoffline = tSumOffline;
804  colArray[1] = i;
805  rowArray[1] = j;
806  }
807 
808  // check thresholds
809  if (tSumOffline > fCaloTriggerSetupOut->GetThresholdJetLowSimple())
810  tBits = tBits | ( 1 << ( bitOffSet + fTriggerBitConfig->GetJetLowBit() ));
811  if (tSumOffline > fCaloTriggerSetupOut->GetThresholdJetHighSimple())
812  tBits = tBits | ( 1 << ( bitOffSet + fTriggerBitConfig->GetJetHighBit() ));
813 
814  // add trigger values
815  if (tBits != 0) {
816  // add offline bit
817  tBits = tBits | ( 1 << AliEmcalTriggerPatchInfo::kSimpleOfflineBitNum );
818  tBitsArray.Set( tBitsArray.GetSize() + 1 );
819  colArray.Set( colArray.GetSize() + 1 );
820  rowArray.Set( rowArray.GetSize() + 1 );
821  tBitsArray[tBitsArray.GetSize()-1] = tBits;
822  colArray[colArray.GetSize()-1] = i;
823  rowArray[rowArray.GetSize()-1] = j;
824  }
825  }
826  } // trigger algo
827 
828  // 4x4 trigger algo, stepping by 2 towers (= 1 trigger channel)
829  maxPatchADC = -1;
830  maxPatchADCoffline = -1;
831 
832  for (Int_t i = 0; i <= (maxCol-2); ++i) {
833  for (Int_t j = 0; j <= (maxRow-2); ++j) {
834  Int_t tSum = 0;
835  Double_t tSumOffline = 0;
836  Int_t tBits = 0;
837 
838  // window
839  for (Int_t k = 0; k < 2; ++k) {
840  for (Int_t l = 0; l < 2; ++l) {
841  tSumOffline += fPatchADCSimple[i+k][j+l];
842  tSum += (ULong64_t)fPatchADC[i+k][j+l];
843  }
844  }
845 
846  if (tSum > maxPatchADC) { // Mark highest Gamma patch
847  maxPatchADC = tSum;
848  colArray[2] = i;
849  rowArray[2] = j;
850  }
851  if (tSumOffline > maxPatchADCoffline) { // Mark highest Gamma patch
852  maxPatchADCoffline = tSumOffline;
853  colArray[3] = i;
854  rowArray[3] = j;
855  }
856 
857  // check thresholds
859  tBits = tBits | ( 1 << ( bitOffSet + fTriggerBitConfig->GetGammaLowBit() ));
861  tBits = tBits | ( 1 << ( bitOffSet + fTriggerBitConfig->GetGammaHighBit() ));
862 
863  // add trigger values
864  if (tBits != 0) {
865  // add offline bit
866  tBits = tBits | ( 1 << AliEmcalTriggerPatchInfo::kSimpleOfflineBitNum );
867  tBitsArray.Set( tBitsArray.GetSize() + 1 );
868  colArray.Set( colArray.GetSize() + 1 );
869  rowArray.Set( rowArray.GetSize() + 1 );
870  tBitsArray[tBitsArray.GetSize()-1] = tBits;
871  colArray[colArray.GetSize()-1] = i;
872  rowArray[rowArray.GetSize()-1] = j;
873  }
874  }
875  } // trigger algo
876 
877  // save in object
878  fSimpleOfflineTriggers->DeAllocate();
879  fSimpleOfflineTriggers->Allocate(tBitsArray.GetSize());
880  for (Int_t i = 0; i < tBitsArray.GetSize(); ++i){
881  fSimpleOfflineTriggers->Add(colArray[i],rowArray[i], 0, 0, 0, 0, 0, tBitsArray[i]);
882  }
883 }
884 
890 Bool_t AliEmcalTriggerMaker::NextTrigger(Bool_t &isOfflineSimple)
891 {
892 
893  isOfflineSimple = kFALSE;
894  Bool_t loopContinue = fCaloTriggers->Next();
895  if (!loopContinue) {
896  loopContinue = fSimpleOfflineTriggers->Next();
897  isOfflineSimple = kTRUE;
898  }
899  return loopContinue;
900 }
901 
908 Bool_t AliEmcalTriggerMaker::CheckForL0(const AliVCaloTrigger& trg) const {
909  Int_t row(-1), col(-1); trg.GetPosition(col, row);
910  if(col < 0 || row < 0){
911  AliError(Form("Patch outside range [col %d, row %d]", col, row));
912  return kFALSE;
913  }
914  Int_t truref(-1), trumod(-1), absFastor(-1), adc(-1);
915  fGeom->GetAbsFastORIndexFromPositionInEMCAL(col, row, absFastor);
916  fGeom->GetTRUFromAbsFastORIndex(absFastor, truref, adc);
917  int nvalid(0);
918  for(int ipos = 0; ipos < 2; ipos++){
919  if(row + ipos >= kPatchRows) continue; // boundary check
920  for(int jpos = 0; jpos < 2; jpos++){
921  if(col + jpos >= kPatchCols) continue; // boundary check
922  // Check whether we are in the same TRU
923  trumod = -1;
924  fGeom->GetAbsFastORIndexFromPositionInEMCAL(col+jpos, row+ipos, absFastor);
925  fGeom->GetTRUFromAbsFastORIndex(absFastor, trumod, adc);
926  if(trumod != truref) continue;
927  if(col + jpos >= kPatchCols) AliError(Form("Boundary error in col [%d, %d + %d]", col + jpos, col, jpos));
928  if(row + ipos >= kPatchRows) AliError(Form("Boundary error in row [%d, %d + %d]", row + ipos, row, ipos));
929  Char_t l0times = fLevel0TimeMap[col + jpos][row + ipos];
930  if(l0times > 7 && l0times < 10) nvalid++;
931  }
932  }
933  if (nvalid != 4) return false;
934  return true;
935 }
936 
944  if(HasChannel(col, row)) return;
945  fChannels.Add(new AliEmcalTriggerChannelPosition(col, row));
946 }
947 
956  if(fChannels.FindObject(&refChannel)) return true;
957  return false;
958 }
ClassImp(AliAnalysisTaskTriggerRates) AliAnalysisTaskTriggerRates
TString fCaloTriggersOutName
name of output track array
Trigger bit for recalculated jet patches.
Trigger bit indicating the main (highest energy) trigger patch of a given type per event...
Class to make array of trigger patch objects in AOD/ESD events.
Old configuration, no distinction between high and low threshold.
void SetEdge2(TLorentzVector &v)
TriggerMakerBitConfig_t fUseTriggerBitConfig
type of trigger config
Trigger bit for recalculated gamma patches.
TriggerMakerTriggerType_t
Definition of different trigger patch types.
Bool_t fDoQA
Fill QA histograms.
void SetEdge1(TLorentzVector &v)
const AliEmcalTriggerBitConfig * fTriggerBitConfig
Int_t fITrigger
trigger counter
Trigger bit indicating that the patch was created by the offline trigger algorithm.
TList * fOutput
x-section from pythia header
Float_t fPatchAmplitudes[kPatchCols][kPatchRows]
TRU Amplitudes (for L0)
AliEmcalTriggerChannelContainer fBadChannels
Container of bad channels.
New configuration, distiction between high and low threshold.
static const TString fgkTriggerTypeNames[5]
Histogram name tags.
2D position of a trigger channel on the EMCAL surface
Bool_t IsEGA(Int_t tBits) const
Main data structure storing all relevant information of EMCAL/DCAL trigger patches.
AliEMCALGeometry * fGeom
whether it's an ESD analysis
Int_t fPatchADC[kPatchCols][kPatchRows]
ADC values map.
Int_t fThresholdConstants[4][3]
simple offline trigger thresholds constants
Bool_t IsEJE(Int_t tBits) const
void SetEdgeCell(Int_t x, Int_t y)
TString fV0InName
name of output track array
EMCAL Jet patches, recalculated.
Definition of old trigger bit configuration.
Definition of new trigger bit configuration.
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)
Double_t fPatchADCSimple[kPatchCols][kPatchRows]
patch map for simple offline trigger
AliVCaloCells * fCaloCells
clusters
AliVVZERO * fV0
V0 object.
AliAODCaloTrigger * fSimpleOfflineTriggers
simple offline trigger
Bool_t isMC
EMCAL trigger patch maker.
TClonesArray * fCaloTriggersOut
trigger array out
void SetCenterMass(TLorentzVector &v)
THistManager * fQAHistos
Histograms for QA.
Double_t fVertex[3]
event plane V0C
static const Double_t kEMCL1ADCtoGeV
Conversion from EMCAL Level1 ADC to energy.
void SetTriggerBitConfig(const AliEmcalTriggerBitConfig *ref)
EMCAL Gamma patches, recalculated.
Class to make array of trigger patch objects in AOD/ESD events.
Int_t GetRunNumber(TString)
Definition: PlotMuonQA.C:2235
Char_t fLevel0TimeMap[kPatchCols][kPatchRows]
Map needed to store the level0 times.
AliVCaloTrigger * fCaloTriggers
cells
Bool_t fRunTriggerType[5]
Run patch maker for a given trigger type.
TString fCaloTriggerSetupOutName
name of output track array
Settings manager for the trigger patch algorithm.
void SetThresholdsSimple(Int_t i0, Int_t i1, Int_t i2, Int_t i3)
AliEmcalTriggerPatchInfo * ProcessPatch(TriggerMakerTriggerType_t type, Bool_t isOfflineSimple)
Bool_t NextTrigger(Bool_t &isOfflineSimple)
void SetCenterGeo(TVector3 &v, Double_t e)
TSortedList fChannels
Container for listed channels.
void SetThresholds(Int_t i0, Int_t i1, Int_t i2, Int_t i3)
Bool_t CheckForL0(const AliVCaloTrigger &trg) const