]>
Commit | Line | Data |
---|---|---|
f9a1843e | 1 | // $Id: AliEmcalTriggerMaker.cxx 64593 2013-10-18 10:23:58Z loizides $ |
00c77045 | 2 | // |
05a42e4d | 3 | // Class to make array of trigger patch objects in AOD/ESD events. |
00c77045 | 4 | // |
5 | // Author: J.Kral | |
00c77045 | 6 | #include <TClonesArray.h> |
36e1f11b | 7 | #include <TArrayI.h> |
86a543a0 | 8 | #include <THashList.h> |
05a42e4d | 9 | #include "AliAODCaloTrigger.h" |
10 | #include "AliEMCALGeometry.h" | |
11 | #include "AliEMCALTriggerTypes.h" | |
00c77045 | 12 | #include "AliEmcalTriggerPatchInfo.h" |
13 | #include "AliEmcalTriggerSetupInfo.h" | |
05a42e4d | 14 | #include "AliLog.h" |
00c77045 | 15 | #include "AliVCaloCells.h" |
05a42e4d | 16 | #include "AliVCaloTrigger.h" |
001765f7 | 17 | #include "AliVVZERO.h" |
05a42e4d | 18 | #include "AliEmcalTriggerMaker.h" |
00c77045 | 19 | |
19dfd8dd | 20 | #include "THistManager.h" |
21 | #include "TString.h" | |
22 | ||
00c77045 | 23 | ClassImp(AliEmcalTriggerMaker) |
24 | ||
25 | using namespace std; | |
26 | ||
27 | //________________________________________________________________________ | |
28 | AliEmcalTriggerMaker::AliEmcalTriggerMaker() : | |
9239b066 | 29 | AliAnalysisTaskEmcal("AliEmcalTriggerMaker",kFALSE), |
00c77045 | 30 | fCaloTriggersOutName("EmcalTriggers"), |
31 | fCaloTriggerSetupOutName("EmcalTriggersSetup"), | |
001765f7 | 32 | fV0InName("AliAODVZERO"), |
00c77045 | 33 | fCaloTriggersOut(0), |
001765f7 | 34 | fCaloTriggerSetupOut(0), |
35 | fSimpleOfflineTriggers(0), | |
f9a1843e | 36 | fV0(0), |
19dfd8dd | 37 | fITrigger(0), |
38 | fDoQA(kFALSE), | |
39 | fQAHistos(NULL) | |
00c77045 | 40 | { |
41 | // Constructor. | |
1645a556 | 42 | memset(fThresholdConstants, 0, sizeof(Int_t) * 12); |
43 | memset(fPatchADCSimple, 0, sizeof(Int_t) * kPatchCols * kPatchRows); | |
44 | memset(fPatchADC, 0, sizeof(Int_t) * kPatchCols * kPatchRows); | |
00c77045 | 45 | } |
46 | ||
47 | //________________________________________________________________________ | |
19dfd8dd | 48 | AliEmcalTriggerMaker::AliEmcalTriggerMaker(const char *name, Bool_t doQA) : |
49 | AliAnalysisTaskEmcal(name,doQA), | |
00c77045 | 50 | fCaloTriggersOutName("EmcalTriggers"), |
51 | fCaloTriggerSetupOutName("EmcalTriggersSetup"), | |
001765f7 | 52 | fV0InName("AliAODVZERO"), |
00c77045 | 53 | fCaloTriggersOut(0), |
001765f7 | 54 | fCaloTriggerSetupOut(0), |
55 | fSimpleOfflineTriggers(0), | |
f9a1843e | 56 | fV0(0), |
19dfd8dd | 57 | fITrigger(0), |
58 | fDoQA(doQA), | |
59 | fQAHistos(NULL) | |
00c77045 | 60 | { |
61 | // Constructor. | |
19dfd8dd | 62 | memset(fThresholdConstants, 0, sizeof(Int_t) * 12); |
63 | memset(fPatchADCSimple, 0, sizeof(Int_t) * kPatchCols * kPatchRows); | |
64 | memset(fPatchADC, 0, sizeof(Int_t) * kPatchCols * kPatchRows); | |
00c77045 | 65 | } |
66 | ||
67 | //________________________________________________________________________ | |
68 | AliEmcalTriggerMaker::~AliEmcalTriggerMaker() | |
69 | { | |
70 | // Destructor. | |
71 | } | |
72 | ||
73 | //________________________________________________________________________ | |
74 | void AliEmcalTriggerMaker::ExecOnce() | |
75 | { | |
76 | // Init the analysis. | |
77 | ||
9239b066 | 78 | AliAnalysisTaskEmcal::ExecOnce(); |
00c77045 | 79 | |
80 | if (!fInitialized) | |
81 | return; | |
82 | ||
83 | if (!fCaloTriggersOutName.IsNull()) { | |
84 | fCaloTriggersOut = new TClonesArray("AliEmcalTriggerPatchInfo"); | |
85 | fCaloTriggersOut->SetName(fCaloTriggersOutName); | |
86 | ||
87 | if (!(InputEvent()->FindListObject(fCaloTriggersOutName))) { | |
88 | InputEvent()->AddObject(fCaloTriggersOut); | |
89 | } | |
90 | else { | |
91 | fInitialized = kFALSE; | |
92 | AliFatal(Form("%s: Container with same name %s already present. Aborting", GetName(), fCaloTriggersOutName.Data())); | |
93 | return; | |
94 | } | |
95 | } | |
96 | ||
97 | if (!fCaloTriggerSetupOutName.IsNull()) { | |
98 | fCaloTriggerSetupOut = new AliEmcalTriggerSetupInfo(); | |
99 | fCaloTriggerSetupOut->SetName(fCaloTriggerSetupOutName); | |
100 | ||
101 | if (!(InputEvent()->FindListObject(fCaloTriggerSetupOutName))) { | |
102 | InputEvent()->AddObject(fCaloTriggerSetupOut); | |
103 | } | |
104 | else { | |
105 | fInitialized = kFALSE; | |
106 | AliFatal(Form("%s: Container with same name %s already present. Aborting", GetName(), fCaloTriggerSetupOutName.Data())); | |
107 | return; | |
108 | } | |
109 | } | |
110 | ||
001765f7 | 111 | if ( ! fV0InName.IsNull()) { |
05a42e4d | 112 | fV0 = (AliVVZERO*)InputEvent()->FindListObject(fV0InName); |
001765f7 | 113 | } |
114 | ||
115 | // container for simple offline trigger processing | |
116 | fSimpleOfflineTriggers = new AliAODCaloTrigger(); | |
05a42e4d | 117 | fSimpleOfflineTriggers->Allocate(0); |
00c77045 | 118 | } |
119 | ||
19dfd8dd | 120 | //________________________________________________________________________ |
121 | void AliEmcalTriggerMaker::UserCreateOutputObjects() | |
122 | { | |
123 | // Do basic QA monitoring (if requested) | |
124 | AliAnalysisTaskEmcal::UserCreateOutputObjects(); | |
125 | ||
126 | if(fDoQA){ | |
127 | fQAHistos = new THistManager("TriggerQA"); | |
128 | ||
129 | TString trtypenames[3] = {"EJE", "EGA", "EL0"}; | |
130 | for(int itype = 0; itype < 3; itype++){ | |
131 | fQAHistos->CreateTH2(Form("RCPos%s", trtypenames[itype].Data()), Form("Lower edge position of %s patches (col-row)", trtypenames[itype].Data()), 48, -0.5, 47.5, 64, -0.5, 63.5); | |
132 | fQAHistos->CreateTH2(Form("EPCentPos%s", trtypenames[itype].Data()), Form("Center position of the %s trigger patches", trtypenames[itype].Data()), 20, -0.8, 0.8, 100., 1., 4.); | |
133 | fQAHistos->CreateTH2(Form("PatchADCvsE%s", trtypenames[itype].Data()), Form("Patch ADC value for trigger type %s", trtypenames[itype].Data()), 200, 0., 200, 200, 0., 200); | |
134 | } | |
135 | fQAHistos->CreateTH1("triggerBitsAll", "Trigger bits for all incoming patches", 64, -0.5, 63.5); | |
136 | fQAHistos->CreateTH1("triggerBitsSel", "Trigger bits for reconstructed patches", 64, -0.5, 63.5); | |
137 | fOutput->Add(fQAHistos->GetListOfHistograms()); | |
138 | PostData(1, fOutput); | |
139 | } | |
140 | } | |
141 | ||
00c77045 | 142 | //________________________________________________________________________ |
143 | Bool_t AliEmcalTriggerMaker::Run() | |
144 | { | |
05a42e4d | 145 | // Create and fill the patch array. |
146 | ||
5b6a633e | 147 | AliEmcalTriggerPatchInfo *trigger, *triggerMainJet, *triggerMainGamma, *triggerMainLevel0; |
f9a1843e | 148 | AliEmcalTriggerPatchInfo *triggerMainJetSimple, *triggerMainGammaSimple; |
00c77045 | 149 | |
150 | // delete patch array, clear setup object | |
151 | fCaloTriggersOut->Delete(); | |
152 | fCaloTriggerSetupOut->Clean(); | |
153 | ||
05a42e4d | 154 | if (!fCaloTriggers) { |
00c77045 | 155 | AliError(Form("Calo triggers container %s not available.", fCaloTriggersName.Data())); |
156 | return kTRUE; | |
157 | } | |
05a42e4d | 158 | if (!fCaloCells) { |
00c77045 | 159 | AliError(Form("Calo cells container %s not available.", fCaloCellsName.Data())); |
160 | return kTRUE; | |
161 | } | |
05a42e4d | 162 | if (!fCaloCells) { |
001765f7 | 163 | AliError(Form("V0 container %s not available.", fV0InName.Data())); |
164 | return kTRUE; | |
165 | } | |
f9a1843e | 166 | |
167 | // do not process, if sooner than 11h period | |
168 | // 160683 ?? | |
169 | if( InputEvent()->GetRunNumber() < 167693 ) | |
170 | return kTRUE; | |
171 | ||
172 | // // do not process any MC, since no MC was generated with correct | |
173 | // // EMCal trigger L1 jet trigger simulation, yet | |
174 | // // productions will be enabled, once some correct once are produced | |
175 | // if( MCEvent() != 0 ) | |
176 | // return kTRUE; | |
177 | ||
00c77045 | 178 | // must reset before usage, or the class will fail |
179 | fCaloTriggers->Reset(); | |
f9a1843e | 180 | |
05a42e4d | 181 | // first run over the patch array to compose a map of 2x2 patch energies |
cf9ee6ed | 182 | // which is then needed to construct the full patch ADC energy |
183 | // class is not empty | |
05a42e4d | 184 | if (fCaloTriggers->GetEntries() > 0) { |
1645a556 | 185 | // zero the arrays |
36e1f11b | 186 | memset(fPatchADC, 0, sizeof(Int_t) * kPatchCols * kPatchRows); |
1645a556 | 187 | |
cf9ee6ed | 188 | // go throuth the trigger channels |
05a42e4d | 189 | while (fCaloTriggers->Next()) { |
cf9ee6ed | 190 | // get position in global 2x2 tower coordinates |
191 | // A0 left bottom (0,0) | |
05a42e4d | 192 | Int_t globCol=-1, globRow=-1; |
193 | fCaloTriggers->GetPosition(globCol, globRow); | |
cf9ee6ed | 194 | // for some strange reason some ADC amps are initialized in reconstruction |
05a42e4d | 195 | // as -1, neglect those |
196 | Int_t adcAmp=-1; | |
197 | fCaloTriggers->GetL1TimeSum(adcAmp); | |
198 | if (adcAmp>-1) | |
1645a556 | 199 | fPatchADC[globCol][globRow] = adcAmp; |
05a42e4d | 200 | } // patches |
201 | } // array not empty | |
cf9ee6ed | 202 | |
001765f7 | 203 | // fill the array for offline trigger processing |
204 | // using calibrated cell energies | |
1645a556 | 205 | memset(fPatchADCSimple, 0, sizeof(Int_t) * kPatchRows * kPatchCols); |
001765f7 | 206 | |
207 | // fill the patch ADCs from cells | |
05a42e4d | 208 | Int_t nCell = fCaloCells->GetNumberOfCells(); |
209 | for(Int_t iCell = 0; iCell < nCell; ++iCell) { | |
001765f7 | 210 | // get the cell info, based in index in array |
05a42e4d | 211 | Short_t cellId = fCaloCells->GetCellNumber(iCell); |
212 | Double_t amp = fCaloCells->GetAmplitude(iCell); | |
001765f7 | 213 | // get position |
05a42e4d | 214 | Int_t absId=-1; |
215 | fGeom->GetFastORIndexFromCellIndex(cellId, absId); | |
216 | Int_t globCol=-1, globRow=-1; | |
217 | fGeom->GetPositionInEMCALFromAbsFastORIndex(absId, globCol, globRow); | |
001765f7 | 218 | // add |
219 | fPatchADCSimple[globCol][globRow] += amp/kEMCL1ADCtoGeV; | |
220 | } | |
cf9ee6ed | 221 | |
00c77045 | 222 | // dig out common data (thresholds) |
223 | // 0 - jet high, 1 - gamma high, 2 - jet low, 3 - gamma low | |
05a42e4d | 224 | fCaloTriggerSetupOut->SetThresholds(fCaloTriggers->GetL1Threshold(0), |
225 | fCaloTriggers->GetL1Threshold(1), | |
226 | fCaloTriggers->GetL1Threshold(2), | |
227 | fCaloTriggers->GetL1Threshold(3)); | |
00c77045 | 228 | |
001765f7 | 229 | // get the V0 value and compute and set the offline thresholds |
230 | // get V0, compute thresholds and save them as global parameters | |
05a42e4d | 231 | Int_t v0[2]; |
001765f7 | 232 | v0[0] = fV0->GetTriggerChargeA(); |
233 | v0[1] = fV0->GetTriggerChargeC(); | |
05a42e4d | 234 | ULong64_t v0S = v0[0] + v0[1]; |
235 | fSimpleOfflineTriggers->SetL1V0(v0); | |
001765f7 | 236 | |
05a42e4d | 237 | for (Int_t i = 0; i < 4; ++i) { |
001765f7 | 238 | // A*V0^2/2^32+B*V0/2^16+C |
05a42e4d | 239 | ULong64_t thresh = ( ((ULong64_t)fThresholdConstants[i][0]) * v0S * v0S ) >> 32; |
001765f7 | 240 | thresh += ( ((ULong64_t)fThresholdConstants[i][1]) * v0S ) >> 16; |
241 | thresh += ((ULong64_t)fThresholdConstants[i][2]); | |
05a42e4d | 242 | fSimpleOfflineTriggers->SetL1Threshold(i,thresh); |
001765f7 | 243 | } |
244 | ||
245 | // save the thresholds in output object | |
05a42e4d | 246 | fCaloTriggerSetupOut->SetThresholdsSimple(fSimpleOfflineTriggers->GetL1Threshold(0), |
247 | fSimpleOfflineTriggers->GetL1Threshold(1), | |
248 | fSimpleOfflineTriggers->GetL1Threshold(2), | |
249 | fSimpleOfflineTriggers->GetL1Threshold(3)); | |
250 | ||
001765f7 | 251 | // run the trigger |
252 | RunSimpleOfflineTrigger(); | |
253 | ||
254 | // reset for re-run | |
255 | fCaloTriggers->Reset(); | |
256 | fSimpleOfflineTriggers->Reset(); | |
257 | ||
00c77045 | 258 | // class is not empty |
05a42e4d | 259 | if (fCaloTriggers->GetEntries() > 0 || fSimpleOfflineTriggers->GetEntries() > 0) { |
f9a1843e | 260 | fITrigger = 0; |
05a42e4d | 261 | triggerMainGamma = 0; |
262 | triggerMainJet = 0; | |
263 | triggerMainGammaSimple = 0; | |
264 | triggerMainJetSimple = 0; | |
265 | triggerMainLevel0 = 0; | |
00c77045 | 266 | |
001765f7 | 267 | // go throuth the trigger channels, real first, then offline |
05a42e4d | 268 | Bool_t isOfflineSimple=0; |
269 | while (NextTrigger(isOfflineSimple)) { | |
270 | // process jet | |
271 | trigger = ProcessPatch(kTMEMCalJet, isOfflineSimple); | |
272 | // save main jet triggers in event | |
273 | if (trigger != 0) { | |
36e1f11b | 274 | // check if more energetic than others for main patch marking |
275 | if (!isOfflineSimple) { | |
276 | if (triggerMainJet == 0 || (triggerMainJet->GetPatchE() < trigger->GetPatchE())) | |
277 | triggerMainJet = trigger; | |
278 | } else { | |
279 | if (triggerMainJetSimple == 0 || (triggerMainJetSimple->GetPatchE() < trigger->GetPatchE())) | |
280 | triggerMainJetSimple = trigger; | |
281 | } | |
05a42e4d | 282 | } |
00c77045 | 283 | |
05a42e4d | 284 | // process gamma |
285 | trigger = ProcessPatch(kTMEMCalGamma, isOfflineSimple); | |
286 | // save main gamma triggers in event | |
287 | if (trigger != 0) { | |
36e1f11b | 288 | // check if more energetic than others for main patch marking |
289 | if (!isOfflineSimple) { | |
290 | if (triggerMainGamma == 0 || (triggerMainGamma->GetPatchE() < trigger->GetPatchE())) | |
291 | triggerMainGamma = trigger; | |
292 | } else { | |
293 | if (triggerMainGammaSimple == 0 || (triggerMainGammaSimple->GetPatchE() < trigger->GetPatchE())) | |
294 | triggerMainGammaSimple = trigger; | |
295 | } | |
05a42e4d | 296 | } |
297 | ||
298 | // level 0 triggers | |
299 | trigger = ProcessPatch(kTMEMCalLevel0, isOfflineSimple); | |
300 | // save main level0 trigger in the event | |
301 | if (trigger) { | |
36e1f11b | 302 | if (!triggerMainLevel0 || (triggerMainLevel0->GetPatchE() < trigger->GetPatchE())) |
303 | triggerMainLevel0 = trigger; | |
05a42e4d | 304 | } |
00c77045 | 305 | } // triggers |
306 | ||
307 | // mark the most energetic patch as main | |
001765f7 | 308 | // for real and also simple offline |
05a42e4d | 309 | if (triggerMainJet != 0) { |
310 | Int_t tBits = triggerMainJet->GetTriggerBits(); | |
f9a1843e | 311 | // main trigger flag |
312 | tBits = tBits | ( 1 << 24 ); | |
313 | triggerMainJet->SetTriggerBits( tBits ); | |
314 | } | |
05a42e4d | 315 | if (triggerMainJetSimple != 0) { |
316 | Int_t tBits = triggerMainJetSimple->GetTriggerBits(); | |
00c77045 | 317 | // main trigger flag |
318 | tBits = tBits | ( 1 << 24 ); | |
05a42e4d | 319 | triggerMainJetSimple->SetTriggerBits(tBits); |
00c77045 | 320 | } |
05a42e4d | 321 | if (triggerMainGamma != 0) { |
322 | Int_t tBits = triggerMainGamma->GetTriggerBits(); | |
001765f7 | 323 | // main trigger flag |
324 | tBits = tBits | ( 1 << 24 ); | |
f9a1843e | 325 | triggerMainGamma->SetTriggerBits( tBits ); |
326 | } | |
05a42e4d | 327 | if (triggerMainGammaSimple != 0) { |
328 | Int_t tBits = triggerMainGammaSimple->GetTriggerBits(); | |
f9a1843e | 329 | // main trigger flag |
330 | tBits = tBits | ( 1 << 24 ); | |
331 | triggerMainGammaSimple->SetTriggerBits( tBits ); | |
001765f7 | 332 | } |
5b6a633e | 333 | if(triggerMainLevel0){ |
05a42e4d | 334 | Int_t tBits = triggerMainLevel0->GetTriggerBits(); |
335 | // main trigger flag | |
336 | tBits |= (1 << 24); | |
337 | triggerMainLevel0->SetTriggerBits(tBits); | |
5b6a633e | 338 | } |
00c77045 | 339 | } // there are some triggers |
340 | ||
341 | return kTRUE; | |
342 | } | |
001765f7 | 343 | |
f9a1843e | 344 | //________________________________________________________________________ |
05a42e4d | 345 | AliEmcalTriggerPatchInfo* AliEmcalTriggerMaker::ProcessPatch(TriggerMakerTriggerType_t type, Bool_t isOfflineSimple) |
346 | { | |
347 | // Process and fill trigger patch. | |
348 | // check if jet trigger low or high | |
349 | Int_t tBits=-1; | |
350 | if (!isOfflineSimple) | |
351 | fCaloTriggers->GetTriggerBits(tBits); | |
352 | else | |
353 | fSimpleOfflineTriggers->GetTriggerBits(tBits); | |
19dfd8dd | 354 | |
355 | Int_t nBitsFound = 0; | |
356 | Int_t bitsFound[64]; | |
357 | if(fDoQA){ | |
98192837 | 358 | for(unsigned int ibit = 0; ibit < sizeof(tBits)*8; ibit++) { |
19dfd8dd | 359 | if(tBits & (1 << ibit)){ |
360 | bitsFound[nBitsFound++] = ibit; | |
361 | fQAHistos->FillTH1("triggerBitsAll", ibit); | |
362 | } | |
363 | } | |
364 | } | |
f9a1843e | 365 | |
05a42e4d | 366 | if ((type == kTMEMCalJet && !IsEJE( tBits )) || |
367 | (type == kTMEMCalGamma && !IsEGA( tBits )) || | |
19dfd8dd | 368 | (type == kTMEMCalLevel0 && !(CheckForL0(*fCaloTriggers)))) |
05a42e4d | 369 | return 0; |
19dfd8dd | 370 | TString trtypenames[3] = {"EJE", "EGA", "EL0"}; // For QA |
371 | ||
05a42e4d | 372 | // save primary vertex in vector |
373 | TVector3 vertex; | |
374 | vertex.SetXYZ(fVertex[0], fVertex[1], fVertex[2]); | |
375 | ||
376 | // get position in global 2x2 tower coordinates | |
377 | // A0 left bottom (0,0) | |
378 | Int_t globCol=-1, globRow=-1; | |
379 | if (!isOfflineSimple) | |
380 | fCaloTriggers->GetPosition(globCol,globRow); | |
381 | else | |
382 | fSimpleOfflineTriggers->GetPosition(globCol, globRow); | |
383 | ||
384 | // get the absolute trigger ID | |
385 | Int_t absId=-1; | |
386 | fGeom->GetAbsFastORIndexFromPositionInEMCAL(globCol, globRow, absId); | |
387 | // convert to the 4 absId of the cells composing the trigger channel | |
388 | Int_t cellAbsId[4]={-1,-1,-1,-1}; | |
389 | fGeom->GetCellIndexFromFastORIndex(absId, cellAbsId); | |
f9a1843e | 390 | |
05a42e4d | 391 | // get low left edge (eta max, phi min) |
392 | TVector3 edge1; | |
393 | fGeom->GetGlobal(cellAbsId[0], edge1); | |
f9a1843e | 394 | |
05a42e4d | 395 | // sum the available energy in the 32/32 window of cells |
396 | // step over trigger channels and get all the corresponding cells | |
397 | // make CM | |
1645a556 | 398 | Double_t amp = 0; |
05a42e4d | 399 | Int_t cmiCol = 0; |
400 | Int_t cmiRow = 0; | |
401 | Int_t adcAmp = 0; | |
1645a556 | 402 | int nfastor = (type == kTMEMCalJet) ? 16 : 2; // 32x32 cell window for L1 Jet trigger, 4x4 for L1 Gamma or L0 trigger |
403 | for (Int_t i = 0; i < nfastor; ++i) { | |
404 | for (Int_t j = 0; j < nfastor; ++j) { | |
405 | // get the 4 cells composing the trigger channel | |
406 | fGeom->GetAbsFastORIndexFromPositionInEMCAL(globCol+i, globRow+j, absId); | |
407 | fGeom->GetCellIndexFromFastORIndex(absId, cellAbsId); | |
408 | // add amplitudes and find patch edges | |
409 | for (Int_t k = 0; k < 4; ++k) { | |
410 | Double_t ca = fCaloCells->GetCellAmplitude(cellAbsId[k]); | |
411 | //fGeom->GetGlobal(cellAbsId[k], cellCoor); | |
412 | amp += ca; | |
413 | cmiCol += ca*(Double_t)i; | |
414 | cmiRow += ca*(Double_t)j; | |
415 | } | |
416 | // add the STU ADCs in the patch (in case of L1) or the TRU Amplitude (in case of L0) | |
417 | if (!isOfflineSimple ) | |
36e1f11b | 418 | if(type == kTMEMCalLevel0){ |
19dfd8dd | 419 | adcAmp += fPatchADC[globCol+i][globRow+j] * 4; // precision loss in case of global integer field |
36e1f11b | 420 | } else |
1645a556 | 421 | adcAmp += fPatchADC[globCol+i][globRow+j]; |
422 | else | |
423 | adcAmp += fPatchADCSimple[globCol+i][globRow+j]; | |
424 | } | |
05a42e4d | 425 | } |
5b6a633e | 426 | |
05a42e4d | 427 | if (amp == 0) { |
428 | AliDebug(2,"EMCal trigger patch with 0 energy."); | |
429 | return 0; | |
430 | } | |
431 | ||
432 | // get the CM and patch index | |
433 | cmiCol /= amp; | |
434 | cmiRow /= amp; | |
435 | Int_t cmCol = globCol + (Int_t)cmiCol; | |
436 | Int_t cmRow = globRow + (Int_t)cmiRow; | |
437 | ||
438 | // get the patch and corresponding cells | |
439 | fGeom->GetAbsFastORIndexFromPositionInEMCAL( cmCol, cmRow, absId ); | |
440 | fGeom->GetCellIndexFromFastORIndex( absId, cellAbsId ); | |
441 | ||
442 | // find which out of the 4 cells is closest to CM and get it's position | |
443 | Int_t cmiCellCol = TMath::Nint(cmiCol * 2.); | |
444 | Int_t cmiCellRow = TMath::Nint(cmiRow * 2.); | |
445 | TVector3 centerMass; | |
446 | fGeom->GetGlobal(cellAbsId[(cmiCellRow%2)*2 + cmiCellCol%2], centerMass); | |
f9a1843e | 447 | |
05a42e4d | 448 | // get up right edge (eta min, phi max) |
449 | // get the absolute trigger ID | |
450 | Int_t posOffset=-1; | |
451 | switch(type){ | |
452 | case kTMEMCalJet: | |
453 | posOffset = 15; | |
454 | break; | |
455 | case kTMEMCalGamma: | |
456 | posOffset = 1; | |
457 | break; | |
458 | case kTMEMCalLevel0: | |
459 | posOffset = 1; | |
460 | break; | |
461 | default: | |
462 | posOffset = 0; | |
463 | break; | |
464 | }; | |
465 | fGeom->GetAbsFastORIndexFromPositionInEMCAL(globCol+posOffset, globRow+posOffset, absId); | |
466 | fGeom->GetCellIndexFromFastORIndex(absId, cellAbsId); | |
467 | TVector3 edge2; | |
468 | fGeom->GetGlobal(cellAbsId[3], edge2); | |
f9a1843e | 469 | |
05a42e4d | 470 | // get the geometrical center as an average of two diagonally |
471 | // adjacent patches in the center | |
472 | // picking two diagonally closest cells from the patches | |
473 | switch(type){ | |
474 | case kTMEMCalJet: | |
475 | posOffset = 7; | |
476 | break; | |
477 | case kTMEMCalGamma: | |
478 | posOffset = 0; | |
479 | break; | |
480 | case kTMEMCalLevel0: | |
481 | posOffset = 0; | |
482 | break; | |
483 | default: | |
484 | posOffset = 0; | |
485 | break; | |
486 | }; | |
487 | fGeom->GetAbsFastORIndexFromPositionInEMCAL(globCol+posOffset, globRow+posOffset, absId); | |
488 | fGeom->GetCellIndexFromFastORIndex(absId, cellAbsId); | |
489 | TVector3 center1; | |
490 | fGeom->GetGlobal(cellAbsId[3], center1); | |
f9a1843e | 491 | |
05a42e4d | 492 | switch(type){ |
493 | case kTMEMCalJet: | |
494 | posOffset = 8; | |
495 | break; | |
496 | case kTMEMCalGamma: | |
497 | posOffset = 1; | |
498 | break; | |
499 | case kTMEMCalLevel0: | |
500 | posOffset = 1; | |
501 | break; | |
502 | }; | |
503 | fGeom->GetAbsFastORIndexFromPositionInEMCAL(globCol+posOffset, globRow+posOffset, absId); | |
504 | fGeom->GetCellIndexFromFastORIndex(absId, cellAbsId); | |
505 | TVector3 center2; | |
506 | fGeom->GetGlobal(cellAbsId[0], center2); | |
f9a1843e | 507 | |
05a42e4d | 508 | TVector3 centerGeo(center1); |
509 | centerGeo += center2; | |
510 | centerGeo *= 0.5; | |
f9a1843e | 511 | |
05a42e4d | 512 | // relate all to primary vertex |
513 | centerGeo -= vertex; | |
514 | centerMass -= vertex; | |
515 | edge1 -= vertex; | |
516 | edge2 -= vertex; | |
36e1f11b | 517 | |
518 | Int_t isMC = MCEvent() ? 1 : 0; | |
519 | Int_t offSet = (1 - isMC) * kTriggerTypeEnd; | |
f9a1843e | 520 | |
05a42e4d | 521 | // fix tbits .. remove the unwanted type triggers |
522 | // for Jet and Gamma triggers we remove also the level 0 bit since it will be stored in the level 0 patch | |
523 | // for level 0 we remove all gamma and jet trigger bits | |
524 | switch(type){ | |
525 | case kTMEMCalJet: | |
526 | tBits = tBits & ~( 1 << (kTriggerTypeEnd + kL1GammaLow) | 1 << (kTriggerTypeEnd + kL1GammaHigh) | 1 << (kL1GammaLow) | 1 << (kL1GammaHigh) | | |
527 | 1 << (kTriggerTypeEnd + kL0) | 1 << (kL0)); | |
528 | break; | |
529 | case kTMEMCalGamma: | |
530 | tBits = tBits & ~( 1 << (kTriggerTypeEnd + kL1JetLow) | 1 << (kTriggerTypeEnd + kL1JetHigh) | 1 << (kL1JetLow) | 1 << (kL1JetHigh) | | |
531 | 1 << (kTriggerTypeEnd + kL0) | 1 << (kL0)); | |
532 | break; | |
533 | case kTMEMCalLevel0: | |
36e1f11b | 534 | // Explicitly set the level 0 bit to overcome the masking out |
535 | tBits |= 1 << (offSet + kL0); | |
05a42e4d | 536 | tBits = tBits & ~( 1 << (kTriggerTypeEnd + kL1JetLow) | 1 << (kTriggerTypeEnd + kL1JetHigh) | 1 << (kL1JetLow) | 1 << (kL1JetHigh) | |
537 | 1 << (kTriggerTypeEnd + kL1GammaLow) | 1 << (kTriggerTypeEnd + kL1GammaHigh) | 1 << (kL1GammaLow) | 1 << (kL1GammaHigh)); | |
538 | break; | |
539 | }; | |
540 | ||
541 | // save the trigger object | |
542 | AliEmcalTriggerPatchInfo *trigger = | |
543 | new ((*fCaloTriggersOut)[fITrigger]) AliEmcalTriggerPatchInfo(); | |
544 | fITrigger++; | |
05a42e4d | 545 | trigger->SetCenterGeo(centerGeo, amp); |
546 | trigger->SetCenterMass(centerMass, amp); | |
547 | trigger->SetEdge1(edge1, amp); | |
548 | trigger->SetEdge2(edge2, amp); | |
549 | trigger->SetADCAmp(adcAmp); | |
550 | trigger->SetTriggerBits(tBits); | |
551 | trigger->SetOffSet(offSet); | |
552 | trigger->SetEdgeCell(globCol*2, globRow*2); // from triggers to cells | |
19dfd8dd | 553 | if(fDoQA){ |
554 | fQAHistos->FillTH2(Form("RCPos%s", trtypenames[type].Data()), globCol, globRow); | |
555 | fQAHistos->FillTH2(Form("EPCentPos%s", trtypenames[type].Data()), centerGeo.Eta(), centerGeo.Phi()); | |
556 | fQAHistos->FillTH2(Form("PatchADCvsE%s", trtypenames[type].Data()), adcAmp, trigger->GetPatchE()); | |
557 | if(nBitsFound){ | |
558 | for(int ibit = 0; ibit < nBitsFound; ibit++) | |
98192837 | 559 | fQAHistos->FillTH1("triggerBitsSel", bitsFound[ibit]); |
19dfd8dd | 560 | } |
561 | } | |
05a42e4d | 562 | return trigger; |
f9a1843e | 563 | } |
564 | ||
001765f7 | 565 | //________________________________________________________________________ |
566 | void AliEmcalTriggerMaker::RunSimpleOfflineTrigger() | |
567 | { | |
05a42e4d | 568 | // Runs a simple offline trigger algorithm. |
569 | // It creates separate patches for jet and gamma triggers | |
f9a1843e | 570 | // on the same positions (different from STU reconstruction behavior) |
571 | // TODO:: change to merge | |
001765f7 | 572 | |
001765f7 | 573 | TArrayI tBitsArray, rowArray, colArray; |
574 | ||
575 | // 0 thresholds = no processing | |
05a42e4d | 576 | if (fCaloTriggerSetupOut->GetThresholdJetLowSimple() == 0 && |
577 | fCaloTriggerSetupOut->GetThresholdJetHighSimple() == 0 ) | |
001765f7 | 578 | return; |
579 | ||
580 | // run the trigger algo, stepping by 8 towers (= 4 trigger channels) | |
05a42e4d | 581 | for (Int_t i = 0; i < 32; i += 4) { |
582 | for (Int_t j = 0; j < 48; j += 4) { | |
583 | Int_t tSum = 0; | |
584 | Int_t tBits = 0; | |
001765f7 | 585 | // window |
05a42e4d | 586 | for (Int_t k = 0; k < 16; ++k) |
587 | for (Int_t l = 0; l < 16; ++l) | |
001765f7 | 588 | tSum += (ULong64_t)fPatchADCSimple[i+k][j+l]; |
589 | ||
590 | // check thresholds | |
05a42e4d | 591 | if (tSum > fCaloTriggerSetupOut->GetThresholdJetLowSimple()) |
f9a1843e | 592 | tBits = tBits | ( 1 << ( kTriggerTypeEnd + kL1JetLow )); |
05a42e4d | 593 | if (tSum > fCaloTriggerSetupOut->GetThresholdJetHighSimple()) |
f9a1843e | 594 | tBits = tBits | ( 1 << ( kTriggerTypeEnd + kL1JetHigh )); |
001765f7 | 595 | |
596 | // add trigger values | |
05a42e4d | 597 | if (tBits != 0) { |
001765f7 | 598 | // add offline bit |
599 | tBits = tBits | ( 1 << 25 ); | |
001765f7 | 600 | tBitsArray.Set( tBitsArray.GetSize() + 1 ); |
601 | colArray.Set( colArray.GetSize() + 1 ); | |
602 | rowArray.Set( rowArray.GetSize() + 1 ); | |
001765f7 | 603 | tBitsArray[tBitsArray.GetSize()-1] = tBits; |
604 | colArray[colArray.GetSize()-1] = i; | |
605 | rowArray[rowArray.GetSize()-1] = j; | |
606 | } | |
607 | } | |
608 | } // trigger algo | |
609 | ||
f9a1843e | 610 | // 4x4 trigger algo, stepping by 2 towers (= 1 trigger channel) |
05a42e4d | 611 | for (Int_t i = 0; i < 46; ++i) { |
612 | for (Int_t j = 0; j < 62; ++j) { | |
613 | Int_t tSum = 0; | |
614 | Int_t tBits = 0; | |
f9a1843e | 615 | |
616 | // window | |
05a42e4d | 617 | for (Int_t k = 0; k < 2; ++k) |
618 | for (Int_t l = 0; l < 2; ++l) | |
f9a1843e | 619 | tSum += (ULong64_t)fPatchADCSimple[i+k][j+l]; |
620 | ||
621 | // check thresholds | |
05a42e4d | 622 | if (tSum > fCaloTriggerSetupOut->GetThresholdGammaLowSimple()) |
f9a1843e | 623 | tBits = tBits | ( 1 << ( kTriggerTypeEnd + kL1GammaLow )); |
05a42e4d | 624 | if (tSum > fCaloTriggerSetupOut->GetThresholdGammaHighSimple()) |
f9a1843e | 625 | tBits = tBits | ( 1 << ( kTriggerTypeEnd + kL1GammaHigh )); |
626 | ||
627 | // add trigger values | |
05a42e4d | 628 | if (tBits != 0) { |
f9a1843e | 629 | // add offline bit |
630 | tBits = tBits | ( 1 << 25 ); | |
f9a1843e | 631 | tBitsArray.Set( tBitsArray.GetSize() + 1 ); |
632 | colArray.Set( colArray.GetSize() + 1 ); | |
633 | rowArray.Set( rowArray.GetSize() + 1 ); | |
f9a1843e | 634 | tBitsArray[tBitsArray.GetSize()-1] = tBits; |
635 | colArray[colArray.GetSize()-1] = i; | |
636 | rowArray[rowArray.GetSize()-1] = j; | |
637 | } | |
638 | } | |
639 | } // trigger algo | |
640 | ||
001765f7 | 641 | // save in object |
642 | fSimpleOfflineTriggers->DeAllocate(); | |
05a42e4d | 643 | fSimpleOfflineTriggers->Allocate(tBitsArray.GetSize()); |
644 | for (Int_t i = 0; i < tBitsArray.GetSize(); ++i){ | |
645 | fSimpleOfflineTriggers->Add(colArray[i],rowArray[i], 0, 0, 0, 0, 0, tBitsArray[i]); | |
001765f7 | 646 | } |
001765f7 | 647 | } |
648 | ||
649 | //________________________________________________________________________ | |
05a42e4d | 650 | Bool_t AliEmcalTriggerMaker::NextTrigger(Bool_t &isOfflineSimple) |
001765f7 | 651 | { |
05a42e4d | 652 | // Get next trigger |
001765f7 | 653 | |
001765f7 | 654 | isOfflineSimple = kFALSE; |
05a42e4d | 655 | Bool_t loopContinue = fCaloTriggers->Next(); |
656 | if (!loopContinue) { | |
001765f7 | 657 | loopContinue = fSimpleOfflineTriggers->Next(); |
658 | isOfflineSimple = kTRUE; | |
659 | } | |
001765f7 | 660 | return loopContinue; |
661 | } | |
1645a556 | 662 | |
663 | //________________________________________________________________________ | |
664 | Bool_t AliEmcalTriggerMaker::CheckForL0(const AliVCaloTrigger& trg) const { | |
19dfd8dd | 665 | // Check whether the patch is a level0 patch |
666 | if(MCEvent()){ | |
667 | // For Monte-Carlo select | |
668 | Int_t tbits(-1); | |
669 | trg.GetTriggerBits(tbits); | |
670 | return tbits & (1 << kL0); | |
671 | } else { | |
672 | // For Data check from the level0 times if the trigger has fired at level0 | |
673 | Int_t nl0times(0); | |
674 | Bool_t l0fired(kFALSE); | |
675 | trg.GetNL0Times(nl0times); | |
676 | if(nl0times){ | |
677 | TArrayI l0times(nl0times); | |
678 | trg.GetL0Times(l0times.GetArray()); | |
679 | // Apply timing cut to see if a L0 has fired | |
680 | for(Int_t *l0timeIter = l0times.GetArray(); l0timeIter < l0times.GetArray() + l0times.GetSize(); l0timeIter++){ | |
681 | if(*l0timeIter > 7 && *l0timeIter < 10){ | |
682 | l0fired = kTRUE; | |
683 | break; | |
684 | } | |
685 | } | |
1645a556 | 686 | } |
19dfd8dd | 687 | return l0fired; |
1645a556 | 688 | } |
1645a556 | 689 | } |