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