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