AliPhysics  vAN-20150827 (3e81cbb)
 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  if((type == kTMEMCalJet && IsEJE( tBits )) && (globRow > fGeom->GetNTotalTRU() - 16)) {
503  AliDebug(1, Form("Jet patch in inactive area: row[%d]", globRow));
504  return NULL;
505  }
506 
508  int patchsize = 2;
509  if(type == kTMEMCalJet || type == kTMEMCalRecalcJet) patchsize = 16;
510  if((globCol + patchsize >= kPatchCols) || (globCol + patchsize >= kPatchRows)){
511  AliError(Form("Invalid patch position for patch type %s: Col[%d], Row[%d] - patch rejected", fgkTriggerTypeNames[type].Data(), globCol, globRow));
512  return NULL;
513  }
514  }
515 
516  // get the absolute trigger ID
517  Int_t absId=-1;
518  fGeom->GetAbsFastORIndexFromPositionInEMCAL(globCol, globRow, absId);
519  // convert to the 4 absId of the cells composing the trigger channel
520  Int_t cellAbsId[4]={-1,-1,-1,-1};
521  fGeom->GetCellIndexFromFastORIndex(absId, cellAbsId);
522 
523  // get low left edge (eta max, phi min)
524  TVector3 edge1;
525  fGeom->GetGlobal(cellAbsId[0], edge1);
526  Int_t colEdge1 = globCol, rowEdge1 = globRow, absIdEdge1 = absId, cellIdEdge1 = cellAbsId[0]; // Used in warning for invalid patch position
527 
528  // sum the available energy in the 32/32 window of cells
529  // step over trigger channels and get all the corresponding cells
530  // make CM
531  Float_t amp = 0;
532  Float_t cmiCol = 0;
533  Float_t cmiRow = 0;
534  Int_t adcAmp = 0;
535  Double_t adcOfflineAmp = 0;
536  int nfastor = (type == kTMEMCalJet || type == kTMEMCalRecalcJet) ? 16 : 2; // 32x32 cell window for L1 Jet trigger, 4x4 for L1 Gamma or L0 trigger
537  for (Int_t i = 0; i < nfastor; ++i) {
538  for (Int_t j = 0; j < nfastor; ++j) {
539  // get the 4 cells composing the trigger channel
540  fGeom->GetAbsFastORIndexFromPositionInEMCAL(globCol+i, globRow+j, absId);
541  fGeom->GetCellIndexFromFastORIndex(absId, cellAbsId);
542  // add amplitudes and find patch edges
543  for (Int_t k = 0; k < 4; ++k) {
544  Float_t ca = fCaloCells->GetCellAmplitude(cellAbsId[k]);
545  //fGeom->GetGlobal(cellAbsId[k], cellCoor);
546  amp += ca;
547  cmiCol += ca*(Float_t)i;
548  cmiRow += ca*(Float_t)j;
549  }
550  // add the STU ADCs in the patch (in case of L1) or the TRU Amplitude (in case of L0)
551  if(type == kTMEMCalLevel0){
552  adcAmp += static_cast<Int_t>(fPatchAmplitudes[globCol+i][globRow+j] * 4); // precision loss in case of global integer field
553  } else {
554  adcAmp += fPatchADC[globCol+i][globRow+j];
555  }
556 
557  adcOfflineAmp += fPatchADCSimple[globCol+i][globRow+j];
558  }
559  }
560 
561  if (amp == 0) {
562  AliDebug(2,"EMCal trigger patch with 0 energy.");
563  return 0;
564  }
565 
566  // get the CM and patch index
567  cmiCol /= amp;
568  cmiRow /= amp;
569  Int_t cmCol = globCol + (Int_t)cmiCol;
570  Int_t cmRow = globRow + (Int_t)cmiRow;
571 
572  // get the patch and corresponding cells
573  fGeom->GetAbsFastORIndexFromPositionInEMCAL( cmCol, cmRow, absId );
574  fGeom->GetCellIndexFromFastORIndex( absId, cellAbsId );
575 
576  // find which out of the 4 cells is closest to CM and get it's position
577  Int_t cmiCellCol = TMath::Nint(cmiCol * 2.);
578  Int_t cmiCellRow = TMath::Nint(cmiRow * 2.);
579  TVector3 centerMass;
580  fGeom->GetGlobal(cellAbsId[(cmiCellRow%2)*2 + cmiCellCol%2], centerMass);
581 
582  // get up right edge (eta min, phi max)
583  // get the absolute trigger ID
584  Int_t posOffset=-1;
585  switch(type){
586  case kTMEMCalJet:
587  case kTMEMCalRecalcJet:
588  posOffset = 15;
589  break;
590  case kTMEMCalGamma:
591  case kTMEMCalRecalcGamma:
592  posOffset = 1;
593  break;
594  case kTMEMCalLevel0:
595  posOffset = 1;
596  break;
597  default:
598  posOffset = 0;
599  break;
600  };
601  fGeom->GetAbsFastORIndexFromPositionInEMCAL(globCol+posOffset, globRow+posOffset, absId);
602  fGeom->GetCellIndexFromFastORIndex(absId, cellAbsId);
603  TVector3 edge2;
604  fGeom->GetGlobal(cellAbsId[3], edge2);
605  Int_t colEdge2 = globCol+posOffset, rowEdge2 = globRow+posOffset, absIdEdge2 = absId, cellIdEdge2 = cellAbsId[3]; // Used in warning for invalid patch position
606 
607  // get the geometrical center as an average of two diagonally
608  // adjacent patches in the center
609  // picking two diagonally closest cells from the patches
610  switch(type){
611  case kTMEMCalJet:
612  case kTMEMCalRecalcJet:
613  posOffset = 7;
614  break;
615  case kTMEMCalGamma:
616  case kTMEMCalRecalcGamma:
617  posOffset = 0;
618  break;
619  case kTMEMCalLevel0:
620  posOffset = 0;
621  break;
622  default:
623  posOffset = 0;
624  break;
625  };
626  fGeom->GetAbsFastORIndexFromPositionInEMCAL(globCol+posOffset, globRow+posOffset, absId);
627  fGeom->GetCellIndexFromFastORIndex(absId, cellAbsId);
628  TVector3 center1;
629  fGeom->GetGlobal(cellAbsId[3], center1);
630 
631  switch(type){
632  case kTMEMCalJet:
633  case kTMEMCalRecalcJet:
634  posOffset = 8;
635  break;
636  case kTMEMCalGamma:
637  case kTMEMCalRecalcGamma:
638  posOffset = 1;
639  break;
640  case kTMEMCalLevel0:
641  posOffset = 1;
642  break;
643  };
644  fGeom->GetAbsFastORIndexFromPositionInEMCAL(globCol+posOffset, globRow+posOffset, absId);
645  fGeom->GetCellIndexFromFastORIndex(absId, cellAbsId);
646  TVector3 center2;
647  fGeom->GetGlobal(cellAbsId[0], center2);
648 
649  TVector3 centerGeo(center1);
650  centerGeo += center2;
651  centerGeo *= 0.5;
652 
653  // relate all to primary vertex
654  TVector3 edge1tmp = edge1, edge2tmp = edge2; // Used in warning for invalid patch position
655  centerGeo -= vertex;
656  centerMass -= vertex;
657  edge1 -= vertex;
658  edge2 -= vertex;
659  // Check for invalid patch positions
660  if(!(edge1[0] || edge1[1] || edge1[2])){
661  AliWarning(Form("Inconsistency in patch position for edge1: [%f|%f|%f]", edge1[0], edge1[1], edge1[2]));
662  AliWarning("Original vectors:");
663  AliWarning(Form("edge1: [%f|%f|%f]", edge1tmp[0], edge1tmp[1], edge1tmp[2]));
664  AliWarning(Form("vertex: [%f|%f|%f]", vertex[0], vertex[1], vertex[2]));
665  AliWarning(Form("Col: %d, Row: %d, FABSID: %d, Cell: %d", colEdge1, rowEdge1, absIdEdge1, cellIdEdge1));
666  AliWarning(Form("Offline: %s", isOfflineSimple ? "yes" : "no"));
667  }
668  if(!(edge2[0] || edge2[1] || edge2[2])){
669  AliWarning(Form("Inconsistency in patch position for edge2: [%f|%f|%f]", edge2[0], edge2[1], edge2[2]));
670  AliWarning("Original vectors:");
671  AliWarning(Form("edge2: [%f|%f|%f]", edge2tmp[0], edge2tmp[1], edge2tmp[2]));
672  AliWarning(Form("vertex: [%f|%f|%f]", vertex[0], vertex[1], vertex[2]));
673  AliWarning(Form("Col: %d, Row: %d, FABSID: %d, Cell: %d", colEdge2, rowEdge2, absIdEdge2, cellIdEdge2));
674  AliWarning(Form("Offline: %s", isOfflineSimple ? "yes" : "no"));
675  }
676 
677  Int_t isMC = MCEvent() ? 1 : 0;
678  Int_t offSet = (1 - isMC) * fTriggerBitConfig->GetTriggerTypesEnd();
679 
680  // fix tbits .. remove the unwanted type triggers
681  // for Jet and Gamma triggers we remove also the level 0 bit since it will be stored in the level 0 patch
682  // for level 0 we remove all gamma and jet trigger bits
683  switch(type){
684  case kTMEMCalJet:
688  break;
689  case kTMEMCalGamma:
693  break;
694  case kTMEMCalLevel0:
695  // Explicitly set the level 0 bit to overcome the masking out
696  tBits |= 1 << (offSet + fTriggerBitConfig->GetLevel0Bit());
700  break;
701  default: // recalculated patches don't need any action
702  break;
703  };
704 
705  // save the trigger object
706  AliEmcalTriggerPatchInfo *trigger =
707  new ((*fCaloTriggersOut)[fITrigger]) AliEmcalTriggerPatchInfo();
708  fITrigger++;
710  trigger->SetCenterGeo(centerGeo, amp);
711  trigger->SetCenterMass(centerMass, amp);
712  trigger->SetEdge1(edge1, amp);
713  trigger->SetEdge2(edge2, amp);
714  trigger->SetADCAmp(adcAmp);
715  trigger->SetADCOfflineAmp(Int_t(adcOfflineAmp));
716  trigger->SetTriggerBits(tBits);
717  trigger->SetOffSet(offSet);
718  trigger->SetEdgeCell(globCol*2, globRow*2); // from triggers to cells
719  //if(isOfflineSimple)trigger->SetOfflineSimple();
720  if(fDoQA){
721  TString patchtype = isOfflineSimple ? "Offline" : "Online";
722  fQAHistos->FillTH2(Form("RCPos%s%s", fgkTriggerTypeNames[type].Data(), patchtype.Data()), globCol, globRow);
723  fQAHistos->FillTH2(Form("EPCentPos%s%s", fgkTriggerTypeNames[type].Data(), patchtype.Data()), centerGeo.Eta(), centerGeo.Phi());
724  fQAHistos->FillTH2(Form("PatchADCvsE%s%s", fgkTriggerTypeNames[type].Data(), patchtype.Data()), isOfflineSimple ? adcOfflineAmp : adcAmp, trigger->GetPatchE());
725  // Redo checking of found trigger bits after masking of unwanted triggers
726  for(unsigned int ibit = 0; ibit < sizeof(tBits)*8; ibit++) {
727  if(tBits & (1 << ibit)){
728  fQAHistos->FillTH1("triggerBitsSel", ibit);
729  }
730  }
731  }
732  return trigger;
733 }
734 
744 {
745 
746  TArrayI tBitsArray(4), rowArray(4), colArray(4);
747 
748  // First entries are for recalculated patches
749 
750  tBitsArray[0] = 1 << AliEmcalTriggerPatchInfo::kRecalcJetBitNum;
751  colArray[0] = -1;
752  rowArray[0] = -1;
753 
755  colArray[1] = -1;
756  rowArray[1] = -1;
757 
759  colArray[2] = -1;
760  rowArray[2] = -1;
761 
763  colArray[3] = -1;
764  rowArray[3] = -1;
765 
766  Double_t maxPatchADCoffline = -1;
767  Int_t maxPatchADC = -1;
768  // run the trigger algo, stepping by 8 towers (= 4 trigger channels)
769  Int_t maxCol = 48;
770  Int_t maxRow = fGeom->GetNTotalTRU()*2;
771  // Markus:
772  // temp fix for the number of TRUs in the 2011 PbPb data to 30
773  // @TODO: Fix in the geometry in the OCDB
774  int runnumber = InputEvent()->GetRunNumber();
775  if(runnumber > 139517 && runnumber <= 170593) maxRow = 60;
776  Int_t isMC = MCEvent() ? 1 : 0;
777  Int_t bitOffSet = (1 - isMC) * fTriggerBitConfig->GetTriggerTypesEnd();
778  for (Int_t i = 0; i <= (maxCol-16); i += 4) {
779  for (Int_t j = 0; j <= (maxRow-16); j += 4) {
780  Double_t tSumOffline = 0;
781  Int_t tSum = 0;
782  Int_t tBits = 0;
783  // window
784  for (Int_t k = 0; k < 16; ++k) {
785  for (Int_t l = 0; l < 16; ++l) {
786  tSumOffline += fPatchADCSimple[i+k][j+l];
787  tSum += (ULong64_t)fPatchADC[i+k][j+l];
788  }
789  }
790 
791  if (tSum > maxPatchADC) { // Mark highest Jet patch
792  maxPatchADC = tSum;
793  colArray[0] = i;
794  rowArray[0] = j;
795  }
796 
797  if (tSumOffline > maxPatchADCoffline) { // Mark highest Jet patch
798  maxPatchADCoffline = tSumOffline;
799  colArray[1] = i;
800  rowArray[1] = j;
801  }
802 
803  // check thresholds
804  if (tSumOffline > fCaloTriggerSetupOut->GetThresholdJetLowSimple())
805  tBits = tBits | ( 1 << ( bitOffSet + fTriggerBitConfig->GetJetLowBit() ));
806  if (tSumOffline > fCaloTriggerSetupOut->GetThresholdJetHighSimple())
807  tBits = tBits | ( 1 << ( bitOffSet + fTriggerBitConfig->GetJetHighBit() ));
808 
809  // add trigger values
810  if (tBits != 0) {
811  // add offline bit
812  tBits = tBits | ( 1 << AliEmcalTriggerPatchInfo::kSimpleOfflineBitNum );
813  tBitsArray.Set( tBitsArray.GetSize() + 1 );
814  colArray.Set( colArray.GetSize() + 1 );
815  rowArray.Set( rowArray.GetSize() + 1 );
816  tBitsArray[tBitsArray.GetSize()-1] = tBits;
817  colArray[colArray.GetSize()-1] = i;
818  rowArray[rowArray.GetSize()-1] = j;
819  }
820  }
821  } // trigger algo
822 
823  // 4x4 trigger algo, stepping by 2 towers (= 1 trigger channel)
824  maxPatchADC = -1;
825  maxPatchADCoffline = -1;
826 
827  for (Int_t i = 0; i <= (maxCol-2); ++i) {
828  for (Int_t j = 0; j <= (maxRow-2); ++j) {
829  Int_t tSum = 0;
830  Double_t tSumOffline = 0;
831  Int_t tBits = 0;
832 
833  // window
834  for (Int_t k = 0; k < 2; ++k) {
835  for (Int_t l = 0; l < 2; ++l) {
836  tSumOffline += fPatchADCSimple[i+k][j+l];
837  tSum += (ULong64_t)fPatchADC[i+k][j+l];
838  }
839  }
840 
841  if (tSum > maxPatchADC) { // Mark highest Gamma patch
842  maxPatchADC = tSum;
843  colArray[2] = i;
844  rowArray[2] = j;
845  }
846  if (tSumOffline > maxPatchADCoffline) { // Mark highest Gamma patch
847  maxPatchADCoffline = tSumOffline;
848  colArray[3] = i;
849  rowArray[3] = j;
850  }
851 
852  // check thresholds
854  tBits = tBits | ( 1 << ( bitOffSet + fTriggerBitConfig->GetGammaLowBit() ));
856  tBits = tBits | ( 1 << ( bitOffSet + fTriggerBitConfig->GetGammaHighBit() ));
857 
858  // add trigger values
859  if (tBits != 0) {
860  // add offline bit
861  tBits = tBits | ( 1 << AliEmcalTriggerPatchInfo::kSimpleOfflineBitNum );
862  tBitsArray.Set( tBitsArray.GetSize() + 1 );
863  colArray.Set( colArray.GetSize() + 1 );
864  rowArray.Set( rowArray.GetSize() + 1 );
865  tBitsArray[tBitsArray.GetSize()-1] = tBits;
866  colArray[colArray.GetSize()-1] = i;
867  rowArray[rowArray.GetSize()-1] = j;
868  }
869  }
870  } // trigger algo
871 
872  // save in object
873  fSimpleOfflineTriggers->DeAllocate();
874  fSimpleOfflineTriggers->Allocate(tBitsArray.GetSize());
875  for (Int_t i = 0; i < tBitsArray.GetSize(); ++i){
876  fSimpleOfflineTriggers->Add(colArray[i],rowArray[i], 0, 0, 0, 0, 0, tBitsArray[i]);
877  }
878 }
879 
885 Bool_t AliEmcalTriggerMaker::NextTrigger(Bool_t &isOfflineSimple)
886 {
887 
888  isOfflineSimple = kFALSE;
889  Bool_t loopContinue = fCaloTriggers->Next();
890  if (!loopContinue) {
891  loopContinue = fSimpleOfflineTriggers->Next();
892  isOfflineSimple = kTRUE;
893  }
894  return loopContinue;
895 }
896 
903 Bool_t AliEmcalTriggerMaker::CheckForL0(const AliVCaloTrigger& trg) const {
904  Int_t row(-1), col(-1); trg.GetPosition(col, row);
905  if(col < 0 || row < 0){
906  AliError(Form("Patch outside range [col %d, row %d]", col, row));
907  return kFALSE;
908  }
909  Int_t truref(-1), trumod(-1), absFastor(-1), adc(-1);
910  fGeom->GetAbsFastORIndexFromPositionInEMCAL(col, row, absFastor);
911  fGeom->GetTRUFromAbsFastORIndex(absFastor, truref, adc);
912  int nvalid(0);
913  for(int ipos = 0; ipos < 2; ipos++){
914  if(row + ipos >= kPatchRows) continue; // boundary check
915  for(int jpos = 0; jpos < 2; jpos++){
916  if(col + jpos >= kPatchCols) continue; // boundary check
917  // Check whether we are in the same TRU
918  trumod = -1;
919  fGeom->GetAbsFastORIndexFromPositionInEMCAL(col+jpos, row+ipos, absFastor);
920  fGeom->GetTRUFromAbsFastORIndex(absFastor, trumod, adc);
921  if(trumod != truref) continue;
922  if(col + jpos >= kPatchCols) AliError(Form("Boundary error in col [%d, %d + %d]", col + jpos, col, jpos));
923  if(row + ipos >= kPatchRows) AliError(Form("Boundary error in row [%d, %d + %d]", row + ipos, row, ipos));
924  Char_t l0times = fLevel0TimeMap[col + jpos][row + ipos];
925  if(l0times > 7 && l0times < 10) nvalid++;
926  }
927  }
928  if (nvalid != 4) return false;
929  return true;
930 }
931 
939  if(HasChannel(col, row)) return;
940  fChannels.Add(new AliEmcalTriggerChannelPosition(col, row));
941 }
942 
951  if(fChannels.FindObject(&refChannel)) return true;
952  return false;
953 }
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:2237
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