]> git.uio.no Git - u/mrichter/AliRoot.git/blame - PWGLF/FORWARD/analysis2/AliFMDEventInspector.cxx
Add extra empty event class, better handling of >0, better handling of pile-up result
[u/mrichter/AliRoot.git] / PWGLF / FORWARD / analysis2 / AliFMDEventInspector.cxx
CommitLineData
7984e5f7 1//
2// This class inspects the event
3//
4// Input:
5// - AliESDFMD object possibly corrected for sharing
6//
7// Output:
8// - A histogram of v_z of events with triggers.
9// - A histogram of v_z of events with vertex and triggers
10// - A histogram of trigger counters
11//
12// Note, that these are added to the master output list
13//
14// Corrections used:
15// - None
16//
8565b10b 17#include "AliFMDEventInspector.h"
c8b1a7db 18#include "AliProdInfo.h"
8565b10b 19#include "AliLog.h"
20#include "AliESDEvent.h"
21#include "AliMultiplicity.h"
22#include "AliAnalysisManager.h"
11d40ecb 23#include "AliMCEventHandler.h"
8565b10b 24#include "AliInputEventHandler.h"
25#include "AliTriggerAnalysis.h"
26#include "AliPhysicsSelection.h"
e85a76b7 27#include "AliOADBPhysicsSelection.h"
8565b10b 28#include "AliAODForwardMult.h"
0bd4b00f 29#include "AliForwardUtil.h"
5e4d905e 30#include "AliCentrality.h"
8565b10b 31#include <TH1.h>
32#include <TList.h>
33#include <TDirectory.h>
0bd4b00f 34#include <TROOT.h>
e6463868 35#include <TParameter.h>
dd556bcd 36#include <TMatrixDSym.h>
c8b1a7db 37#include <TPRegexp.h>
0bd4b00f 38#include <iostream>
39#include <iomanip>
65abd48b 40#include "AliMCEvent.h"
41#include "AliHeader.h"
42#include "AliGenEventHeader.h"
43#include "AliCollisionGeometry.h"
da70cd6a 44#include "AliVVZERO.h"
e1f47419 45
77f97e3f
CHC
46//====================================================================
47namespace {
48 AliPhysicsSelection* GetPhysicsSelection()
49 {
50 AliAnalysisManager* am = AliAnalysisManager::GetAnalysisManager();
51
52 // Get the input handler - should always be there
53 AliInputEventHandler* ih =
54 dynamic_cast<AliInputEventHandler*>(am->GetInputEventHandler());
55 if (!ih) {
56 Warning("GetPhysicsSelection", "No input handler");
57 return 0;
58 }
59 // Get the physics selection - should always be there
60 AliPhysicsSelection* ps =
61 dynamic_cast<AliPhysicsSelection*>(ih->GetEventSelection());
62 if (!ps) {
63 Warning("GetPhysicsSelection", "No physics selection");
64 return 0;
65 }
66 return ps;
67 }
68}
69
8565b10b 70//====================================================================
5ca83fee 71const char* AliFMDEventInspector::fgkFolderName = "fmdEventInspector";
72
73//____________________________________________________________________
8565b10b 74AliFMDEventInspector::AliFMDEventInspector()
75 : TNamed(),
76 fHEventsTr(0),
77 fHEventsTrVtx(0),
5bb5d1f6 78 fHEventsAccepted(0),
96110c91 79 fHEventsAcceptedXY(0),
8565b10b 80 fHTriggers(0),
66cf95f2 81 fHTriggerCorr(0),
0bd4b00f 82 fHType(0),
5ca83fee 83 fHWords(0),
84 fHCent(0),
85 fHCentVsQual(0),
86 fHStatus(0),
8449e3e0 87 fHVtxStatus(0),
e65b8b56 88 fHTrgStatus(0),
e5c41d3e 89 fHPileup(0),
5ca83fee 90 fLowFluxCut(1000),
91 fMaxVzErr(0.2),
92 fList(0),
93 fEnergy(0),
0bd4b00f 94 fField(999),
5ca83fee 95 fCollisionSystem(kUnknown),
e308a636 96 fDebug(0),
5bb5d1f6 97 fCentAxis(0),
e83d0620 98 fVtxAxis(10,-10,10),
0ccdab7b 99 fVtxMethod(kNormal),
100 // fUseFirstPhysicsVertex(false),
5ca83fee 101 fUseV0AND(false),
e5c41d3e 102 fPileupFlags(0x5),
0b7de667 103 fMinPileupContrib(3),
104 fMinPileupDistance(0.8),
0ccdab7b 105// fUseDisplacedVertices(false),
0b7de667 106 fDisplacedVertex(),
107 fCollWords(),
108 fBgWords(),
109 fCentMethod("V0M"),
110 fMinCent(-1.0),
111 fMaxCent(-1.0),
0ccdab7b 112// fUsepA2012Vertex(false),
0b7de667 113 fRunNumber(0),
114 fMC(false),
115 fProdYear(-1),
116 fProdLetter('?'),
117 fProdPass(-1),
118 fProdSVN(-1),
119 fProdMC(false)
8565b10b 120{
7984e5f7 121 //
122 // Constructor
123 //
241cca4d 124 DGUARD(fDebug,1,"Default CTOR of AliFMDEventInspector");
8565b10b 125}
126
127//____________________________________________________________________
128AliFMDEventInspector::AliFMDEventInspector(const char* name)
5ca83fee 129 : TNamed(fgkFolderName, name),
8565b10b 130 fHEventsTr(0),
131 fHEventsTrVtx(0),
5bb5d1f6 132 fHEventsAccepted(0),
96110c91 133 fHEventsAcceptedXY(0),
8565b10b 134 fHTriggers(0),
66cf95f2 135 fHTriggerCorr(0),
0bd4b00f 136 fHType(0),
fe52e455 137 fHWords(0),
5e4d905e 138 fHCent(0),
e308a636 139 fHCentVsQual(0),
241cca4d 140 fHStatus(0),
8449e3e0 141 fHVtxStatus(0),
142 fHTrgStatus(0),
e5c41d3e 143 fHPileup(0),
8565b10b 144 fLowFluxCut(1000),
9d05ffeb 145 fMaxVzErr(0.2),
8565b10b 146 fList(0),
0bd4b00f 147 fEnergy(0),
148 fField(999),
149 fCollisionSystem(kUnknown),
e308a636 150 fDebug(0),
5bb5d1f6 151 fCentAxis(0),
e83d0620 152 fVtxAxis(10,-10,10),
0ccdab7b 153 fVtxMethod(kNormal),
154// fUseFirstPhysicsVertex(false),
e6463868 155 fUseV0AND(false),
e5c41d3e 156 fPileupFlags(0x5),
e6463868 157 fMinPileupContrib(3),
65abd48b 158 fMinPileupDistance(0.8),
0ccdab7b 159// fUseDisplacedVertices(false),
241cca4d 160 fDisplacedVertex(),
161 fCollWords(),
5934a3e3 162 fBgWords(),
4f9319f3 163 fCentMethod("V0M"),
8449e3e0 164 fMinCent(-1.0),
165 fMaxCent(-1.0),
0ccdab7b 166// fUsepA2012Vertex(false),
e65b8b56 167 fRunNumber(0),
0b7de667 168 fMC(false),
169 fProdYear(-1),
170 fProdLetter('?'),
171 fProdPass(-1),
172 fProdSVN(-1),
173 fProdMC(false)
8565b10b 174{
7984e5f7 175 //
176 // Constructor
177 //
178 // Parameters:
179 // name Name of object
180 //
241cca4d 181 DGUARD(fDebug,1,"Named CTOR of AliFMDEventInspector: %s", name);
77f97e3f
CHC
182 if (!GetPhysicsSelection()) {
183 AliFatal("No physics selection defined in manager\n"
184 "=======================================================\n"
185 " The use of AliFMDEventInspector _requires_ a valid\n"
186 " AliPhysicsSelection registered with the input handler.\n\n"
187 " Please check our train setup\n"
188 "=======================================================\n");
189}
8565b10b 190}
191
8565b10b 192//____________________________________________________________________
193AliFMDEventInspector::~AliFMDEventInspector()
194{
7984e5f7 195 //
196 // Destructor
197 //
c929bc03 198 DGUARD(fDebug,1,"DTOR of AliFMDEventInspector");
199 // if (fList) delete fList;
8565b10b 200}
8565b10b 201
5934a3e3 202//____________________________________________________________________
203void
204AliFMDEventInspector::SetCentralityMethod(ECentMethod m)
205{
206 switch (m) {
207 case kV0Multiplicity: fCentMethod = "VOM"; break; // VZERO multiplicity
208 case kV0Amplitude: fCentMethod = "V0A"; break; // VZERO amplitude
209 case kV0Charge: fCentMethod = "V0C"; break; // VZERO charge
210 case kFMDRough: fCentMethod = "FMD"; break; // FMD scaled energy l
211 case kNTracks: fCentMethod = "TRK"; break; // Number of tracks
212 case kLTracks: fCentMethod = "TKL"; break; // Number of tracks
213 case kCL0: fCentMethod = "CL0"; break; //
214 case kCL1: fCentMethod = "CL1"; break; //
215 case kCND: fCentMethod = "CND"; break; //
216 case kNParticles: fCentMethod = "NPA"; break; // Neutral particles
217 case kNeutrons: fCentMethod = "ZNA"; break; // ZDC neutron amplitu
218 case kV0vsFMD: fCentMethod = "V0MvsFMD"; break; // VZERO versus FMD
219 case kV0vsNTracks: fCentMethod = "TKLvsVOM"; break; // Tracks versus VZERO
220 case kZEMvsZDC: fCentMethod = "ZEMvsZDC"; break; // ZDC
221 default: fCentMethod = "V0M"; break;
222 }
223}
224
8449e3e0 225//____________________________________________________________________
226void
227AliFMDEventInspector::SetMinCentrality(Double_t minCent)
228{
229 AliWarning("\n"
230 "*******************************************************\n"
231 "* Setting centrality cuts in this stage is deprecated *\n"
232 "*******************************************************");
233 fMinCent = minCent;
234}
235//____________________________________________________________________
236void
237AliFMDEventInspector::SetMaxCentrality(Double_t maxCent)
238{
239 AliWarning("\n"
240 "*******************************************************\n"
241 "* Setting centrality cuts in this stage is deprecated *\n"
242 "*******************************************************");
243 fMaxCent = maxCent;
244}
245
8565b10b 246//____________________________________________________________________
247Bool_t
fb3430ac 248AliFMDEventInspector::FetchHistograms(const TList* d,
8565b10b 249 TH1I*& hEventsTr,
250 TH1I*& hEventsTrVtx,
5ca83fee 251 TH1I*& hEventsAcc,
8565b10b 252 TH1I*& hTriggers) const
253{
7984e5f7 254 //
255 // Fetch our histograms from the passed list
256 //
257 // Parameters:
258 // d Input
259 // hEventsTr On return, pointer to histogram, or null
260 // hEventsTrVtx On return, pointer to histogram, or null
261 // hTriggers On return, pointer to histogram, or null
262 //
263 // Return:
264 // true on success, false otherwise
265 //
6ab100ec 266 DGUARD(fDebug,3,"Fetch histograms in AliFMDEventInspector");
8565b10b 267 hEventsTr = 0;
268 hEventsTrVtx = 0;
5ca83fee 269 hEventsAcc = 0;
270 hTriggers = 0;
8565b10b 271 TList* dd = dynamic_cast<TList*>(d->FindObject(GetName()));
272 if (!dd) return kFALSE;
273
274 hEventsTr = dynamic_cast<TH1I*>(dd->FindObject("nEventsTr"));
275 hEventsTrVtx = dynamic_cast<TH1I*>(dd->FindObject("nEventsTrVtx"));
5ca83fee 276 hEventsAcc = dynamic_cast<TH1I*>(dd->FindObject("nEventsAccepted"));
8565b10b 277 hTriggers = dynamic_cast<TH1I*>(dd->FindObject("triggers"));
278
5ca83fee 279 if (!hEventsTr ||
280 !hEventsTrVtx ||
281 !hEventsAcc ||
282 !hTriggers) return kFALSE;
8565b10b 283 return kTRUE;
284}
241cca4d 285//____________________________________________________________________
286void
287AliFMDEventInspector::CacheConfiguredTriggerClasses(TList& cache,
288 const TList* classes,
289 AliOADBPhysicsSelection* o)
290{
291 TIter nextClass(classes);
292 TObjString* trigClass = 0;
293 // Loop over all trigger classes. Trigger classes have the format
294 //
295 // class := positive_words SPACE(s) negative_words
296 // positive_words :=
297 // | '+' words
298 // negative_words :=
299 // | '-' words
300 // words := word
301 // | word ',' words
302 //
303 while ((trigClass = static_cast<TObjString*>(nextClass()))) {
304 // Tokenize on space to get positive and negative parts
305 TString side = o->GetBeamSide(trigClass->String());
306 TObjArray* parts = trigClass->String().Tokenize(" ");
307 TObjString* part = 0;
308 TIter nextPart(parts);
309 while ((part = static_cast<TObjString*>(nextPart()))) {
310 // We only care about the positive ones
311 if (part->GetName()[0] != '+') continue;
312 part->String().Remove(0,1);
313
314 // Tokenize on a comma to get the words
315 TObjArray* words = part->String().Tokenize(",");
316 TObjString* word = 0;
317 TIter nextWord(words);
318 while ((word = static_cast<TObjString*>(nextWord()))) {
319 TNamed* store = new TNamed(word->String(), side);
320 cache.Add(store);
321 DMSG(fDebug,3,"Caching %s trigger word %s",
322 store->GetTitle(), store->GetName());
323 } // while (word)
324 delete words;
325 }
326 delete parts;
327 }
328}
329
8565b10b 330//____________________________________________________________________
331void
5934a3e3 332AliFMDEventInspector::SetupForData(const TAxis& vtxAxis)
8565b10b 333{
7984e5f7 334 //
241cca4d 335 // Initialize the object - this is called on the first seen event.
7984e5f7 336 //
337 // Parameters:
338 // vtxAxis Vertex axis in use
339 //
6ab100ec 340 DGUARD(fDebug,1,"Initialize in AliFMDEventInspector");
241cca4d 341
241cca4d 342 // Get the physics selection - should always be there
77f97e3f 343 AliPhysicsSelection* ps = GetPhysicsSelection();
241cca4d 344 if (!ps) {
345 AliWarning("No physics selection");
346 return;
347 }
348 // Get the configured triggers
349 AliOADBPhysicsSelection* oadb =
350 const_cast<AliOADBPhysicsSelection*>(ps->GetOADBPhysicsSelection());
351 if (!oadb) {
352 AliWarning("No OADB physics selection object");
353 return;
354 }
355 // Get the configured trigger words from the physics selection
356 const TList* collTriggClasses = ps->GetCollisionTriggerClasses();
357 const TList* bgTriggClasses = ps->GetBGTriggerClasses();
358 if (!collTriggClasses) {
359 AliWarning("No configured collision trigger classes");
360 return;
361 }
362 if (!bgTriggClasses) {
363 AliWarning("No configured background trigger classes");
364 return;
365 }
366 CacheConfiguredTriggerClasses(fCollWords, collTriggClasses, oadb);
367 CacheConfiguredTriggerClasses(fBgWords, bgTriggClasses, oadb);
368 // fCollWords.ls();
369 // fBgWords.ls();
370
e308a636 371
8449e3e0 372 TArrayD limits;
373 if ((fMinCent < 0 && fMaxCent < 0) || fMaxCent <= fMinCent) {
77f97e3f 374 // Was:
8449e3e0 375 // -1.5 -0.5 0.5 1.5 ... 89.5 ... 100.5
376 // ----- 92 number --------- ---- 1 ---
77f97e3f
CHC
377 // Now:
378 // -0.5 0.5 1.5 ... 89.5 ... 100.5
379 // ----- 91 number ---- ---- 1 ---
380 limits.Set(92);
381 for (Int_t i = 0; i < 91; i++) limits[i] = -.5 + i;
382 limits[91] = 100.5;
8449e3e0 383 }
384 else {
77f97e3f 385 Int_t n = Int_t(fMaxCent-fMinCent+2);
8449e3e0 386 limits.Set(n);
387 for (Int_t i = 0; i < n; i++) {
388 limits[i] = fMinCent + i - .5;
389 }
390 }
391
5bb5d1f6 392 fVtxAxis.Set(vtxAxis.GetNbins(), vtxAxis.GetXmin(), vtxAxis.GetXmax());
e308a636 393
394 fCentAxis = new TAxis(limits.GetSize()-1, limits.GetArray());
8565b10b 395 fHEventsTr = new TH1I("nEventsTr", "Number of events w/trigger",
5bb5d1f6 396 4*vtxAxis.GetNbins(),
397 2*vtxAxis.GetXmin(),
398 2*vtxAxis.GetXmax());
8565b10b 399 fHEventsTr->SetXTitle("v_{z} [cm]");
400 fHEventsTr->SetYTitle("# of events");
401 fHEventsTr->SetFillColor(kRed+1);
402 fHEventsTr->SetFillStyle(3001);
403 fHEventsTr->SetDirectory(0);
404 // fHEventsTr->Sumw2();
405 fList->Add(fHEventsTr);
406
5bb5d1f6 407 fHEventsTrVtx = static_cast<TH1I*>(fHEventsTr->Clone("nEventsTrVtx"));
408 fHEventsTrVtx->SetTitle("Number of events w/trigger and vertex");
8565b10b 409 fHEventsTrVtx->SetFillColor(kBlue+1);
8565b10b 410 fHEventsTrVtx->SetDirectory(0);
411 // fHEventsTrVtx->Sumw2();
412 fList->Add(fHEventsTrVtx);
413
5bb5d1f6 414 fHEventsAccepted = new TH1I("nEventsAccepted",
415 "Number of events w/trigger and vertex in range",
416 2*vtxAxis.GetNbins(),
417 2*vtxAxis.GetXmin(),
418 2*vtxAxis.GetXmax());
419 fHEventsAccepted->SetXTitle("v_{z} [cm]");
420 fHEventsAccepted->SetYTitle("# of events");
421 fHEventsAccepted->SetFillColor(kGreen+1);
422 fHEventsAccepted->SetFillStyle(3001);
423 fHEventsAccepted->SetDirectory(0);
424 // fHEventsAccepted->Sumw2();
425 fList->Add(fHEventsAccepted);
426
96110c91 427 fHEventsAcceptedXY = new TH2D("nEventsAcceptedXY",
428 "XY vertex w/trigger and Z vertex in range",
429 1000,-1,1,1000,-1,1);
430
431 fHEventsAcceptedXY->SetXTitle("v_{x} [cm]");
432 fHEventsAcceptedXY->SetYTitle("v_{y} [cm]");
433 fHEventsAcceptedXY->SetDirectory(0);
434 // fHEventsAccepted->Sumw2();
435 fList->Add(fHEventsAcceptedXY);
436
437
0be6c8cd 438 fHTriggers = new TH1I("triggers", "Triggers", kOffline+1, 0, kOffline+1);
8565b10b 439 fHTriggers->SetFillColor(kRed+1);
440 fHTriggers->SetFillStyle(3001);
441 fHTriggers->SetStats(0);
442 fHTriggers->SetDirectory(0);
66cf95f2 443
444 fHTriggerCorr = new TH2I("triggerCorr", "Trigger correlation",
445 kOffline+1, 0, kOffline+1,
446 kOffline+1, 0, kOffline+1);
447 fHTriggerCorr->SetStats(0);
448 fHTriggerCorr->SetDirectory(0);
cd51b0dd 449 fHTriggerCorr->SetXTitle("Requirement");
450 fHTriggerCorr->SetYTitle("Companion");
451
66cf95f2 452 Int_t binNum[] = { kInel +1,
453 kInelGt0+1,
454 kNSD +1,
455 kV0AND +1,
456 kEmpty +1,
457 kA +1,
458 kB +1,
459 kC +1,
460 kE +1,
461 kPileUp +1,
462 kMCNSD +1,
8449e3e0 463 kSatellite+1,
e5c41d3e 464 kSpdOutlier+1,
66cf95f2 465 kOffline+1 };
466 const char* binLbl[] = { "INEL",
467 "INEL>0",
468 "NSD",
469 "VOAND",
470 "Empty",
471 "A",
472 "B",
473 "C",
474 "E",
475 "Pileup",
476 "NSD_{MC}",
8449e3e0 477 "Satellite",
e5c41d3e 478 "SPD outlier",
66cf95f2 479 "Offline" };
cd51b0dd 480 for (Int_t i = 0; i < kOffline+1; i++) {
66cf95f2 481 fHTriggers->GetXaxis()->SetBinLabel(binNum[i], binLbl[i]);
482 fHTriggerCorr->GetXaxis()->SetBinLabel(binNum[i], binLbl[i]);
483 fHTriggerCorr->GetYaxis()->SetBinLabel(binNum[i], binLbl[i]);
484 }
8565b10b 485 fList->Add(fHTriggers);
66cf95f2 486 fList->Add(fHTriggerCorr);
487
0bd4b00f 488
489 fHType = new TH1I("type", Form("Event type (cut: SPD mult>%d)",
490 fLowFluxCut), 2, -.5, 1.5);
491 fHType->SetFillColor(kRed+1);
492 fHType->SetFillStyle(3001);
493 fHType->SetStats(0);
494 fHType->SetDirectory(0);
495 fHType->GetXaxis()->SetBinLabel(1,"Low-flux");
496 fHType->GetXaxis()->SetBinLabel(2,"High-flux");
497 fList->Add(fHType);
fe52e455 498
c56f8519 499#if 0
500 // This histogram disabled as it causes problems in the merge
fe52e455 501 fHWords = new TH1I("words", "Trigger words seen", 1, 0, 0);
502 fHWords->SetFillColor(kBlue+1);
503 fHWords->SetFillStyle(3001);
504 fHWords->SetStats(0);
505 fHWords->SetDirectory(0);
506 fHWords->SetBit(TH1::kCanRebin);
507 fList->Add(fHWords);
c56f8519 508#endif
5e4d905e 509
e308a636 510 fHCent = new TH1F("cent", "Centrality", limits.GetSize()-1,limits.GetArray());
5e4d905e 511 fHCent->SetFillColor(kBlue+1);
512 fHCent->SetFillStyle(3001);
513 fHCent->SetStats(0);
514 fHCent->SetDirectory(0);
515 fHCent->SetXTitle("Centrality [%]");
516 fHCent->SetYTitle("Events");
517 fList->Add(fHCent);
e308a636 518
519 fHCentVsQual = new TH2F("centVsQuality", "Quality vs Centrality",
520 5, 0, 5, limits.GetSize()-1, limits.GetArray());
521 fHCentVsQual->SetXTitle("Quality");
522 fHCentVsQual->SetYTitle("Centrality [%]");
523 fHCentVsQual->SetZTitle("Events");
524 fHCentVsQual->GetXaxis()->SetBinLabel(1, "OK");
525 fHCentVsQual->GetXaxis()->SetBinLabel(2, "Outside v_{z} cut");
526 fHCentVsQual->GetXaxis()->SetBinLabel(3, "V0 vs SPD outlier");
527 fHCentVsQual->GetXaxis()->SetBinLabel(4, "V0 vs TPC outlier");
528 fHCentVsQual->GetXaxis()->SetBinLabel(5, "V0 vs ZDC outlier");
b7ab8a2c 529 fHCentVsQual->SetDirectory(0);
e308a636 530 fList->Add(fHCentVsQual);
241cca4d 531
77f97e3f 532 fHStatus = new TH1I("status", "Status", 8, 1, 9);
8449e3e0 533 fHStatus->SetFillColor(kBlue+1);
241cca4d 534 fHStatus->SetFillStyle(3001);
535 fHStatus->SetStats(0);
536 fHStatus->SetDirectory(0);
8449e3e0 537 TAxis* xAxis = fHStatus->GetXaxis();
538 xAxis->SetBinLabel(1, "OK");
539 xAxis->SetBinLabel(2, "No event");
540 xAxis->SetBinLabel(3, "No triggers");
541 xAxis->SetBinLabel(4, "No SPD");
542 xAxis->SetBinLabel(5, "No FMD");
543 xAxis->SetBinLabel(6, "No vertex");
544 xAxis->SetBinLabel(7, "Bad vertex");
77f97e3f 545 xAxis->SetBinLabel(8, "No centrality");
241cca4d 546 fList->Add(fHStatus);
8449e3e0 547
548 fHVtxStatus = new TH1I("vtxStatus","Vertex Status",
549 kNotVtxZ,kVtxOK,kNotVtxZ+1);
550 fHVtxStatus->SetFillColor(kGreen+1);
551 fHVtxStatus->SetFillStyle(3001);
552 fHVtxStatus->SetStats(0);
553 fHVtxStatus->SetDirectory(0);
554 xAxis = fHVtxStatus->GetXaxis();
555 xAxis->SetBinLabel(kVtxOK, "OK");
556 xAxis->SetBinLabel(kNoVtx, "None/bad status");
557 xAxis->SetBinLabel(kNoSPDVtx, "No SPD/bad status");
558 xAxis->SetBinLabel(kFewContrib, "N_{contrib} <= 0");
559 xAxis->SetBinLabel(kUncertain, Form("#delta z > %4.2f", fMaxVzErr));
560 xAxis->SetBinLabel(kNotVtxZ, "Not Z vertexer");
561 fList->Add(fHVtxStatus);
562
563 fHTrgStatus = new TH1I("trgStatus", "Trigger Status",
564 kOther, kNoTrgWords, kOther+1);
565 fHTrgStatus->SetFillColor(kMagenta+1);
566 fHTrgStatus->SetFillStyle(3001);
567 fHTrgStatus->SetStats(0);
568 fHTrgStatus->SetDirectory(0);
569 xAxis = fHTrgStatus->GetXaxis();
570 xAxis->SetBinLabel(kNoTrgWords, "No words");
571 xAxis->SetBinLabel(kPP2760Fast, "FAST in pp@#sqrt{s}=2.76TeV");
572 xAxis->SetBinLabel(kMUON, "Muon trigger");
573 xAxis->SetBinLabel(kTriggered, "Triggered");
574 xAxis->SetBinLabel(kMinBias, "CINT1 (V0A||V0C||FASTOR)");
575 xAxis->SetBinLabel(kMinBiasNoSPD, "CINT5 (V0A||V0C)");
576 xAxis->SetBinLabel(kV0AndTrg, "CINT7 (V0A&&V0C)");
577 xAxis->SetBinLabel(kHighMult, "N>>0");
578 xAxis->SetBinLabel(kCentral, "Central");
579 xAxis->SetBinLabel(kSemiCentral, "Semi-central");
580 xAxis->SetBinLabel(kDiffractive, "Diffractive");
581 xAxis->SetBinLabel(kUser, "User");
582 xAxis->SetBinLabel(kOther, "Other");
583 fList->Add(fHTrgStatus);
584
e5c41d3e 585 fHPileup = new TH1I("pileupStatus", "Pile-up status", 3, 0, 3);
586 fHPileup->SetFillColor(kYellow+2);
587 fHPileup->SetFillStyle(3001);
588 fHPileup->SetStats(0);
589 fHPileup->SetDirectory(0);
590 xAxis = fHPileup->GetXaxis();
591 xAxis->SetBinLabel(1, "SPD tracklets");
592 xAxis->SetBinLabel(2, "Tracks");
593 xAxis->SetBinLabel(3, "Out-of-bunch");
594 fList->Add(fHPileup);
595
0ccdab7b 596 if (AllowDisplaced()) fDisplacedVertex.SetupForData(fList, "", false);
8565b10b 597}
598
f7cfc454 599//____________________________________________________________________
600void
8449e3e0 601AliFMDEventInspector::StoreInformation()
f7cfc454 602{
603 // Write TNamed objects to output list containing information about
604 // the running conditions
6ab100ec 605 DGUARD(fDebug,2,"Store information from AliFMDEventInspector");
f7cfc454 606 if (!fList) return;
607
241cca4d 608
609 fList->Add(AliForwardUtil::MakeParameter("sys", fCollisionSystem));
610 fList->Add(AliForwardUtil::MakeParameter("sNN", fEnergy));
611 fList->Add(AliForwardUtil::MakeParameter("field", fField));
8449e3e0 612 fList->Add(AliForwardUtil::MakeParameter("runNo", fRunNumber));
241cca4d 613 fList->Add(AliForwardUtil::MakeParameter("lowFlux", fLowFluxCut));
0ccdab7b 614 fList->Add(AliForwardUtil::MakeParameter("ipMethod", fVtxMethod));
615 //fList->Add(AliForwardUtil::MakeParameter("fpVtx",fUseFirstPhysicsVertex));
241cca4d 616 fList->Add(AliForwardUtil::MakeParameter("v0and",fUseV0AND));
e5c41d3e 617 fList->Add(AliForwardUtil::MakeParameter("pileup", fPileupFlags));
241cca4d 618 fList->Add(AliForwardUtil::MakeParameter("nPileUp", fMinPileupContrib));
619 fList->Add(AliForwardUtil::MakeParameter("dPileup", fMinPileupDistance));
0ccdab7b 620 fList->Add(AliForwardUtil::MakeParameter("satellite", AllowDisplaced()));
1ff25622 621 fList->Add(AliForwardUtil::MakeParameter("alirootRev",
622 AliForwardUtil::AliROOTRevision()));
623 fList->Add(AliForwardUtil::MakeParameter("alirootBranch",
624 AliForwardUtil::AliROOTBranch()));
e65b8b56 625 fList->Add(AliForwardUtil::MakeParameter("mc", fMC));
1ff25622 626
f7cfc454 627}
628
c8b1a7db 629//____________________________________________________________________
630void
631AliFMDEventInspector::StoreProduction()
632{
633 if (!fList) return;
634
635 AliAnalysisManager *mgr=AliAnalysisManager::GetAnalysisManager();
636 AliVEventHandler *inputHandler=mgr->GetInputEventHandler();
637 if (!inputHandler) {
638 AliWarning("Got no input handler");
639 return;
640 }
641 TList *uiList = inputHandler->GetUserInfo();
642 if (!uiList) {
643 AliWarning("Got no user list from input tree");
644 return;
645 }
646
647 AliProdInfo p(uiList);
648 p.List();
649 if (p.GetAlirootSvnVersion() <= 0) return;
650
651 // Make our output list
652 TList* out = new TList;
653 out->SetOwner(true);
654 out->SetName("production");
655 // out->SetTitle("ESD production details");
656 fList->Add(out);
657
658 TString period = p.GetLHCPeriod();
659 // TString aliROOTVersion = p.GetAlirootVersion();
0b7de667 660 fProdSVN = p.GetAlirootSvnVersion();
c8b1a7db 661 // TString rootVersion = p.GetRootVersion();
662 Int_t rootSVN = p.GetRootSvnVersion();
0b7de667 663 fProdPass = p.GetRecoPass();
664 fProdMC = p.IsMC();
0e8bd15f
AH
665
666 if (period.Length() > 0) {
667 TObjArray* pp = TPRegexp("LHC([0-9]+)([a-z]+)").MatchS(period);
668 fProdYear = static_cast<TObjString*>(pp->At(1))->String().Atoi();
669 fProdLetter = static_cast<TObjString*>(pp->At(2))->String()[0];
670 pp->Delete();
671 }
c8b1a7db 672
0b7de667 673 out->Add(AliForwardUtil::MakeParameter("year", fProdYear));
674 out->Add(AliForwardUtil::MakeParameter("letter", Int_t(fProdLetter)));
675 out->Add(AliForwardUtil::MakeParameter("alirootSVN", fProdSVN));
c8b1a7db 676 out->Add(AliForwardUtil::MakeParameter("rootSVN", rootSVN));
0b7de667 677 out->Add(AliForwardUtil::MakeParameter("pass", fProdPass));
678 out->Add(AliForwardUtil::MakeParameter("mc", fProdMC));
c8b1a7db 679}
680
681
682
683
8565b10b 684//____________________________________________________________________
685void
5934a3e3 686AliFMDEventInspector::CreateOutputObjects(TList* dir)
8565b10b 687{
7984e5f7 688 //
689 // Define the output histograms. These are put in a sub list of the
690 // passed list. The histograms are merged before the parent task calls
691 // AliAnalysisTaskSE::Terminate
692 //
693 // dir Directory to add to
694 //
6ab100ec 695 DGUARD(fDebug,1,"Define output from AliFMDEventInspector");
8565b10b 696 fList = new TList;
697 fList->SetName(GetName());
c929bc03 698 fList->SetOwner();
8565b10b 699 dir->Add(fList);
700}
701
702//____________________________________________________________________
703UInt_t
704AliFMDEventInspector::Process(const AliESDEvent* event,
705 UInt_t& triggers,
706 Bool_t& lowFlux,
0bd4b00f 707 UShort_t& ivz,
5ca83fee 708 TVector3& ip,
5bb5d1f6 709 Double_t& cent,
710 UShort_t& nClusters)
8565b10b 711{
7984e5f7 712 //
713 // Process the event
714 //
715 // Parameters:
716 // event Input event
717 // triggers On return, the triggers fired
718 // lowFlux On return, true if the event is considered a low-flux
719 // event (according to the setting of fLowFluxCut)
720 // ivz On return, the found vertex bin (1-based). A zero
721 // means outside of the defined vertex range
722 // vz On return, the z position of the interaction
5e4d905e 723 // cent On return, the centrality - if not available < 0
7984e5f7 724 //
725 // Return:
726 // 0 (or kOk) on success, otherwise a bit mask of error codes
727 //
4f9319f3 728 DGUARD(fDebug,1,"Process event in AliFMDEventInspector");
e1f47419 729 // --- Check that we have an event ---------------------------------
8565b10b 730 if (!event) {
731 AliWarning("No ESD event found for input event");
241cca4d 732 fHStatus->Fill(2);
8565b10b 733 return kNoEvent;
734 }
735
bfab35d9 736 // --- Process satellite event information is requested ------------
0ccdab7b 737 if (AllowDisplaced()) {
bfab35d9 738 if (!fDisplacedVertex.Process(event))
739 AliWarning("Failed to process satellite event");
740 }
741
e1f47419 742 // --- Read trigger information from the ESD and store in AOD object
241cca4d 743 if (!ReadTriggers(*event, triggers, nClusters)) {
0bd4b00f 744 if (fDebug > 2) {
745 AliWarning("Failed to read triggers from ESD"); }
241cca4d 746 fHStatus->Fill(3);
8565b10b 747 return kNoTriggers;
748 }
749
e1f47419 750 // --- Check if this is a high-flux event --------------------------
8565b10b 751 const AliMultiplicity* testmult = event->GetMultiplicity();
752 if (!testmult) {
0bd4b00f 753 if (fDebug > 3) {
754 AliWarning("No central multiplicity object found"); }
8565b10b 755 }
e1f47419 756 else
757 lowFlux = testmult->GetNumberOfTracklets() < fLowFluxCut;
5e4d905e 758
0bd4b00f 759 fHType->Fill(lowFlux ? 0 : 1);
314f6077 760
761 // --- Get the interaction point -----------------------------------
762 Bool_t vzOk = ReadVertex(*event, ip);
763 fHEventsTr->Fill(ip.Z());
764 if (!vzOk) {
765 if (fDebug > 3) {
766 AliWarning("Failed to read vertex from ESD"); }
767 fHStatus->Fill(6);
768 return kNoVertex;
769 }
770
771 // --- Read centrality information
e308a636 772 cent = -10;
773 UShort_t qual = 0;
241cca4d 774 if (!ReadCentrality(*event, cent, qual)) {
e1f47419 775 if (fDebug > 3)
776 AliWarning("Failed to get centrality");
8565b10b 777 }
314f6077 778 // --- check centrality cut
4f9319f3 779
8449e3e0 780 if(fMinCent > -0.0001 && cent < fMinCent) return kNoEvent;
781 if(fMaxCent > -0.0001 && cent > fMaxCent) return kNoEvent;
77f97e3f 782 if (cent >= 0) fHCent->Fill(cent);
e308a636 783 if (qual == 0) fHCentVsQual->Fill(0., cent);
784 else {
77f97e3f 785 fHStatus->Fill(8);
e308a636 786 for (UShort_t i = 0; i < 4; i++)
787 if (qual & (1 << i)) fHCentVsQual->Fill(Double_t(i+1), cent);
788 }
314f6077 789
8565b10b 790
5ca83fee 791 fHEventsTrVtx->Fill(ip.Z());
96110c91 792
e1f47419 793 // --- Get the vertex bin ------------------------------------------
5ca83fee 794 ivz = fVtxAxis.FindBin(ip.Z());
5bb5d1f6 795 if (ivz <= 0 || ivz > fVtxAxis.GetNbins()) {
0bd4b00f 796 if (fDebug > 3) {
8565b10b 797 AliWarning(Form("Vertex @ %f outside of range [%f,%f]",
5ca83fee 798 ip.Z(), fVtxAxis.GetXmin(), fVtxAxis.GetXmax()));
5bb5d1f6 799 }
0bd4b00f 800 ivz = 0;
241cca4d 801 fHStatus->Fill(7);
8565b10b 802 return kBadVertex;
803 }
5ca83fee 804 fHEventsAccepted->Fill(ip.Z());
805 fHEventsAcceptedXY->Fill(ip.X(),ip.Y());
e58000b7 806
e1f47419 807 // --- Check the FMD ESD data --------------------------------------
808 if (!event->GetFMDData()) {
809 if (fDebug > 3) {
810 AliWarning("No FMD data found in ESD"); }
241cca4d 811 fHStatus->Fill(5);
e1f47419 812 return kNoFMD;
813 }
814
241cca4d 815 fHStatus->Fill(1);
8565b10b 816 return kOk;
817}
818
e1f47419 819//____________________________________________________________________
820Bool_t
241cca4d 821AliFMDEventInspector::ReadCentrality(const AliESDEvent& esd,
e308a636 822 Double_t& cent,
823 UShort_t& qual) const
e1f47419 824{
825 //
826 // Read centrality from event
827 //
828 // Parameters:
829 // esd Event
830 // cent On return, the centrality or negative if not found
831 //
832 // Return:
833 // False on error, true otherwise
834 //
6ab100ec 835 DGUARD(fDebug,2,"Read the centrality in AliFMDEventInspector");
241cca4d 836
241cca4d 837 cent = -1;
8449e3e0 838 qual = 1;
241cca4d 839 AliCentrality* centObj = const_cast<AliESDEvent&>(esd).GetCentrality();
8449e3e0 840 if (centObj) {
841 cent = centObj->GetCentralityPercentile(fCentMethod);
842 qual = centObj->GetQuality();
843 }
241cca4d 844
bc31b177 845 // We overwrite with satellite events, so we can be sure to get the
846 // centrality determination from the satellite vertex selection
0ccdab7b 847 if (AllowDisplaced() && fDisplacedVertex.IsSatellite()) {
8449e3e0 848 cent = fDisplacedVertex.GetCentralityPercentile();
849 qual = 0;
850 }
e1f47419 851
852 return true;
853}
854
da70cd6a 855//____________________________________________________________________
856Bool_t
857AliFMDEventInspector::CheckpAExtraV0(const AliESDEvent& esd) const
858{
859 if (fCollisionSystem != AliForwardUtil::kPPb) return true;
860
861 AliVVZERO* esdV0 = esd.GetVZEROData();
862 if ((esdV0->GetV0ADecision()!=1) || (esdV0->GetV0CDecision()!=1))
863 return false;
864 return true;
865}
866
8565b10b 867//____________________________________________________________________
868Bool_t
241cca4d 869AliFMDEventInspector::ReadTriggers(const AliESDEvent& esd, UInt_t& triggers,
5bb5d1f6 870 UShort_t& nClusters)
8565b10b 871{
7984e5f7 872 //
873 // Read the trigger information from the ESD event
874 //
875 // Parameters:
876 // esd ESD event
877 // triggers On return, contains the trigger bits
878 //
879 // Return:
880 // @c true on success, @c false otherwise
881 //
6ab100ec 882 DGUARD(fDebug,2,"Read the triggers in AliFMDEventInspector");
8565b10b 883 triggers = 0;
884
885 // Get the analysis manager - should always be there
886 AliAnalysisManager* am = AliAnalysisManager::GetAnalysisManager();
241cca4d 887 DMSG(fDebug,10,"Got analysis manager %p", am);
8565b10b 888 if (!am) {
889 AliWarning("No analysis manager defined!");
890 return kFALSE;
891 }
892
893 // Get the input handler - should always be there
894 AliInputEventHandler* ih =
895 static_cast<AliInputEventHandler*>(am->GetInputEventHandler());
241cca4d 896 DMSG(fDebug,10,"Got input handler %p", ih);
8565b10b 897 if (!ih) {
898 AliWarning("No input handler");
899 return kFALSE;
900 }
e85a76b7 901
e1f47419 902 // Check if this is a collision candidate (MB)
8449e3e0 903 ///
904 // Historic remark: Note, that we should use the value cached in the
905 // input handler rather than calling IsCollisionCandiate directly
906 // on the AliPhysicsSelection obejct. If we called the latter
907 // then the AliPhysicsSelection object would overcount by a factor
908 // of 2! :-(
909 UInt_t trgMask = ih->IsEventSelected();
910 Bool_t offline = trgMask;
911 Bool_t fastonly = (trgMask & AliVEvent::kFastOnly);
241cca4d 912 TString trigStr = esd.GetFiredTriggerClasses();
913
8449e3e0 914 if (trigStr.IsNull()) fHTrgStatus->Fill(kNoTrgWords);
241cca4d 915 if (fHWords) fHWords->Fill(trigStr.Data(), 1);
11d40ecb 916
0ccdab7b 917 if(AllowDisplaced()) {
241cca4d 918 DMSG(fDebug,3,"Using displaced vertex stuff");
8449e3e0 919 // if (TMath::Abs(fDisplacedVertex.GetVertexZ()) >= 999) offline = false;
920 if (fDisplacedVertex.IsSatellite())
921 triggers |= AliAODForwardMult::kSatellite;
922 }
923
924 if (CheckFastPartition(fastonly)) {
925 fHTrgStatus->Fill(kPP2760Fast);
926 offline = false;
241cca4d 927 }
65abd48b 928
8449e3e0 929 if (offline && CheckCosmics(trigStr)) {
930 fHTrgStatus->Fill(kMUON);
931 offline = false;
932 }
933 if (offline) fHTrgStatus->Fill(kTriggered);
934 Int_t f = 0;
935 if (trgMask & AliVEvent::kMB) f += fHTrgStatus->Fill(kMinBias);
936 if (trgMask & AliVEvent::kCINT5) f += fHTrgStatus->Fill(kMinBiasNoSPD);
937 if (trgMask & AliVEvent::kINT7) f += fHTrgStatus->Fill(kV0AndTrg);
938 if (trgMask & AliVEvent::kHighMult) f += fHTrgStatus->Fill(kHighMult);
939 if (trgMask & AliVEvent::kCentral) f += fHTrgStatus->Fill(kCentral);
940 if (trgMask & AliVEvent::kSemiCentral) f += fHTrgStatus->Fill(kSemiCentral);
941 if (trgMask & AliVEvent::kDG5) f += fHTrgStatus->Fill(kDiffractive);
942 if (trgMask & AliVEvent::kUserDefined) f += fHTrgStatus->Fill(kUser);
943 if (f <= 0) fHTrgStatus->Fill(kOther);
944
c929bc03 945 // if (!CheckpAExtraV0(esd)) offline = false;
241cca4d 946
947 DMSG(fDebug,2,"Event is %striggered by off-line", offline ? "" : "NOT ");
948
dd556bcd 949 if (offline) triggers |= AliAODForwardMult::kOffline;
950 // Only flag as in-elastic if a min-bias trigger is here
951 if (trgMask & AliVEvent::kMB) {
241cca4d 952 triggers |= AliAODForwardMult::kInel;
241cca4d 953 CheckINELGT0(esd, nClusters, triggers);
65abd48b 954 }
955
e5c41d3e 956 AliTriggerAnalysis ta;
957 if (ta.IsSPDClusterVsTrackletBG(&esd, false))
958 // SPD outlier
959 triggers |= AliAODForwardMult::kSPDOutlier;
960
241cca4d 961 CheckNSD(esd,triggers);
cd51b0dd 962 CheckPileup(esd, triggers);
963 CheckEmpty(trigStr, triggers);
964 // if (CheckPileup(esd, triggers)) fHTriggers->Fill(kPileUp+.5);
965 // if (CheckEmpty(trigStr, triggers)) fHTriggers->Fill(kEmpty+.5);
241cca4d 966
8449e3e0 967 CheckWords(esd, triggers);
241cca4d 968
66cf95f2 969#define TEST_TRIG_BIN(RET,BIN,TRIGGERS) \
970 do { switch (BIN) { \
e5c41d3e 971 case kInel: RET = triggers & AliAODForwardMult::kInel; break; \
972 case kInelGt0: RET = triggers & AliAODForwardMult::kInelGt0; break; \
973 case kNSD: RET = triggers & AliAODForwardMult::kNSD; break; \
974 case kV0AND: RET = triggers & AliAODForwardMult::kV0AND; break; \
975 case kEmpty: RET = triggers & AliAODForwardMult::kEmpty; break; \
976 case kA: RET = triggers & AliAODForwardMult::kA; break; \
977 case kB: RET = triggers & AliAODForwardMult::kB; break; \
978 case kC: RET = triggers & AliAODForwardMult::kC; break; \
979 case kE: RET = triggers & AliAODForwardMult::kE; break; \
980 case kPileUp: RET = triggers & AliAODForwardMult::kPileUp; break; \
981 case kMCNSD: RET = triggers & AliAODForwardMult::kMCNSD; break; \
982 case kSatellite: RET = triggers & AliAODForwardMult::kSatellite; break; \
983 case kSpdOutlier:RET = triggers & AliAODForwardMult::kSPDOutlier; break; \
984 case kOffline: RET = triggers & AliAODForwardMult::kOffline; break; \
985 default: RET = false; } } while(false)
66cf95f2 986
8449e3e0 987 if (!fHTriggers) {
988 AliWarning("Histogram of triggers not defined - has init been called");
989 return false;
990 }
241cca4d 991
66cf95f2 992 for (Int_t i = 0; i < kOffline+1; i++) {
993 Bool_t hasX = false;
994 TEST_TRIG_BIN(hasX, i, triggers);
995 if (!hasX) continue;
cd51b0dd 996 fHTriggers->Fill(i+.5);
997 for (Int_t j = 0; j < kOffline+1; j++) {
66cf95f2 998 Bool_t hasY = false;
999 TEST_TRIG_BIN(hasY, j, triggers);
1000 if (!hasY) continue;
1001
1002 fHTriggerCorr->Fill(i+.5, j+.5);
1003 }
1004 }
241cca4d 1005 return kTRUE;
1006}
1007
1008//____________________________________________________________________
1009Bool_t
1010AliFMDEventInspector::CheckFastPartition(bool fastonly) const
1011{
f6736d23 1012 // For the 2.76 TeV p+p run (LHC11a), the FMD ran in the slow partition
11d40ecb 1013 // so it received no triggers from the fast partition. Therefore
1014 // the fast triggers are removed here but not for MC where all
1015 // triggers are fast.
241cca4d 1016 if (TMath::Abs(fEnergy - 2750.) > 20) return false;
1017 if (fCollisionSystem != AliForwardUtil::kPP) return false;
e65b8b56 1018 if (fMC) return false; // All MC events for pp @ 2.76TeV are `fast'
f6736d23 1019 // if (fastonly)
1020 // DMSG(fDebug,1,"Fast trigger in pp @ sqrt(s)=2.76TeV removed");
241cca4d 1021
1022 return fastonly;
1023}
1024
1025//____________________________________________________________________
1026Bool_t
1027AliFMDEventInspector::CheckCosmics(const TString& trigStr) const
1028{
1029 // MUON triggers are not strictly minimum bias (MB) so they are
1030 // removed (HHD)
1031 if(trigStr.Contains("CMUS1")) {
1032 DMSG(fDebug,1,"Cosmic trigger ins't min-bias, removed");
1033 return true;
1034 }
1035 return false;
1036}
1037
1038//____________________________________________________________________
1039Bool_t
1040AliFMDEventInspector::CheckINELGT0(const AliESDEvent& esd,
1041 UShort_t& nClusters,
1042 UInt_t& triggers) const
1043{
f6736d23 1044 Int_t nTracklets = 0;
5bb5d1f6 1045 nClusters = 0;
8565b10b 1046
241cca4d 1047 // If this is inel, see if we have a tracklet
1048 const AliMultiplicity* spdmult = esd.GetMultiplicity();
1049 if (!spdmult) {
1050 AliWarning("No SPD multiplicity");
1051 return false;
1052 }
1053
1054 // Check if we have one or more tracklets
1055 // in the range -1 < eta < 1 to set the INEL>0
1056 // trigger flag.
1057 //
1058 // Also count tracklets as a single cluster
1059 Int_t n = spdmult->GetNumberOfTracklets();
1060 for (Int_t j = 0; j < n; j++) {
f6736d23 1061 if(TMath::Abs(spdmult->GetEta(j)) < 1) nTracklets++;
8565b10b 1062 }
dd556bcd 1063 // If we at this point had non-zero nClusters, it's INEL>0
f6736d23 1064 if (nTracklets > 0) triggers |= AliAODForwardMult::kInelGt0;
1065 nClusters = nTracklets;
dd556bcd 1066
1067 // Loop over single clusters
241cca4d 1068 n = spdmult->GetNumberOfSingleClusters();
1069 for (Int_t j = 0; j < n; j++) {
1070 Double_t eta = -TMath::Log(TMath::Tan(spdmult->GetThetaSingle(j)/2.));
1071 if (TMath::Abs(eta) < 1) nClusters++;
1072 }
1073 if (nClusters > 0) triggers |= AliAODForwardMult::kNClusterGt0;
1074
1075 return triggers & AliAODForwardMult::kNClusterGt0;
1076}
1077
1078//____________________________________________________________________
1079Bool_t
1080AliFMDEventInspector::CheckNSD(const AliESDEvent& esd, UInt_t& triggers) const
1081{
8565b10b 1082 // Analyse some trigger stuff
1083 AliTriggerAnalysis ta;
241cca4d 1084 if (ta.IsOfflineTriggerFired(&esd, AliTriggerAnalysis::kV0AND)) {
e6463868 1085 triggers |= AliAODForwardMult::kV0AND;
1086 if (fUseV0AND)
31554871 1087 triggers |= AliAODForwardMult::kNSD;
1088 }
241cca4d 1089 if (ta.IsOfflineTriggerFired(&esd, AliTriggerAnalysis::kNSD1))
e6463868 1090 triggers |= AliAODForwardMult::kNSD;
241cca4d 1091 return triggers & AliAODForwardMult::kNSD;
1092}
1093//____________________________________________________________________
1094Bool_t
1095AliFMDEventInspector::CheckPileup(const AliESDEvent& esd,
1096 UInt_t& triggers) const
1097{
5bb5d1f6 1098 // Check for multiple vertices (pile-up) with at least 3
1099 // contributors and at least 0.8cm from the primary vertex
dd556bcd 1100 // if(fCollisionSystem != AliForwardUtil::kPP) return false;
1101
e5c41d3e 1102 UInt_t locTrig = 0;
1103 // Check for standard SPD pile-up
1104 if ((fPileupFlags & kSPD) &&
1105 esd.IsPileupFromSPD(fMinPileupContrib,fMinPileupDistance)) {
1106 fHPileup->Fill(0.5, 1);
1107 locTrig |= AliAODForwardMult::kPileupSPD;
1108 }
241cca4d 1109
dd556bcd 1110 // Check for multi-vertex pileup
e5c41d3e 1111 if ((fPileupFlags & kTracks) && CheckMultiVertex(esd)) {
1112 fHPileup->Fill(1.5, 1);
1113 locTrig |= AliAODForwardMult::kPileupTrack;
1114 }
dd556bcd 1115
1116 // Check for out-of-bunch pileup
e5c41d3e 1117 if ((fPileupFlags & kOutOfBunch) &&
1118 (esd.GetHeader()->GetIRInt2ClosestInteractionMap() != 0 ||
1119 esd.GetHeader()->GetIRInt1ClosestInteractionMap() != 0)) {
1120 fHPileup->Fill(2.5, 1);
1121 locTrig |= AliAODForwardMult::kPileupBC;
1122 }
1123
dd556bcd 1124 // Our result
f6736d23 1125 triggers |= locTrig;
1126 Bool_t pileup = locTrig != 0;
e5c41d3e 1127 if (pileup) triggers |= AliAODForwardMult::kPileUp;
241cca4d 1128 return pileup;
1129}
1130
dd556bcd 1131//____________________________________________________________________
1132Bool_t
c8b1a7db 1133AliFMDEventInspector::CheckMultiVertex(const AliESDEvent& esd,
1134 Bool_t checkOtherBC) const
dd556bcd 1135{
1136 // Adapted from AliAnalysisUtils
1137 //
1138 // Parameters
1139 const Double_t maxChi2nu = 5;
dd556bcd 1140
1141 // Number of vertices
1142 Int_t n = esd.GetNumberOfPileupVerticesTracks();
1143 if (n < 1)
1144 // No additional vertices from tracks -> no pileup
1145 return false;
1146
1147 // Primary vertex
1148 const AliESDVertex* primary = esd.GetPrimaryVertexTracks();
1149 if (primary->GetStatus() != 1)
1150 // No good primary vertex, but many candidates -> pileup
1151 return true;
1152
1153 // Bunch crossing number
1154 Int_t bcPrimary = primary->GetBC();
1155
1156 for (Int_t i = 0; i < n; i++) {
1157 const AliESDVertex* other = esd.GetPileupVertexTracks(i);
1158
1159 if (other->GetNContributors() < fMinPileupContrib)
1160 // Not enough contributors to this vertex
1161 continue;
1162
1163 if (other->GetChi2perNDF() > maxChi2nu)
1164 // Poorly determined vertex
1165 continue;
1166 if (checkOtherBC) {
1167 Int_t bcOther = other->GetBC();
1168 if (bcOther != AliVTrack::kTOFBCNA && TMath::Abs(bcOther-bcPrimary) > 2)
1169 // Pile-up from other BC
1170 return true;
1171 }
1172 // Calculate the distance
1173 Double_t d = -1;
1174 Double_t dx = primary->GetX() - other->GetX();
1175 Double_t dy = primary->GetY() - other->GetY();
1176 Double_t dz = primary->GetZ() - other->GetZ();
1177 Double_t covPrimary[6], covOther[6];
1178 primary->GetCovarianceMatrix(covPrimary);
1179 other->GetCovarianceMatrix(covOther);
1180 TMatrixDSym v(3);
1181 v(0,0) = covPrimary[0] + covOther[0]; // diagonal
1182 v(1,1) = covPrimary[2] + covOther[2]; // diagonal
1183 v(2,2) = covPrimary[5] + covOther[5]; // diagonal
1184 v(1,0) = v(0,1) = covPrimary[1]+covOther[1]; // Band
1185 v(0,2) = v(1,2) = v(2,0) = v(2,1) = 0; // Off-diagonal+band
1186 // Try to invert
1187 v.InvertFast();
1188 if (!v.IsValid())
1189 // Question if kStatus bit is every set after InvertFast?
1190 continue;
1191 d = (v(0,0) * dx * dx + v(1,1) * dy * dy + v(2,2) * dz * dz +
1192 2 * (v(0,1) * dx * dy + v(0,2) * dx * dz + v(1,2) * dy * dz));
1193
1194 if (d < 0 || TMath::Sqrt(d) < fMinPileupDistance)
1195 // Bad distance, or not fare enough from each other
1196 continue;
1197
1198 // Well separated vertices -> pileup
1199 return true;
1200 }
1201 return false;
1202}
1203
241cca4d 1204//____________________________________________________________________
1205Bool_t
1206AliFMDEventInspector::CheckEmpty(const TString& trigStr, UInt_t& triggers) const
1207{
f6736d23 1208 if (trigStr.Contains("CBEAMB-ABCE-NOPF-ALL")||
1209 trigStr.Contains("CBEAMB-B-NOPF-ALLNOTRD")) {
8565b10b 1210 triggers |= AliAODForwardMult::kEmpty;
241cca4d 1211 return true;
8565b10b 1212 }
241cca4d 1213 return false;
1214}
1215//____________________________________________________________________
1216Bool_t
1217AliFMDEventInspector::CheckWords(const AliESDEvent& esd, UInt_t& triggers) const
1218{
1219 TObject* word = 0;
1220 TIter nextColl(&fCollWords);
1221 while ((word = nextColl())) {
1222 DMSG(fDebug,10,"Checking if %s trigger %s is fired",
1223 word->GetTitle(), word->GetName());
1224 if (!esd.IsTriggerClassFired(word->GetName())) continue;
8565b10b 1225
241cca4d 1226 TString beamSide = word->GetTitle();
1227 DMSG(fDebug,10,"Found it - this is a %s trigger", beamSide.Data());
e85a76b7 1228
241cca4d 1229 if (!beamSide.EqualTo("B")) continue;
1230 triggers |= AliAODForwardMult::kB;
1231 break; // No more to do here
e85a76b7 1232 }
241cca4d 1233 TIter nextBg(&fBgWords);
1234 UInt_t all = (AliAODForwardMult::kA |
1235 AliAODForwardMult::kC |
1236 AliAODForwardMult::kE);
1237 while ((word = nextBg())) {
1238 DMSG(fDebug,10,"Checking if %s trigger %s is fired",
1239 word->GetTitle(), word->GetName());
1240 if (!esd.IsTriggerClassFired(word->GetName())) continue;
0be6c8cd 1241
241cca4d 1242 TString beamSide = word->GetTitle();
1243 DMSG(fDebug,10,"Found it - this is a %s trigger", beamSide.Data());
e6463868 1244
241cca4d 1245 if (beamSide.Contains("A")) triggers |= AliAODForwardMult::kA;
1246 if (beamSide.Contains("C")) triggers |= AliAODForwardMult::kC;
1247 if (beamSide.Contains("E")) triggers |= AliAODForwardMult::kE;
1248
1249 if ((triggers & all) == all) break; // No more to do
0be6c8cd 1250 }
241cca4d 1251 return true;
8565b10b 1252}
241cca4d 1253
1254
8565b10b 1255//____________________________________________________________________
1256Bool_t
5ca83fee 1257AliFMDEventInspector::ReadVertex(const AliESDEvent& esd, TVector3& ip)
8565b10b 1258{
7984e5f7 1259 //
1260 // Read the vertex information from the ESD event
1261 //
1262 // Parameters:
1263 // esd ESD event
1264 // vz On return, the vertex Z position
1265 //
1266 // Return:
1267 // @c true on success, @c false otherwise
1268 //
6ab100ec 1269 DGUARD(fDebug,2,"Read the vertex in AliFMDEventInspector");
5ca83fee 1270 ip.SetXYZ(1024, 1024, 0);
65abd48b 1271
8449e3e0 1272 EVtxStatus s = kNoVtx;
0ccdab7b 1273 if (AllowDisplaced() && fDisplacedVertex.IsSatellite()) {
bfab35d9 1274 s = kVtxOK;
1275 ip.SetZ(fDisplacedVertex.GetVertexZ());
1276 }
0ccdab7b 1277 else if (fVtxMethod == kPWGUD)
8449e3e0 1278 s = CheckPWGUDVertex(esd, ip);
0ccdab7b 1279 else if (fVtxMethod == kpA2012)
8449e3e0 1280 s = CheckpA2012Vertex(esd,ip);
0ccdab7b 1281 else if (fVtxMethod == kpA2013)
1282 s = CheckpA2013Vertex(esd,ip);
8449e3e0 1283 else
1284 s = CheckVertex(esd, ip);
1285
8449e3e0 1286 fHVtxStatus->Fill(s);
1287
1288 return s == kVtxOK;
241cca4d 1289}
1290
1291//____________________________________________________________________
8449e3e0 1292AliFMDEventInspector::EVtxStatus
241cca4d 1293AliFMDEventInspector::CheckPWGUDVertex(const AliESDEvent& esd,
5ca83fee 1294 TVector3& ip) const
241cca4d 1295{
1296 // This is the code used by the 1st physics people
1297 const AliESDVertex* vertex = esd.GetPrimaryVertex();
1298 if (!vertex || !vertex->GetStatus()) {
1299 DMSG(fDebug,2,"No primary vertex (%p) or bad status %d",
1300 vertex, (vertex ? vertex->GetStatus() : -1));
8449e3e0 1301 return kNoVtx;
241cca4d 1302 }
1303 const AliESDVertex* vertexSPD = esd.GetPrimaryVertexSPD();
1304 if (!vertexSPD || !vertexSPD->GetStatus()) {
1305 DMSG(fDebug,2,"No primary SPD vertex (%p) or bad status %d",
1306 vertexSPD, (vertexSPD ? vertexSPD->GetStatus() : -1));
8449e3e0 1307 return kNoSPDVtx;
241cca4d 1308 }
96110c91 1309
241cca4d 1310 // if vertex is from SPD vertexZ, require more stringent cuts
1311 if (vertex->IsFromVertexerZ()) {
1312 if (vertex->GetDispersion() > fMaxVzErr ||
1313 vertex->GetZRes() > 1.25 * fMaxVzErr) {
1314 DMSG(fDebug,2,"Dispersion %f > %f or resolution %f > %f",
1315 vertex->GetDispersion(), fMaxVzErr,
1316 vertex->GetZRes(), 1.25 * fMaxVzErr);
8449e3e0 1317 return kUncertain;
96110c91 1318 }
96110c91 1319 }
5ca83fee 1320 ip.SetZ(vertex->GetZ());
241cca4d 1321
1322 if(!vertex->IsFromVertexerZ()) {
5ca83fee 1323 ip.SetX(vertex->GetX());
1324 ip.SetY(vertex->GetY());
241cca4d 1325 }
8449e3e0 1326 return kVtxOK;
241cca4d 1327}
8449e3e0 1328//____________________________________________________________________
1329AliFMDEventInspector::EVtxStatus
1330AliFMDEventInspector::CheckpA2012Vertex(const AliESDEvent& esd,
1331 TVector3& ip) const
ffd35d33 1332{
0ccdab7b 1333 const Int_t nMinContrib = 0;
8449e3e0 1334 const AliESDVertex *vertex = esd.GetPrimaryVertexSPD();
1335 if (!vertex) return kNoSPDVtx;
0ccdab7b 1336 if (vertex->GetNContributors() <= nMinContrib) return kFewContrib;
8449e3e0 1337
1338 TString vtxTyp = vertex->GetTitle();
1339 if (vtxTyp.Contains("vertexer: Z")) return kNotVtxZ;
1340
1341 if (vertex->GetDispersion() >= 0.04 || vertex->GetZRes()>=0.25)
1342 return kUncertain;
1343
1344 ip.SetX(vertex->GetX());
1345 ip.SetY(vertex->GetY());
1346 ip.SetZ(vertex->GetZ());
1347
1348 return kVtxOK;
ffd35d33 1349}
0ccdab7b 1350//____________________________________________________________________
1351AliFMDEventInspector::EVtxStatus
1352AliFMDEventInspector::CheckpA2013Vertex(const AliESDEvent& esd,
1353 TVector3& ip) const
1354{
1355 // This code is adopted from
1356 //
1357 // AliAnalysisUtils::IsVertexSelected2013pA(AliVEvent *event)
1358 //
1359 const Int_t nMinContrib = 0;
1360 const AliESDVertex* primVtx = esd.GetPrimaryVertex();
1361 if (!primVtx) return kNoVtx;
1362 if (primVtx->GetNContributors() <= nMinContrib) return kFewContrib;
1363
e5c41d3e 1364 const AliESDVertex* spdVtx = esd.GetPrimaryVertexSPD();
0ccdab7b 1365 if (!spdVtx) return kNoSPDVtx;
1366 if (spdVtx->GetNContributors() <= nMinContrib) return kFewContrib;
1367
e5c41d3e 1368 // TString vtxTyp = spdVtx->GetTitle();
1369 // if (vtxTyp.Contains("vertexer:Z")) {
1370 if (spdVtx->IsFromVertexerZ() && spdVtx->GetZRes()>0.25) return kUncertain;
1371
0ccdab7b 1372 Bool_t correlateVtx = true;
1373 if (correlateVtx) {
1374 if (TMath::Abs(spdVtx->GetZ() - primVtx->GetZ()) > 0.5) return kUncertain;
1375 }
1376
1377 ip.SetX(primVtx->GetX());
1378 ip.SetY(primVtx->GetY());
1379 ip.SetZ(primVtx->GetZ());
1380
1381 return kVtxOK;
1382}
ffd35d33 1383
241cca4d 1384//____________________________________________________________________
8449e3e0 1385AliFMDEventInspector::EVtxStatus
241cca4d 1386AliFMDEventInspector::CheckVertex(const AliESDEvent& esd,
5ca83fee 1387 TVector3& ip) const
241cca4d 1388{
1389 // Use standard SPD vertex (perhaps preferable for Pb+Pb)
1390 // Get the vertex
1391 const AliESDVertex* vertex = esd.GetPrimaryVertexSPD();
1392 if (!vertex) {
1393 if (fDebug > 2) {
1394 AliWarning("No SPD vertex found in ESD"); }
8449e3e0 1395 return kNoSPDVtx;
241cca4d 1396 }
e83d0620 1397
8449e3e0 1398 // #if 0 // Check disabled - seem to kill a lot of PbPb events
241cca4d 1399 // Check that enough tracklets contributed
1400 if(vertex->GetNContributors() <= 0) {
1401 DMSG(fDebug,2,"Number of contributors to vertex is %d<=0",
1402 vertex->GetNContributors());
5ca83fee 1403 ip.SetZ(0);
8449e3e0 1404 return kFewContrib;
241cca4d 1405 }
8449e3e0 1406 // #endif
1407
241cca4d 1408 // Check that the uncertainty isn't too large
1409 if (vertex->GetZRes() > fMaxVzErr) {
1410 DMSG(fDebug,2,"Uncertaintity in Z of vertex is too large %f > %f",
1411 vertex->GetZRes(), fMaxVzErr);
8449e3e0 1412 return kUncertain;
241cca4d 1413 }
e83d0620 1414
241cca4d 1415 // Get the z coordiante
5ca83fee 1416 ip.SetZ(vertex->GetZ());
241cca4d 1417 const AliESDVertex* vertexXY = esd.GetPrimaryVertex();
96110c91 1418
5ca83fee 1419
241cca4d 1420 if(!vertexXY->IsFromVertexerZ()) {
5ca83fee 1421 ip.SetX(vertexXY->GetX());
1422 ip.SetY(vertexXY->GetY());
241cca4d 1423 }
8449e3e0 1424 return kVtxOK;
8565b10b 1425}
241cca4d 1426
0bd4b00f 1427//____________________________________________________________________
1428Bool_t
1429AliFMDEventInspector::ReadRunDetails(const AliESDEvent* esd)
1430{
7984e5f7 1431 //
1432 // Read the collision system, collision energy, and L3 field setting
1433 // from the ESD
1434 //
1435 // Parameters:
1436 // esd ESD to get information from
1437 //
1438 // Return:
1439 // true on success, false
1440 //
cc83fca2 1441 // AliInfo(Form("Parameters from 1st ESD event: cms=%s, sNN=%f, field=%f",
1442 // esd->GetBeamType(), 2*esd->GetBeamEnergy(),
1443 // esd->GetMagneticField()));
6ab100ec 1444 DGUARD(fDebug,2,"Read the run details in AliFMDEventInspector");
d4d486f8 1445 const char* sys = esd->GetBeamType();
1446 Float_t cms = 2 * esd->GetBeamEnergy();
1447 Float_t fld = esd->GetMagneticField();
1448 fCollisionSystem = AliForwardUtil::ParseCollisionSystem(sys);
1449 fEnergy = AliForwardUtil::ParseCenterOfMassEnergy(fCollisionSystem,
1450 cms);
1451 fField = AliForwardUtil::ParseMagneticField(fld);
8449e3e0 1452 fRunNumber = esd->GetRunNumber();
c8b1a7db 1453 StoreProduction();
8449e3e0 1454 StoreInformation();
d4d486f8 1455 if (fCollisionSystem == AliForwardUtil::kUnknown) {
1456 AliWarningF("Unknown collision system: %s - please check", sys);
1457 return false;
1458 }
1459 if (fEnergy <= 0) {
1460 AliWarningF("Unknown CMS energy: %f (%d) - please check", cms, fEnergy);
1461 return false;
1462 }
1463 if (TMath::Abs(fField) > 10) {
1464 AliWarningF("Unknown L3 field setting: %f (%d) - please check", fld,fField);
1465 return false;
1466 }
0bd4b00f 1467
d4d486f8 1468 return true;
0bd4b00f 1469}
1470
241cca4d 1471
1472//____________________________________________________________________
1473const Char_t*
1474AliFMDEventInspector::CodeString(UInt_t code)
1475{
1476 static TString s;
1477 s = "";
1478 if (code & kNoEvent) s.Append("NOEVENT ");
1479 if (code & kNoTriggers) s.Append("NOTRIGGERS ");
1480 if (code & kNoSPD) s.Append("NOSPD ");
1481 if (code & kNoFMD) s.Append("NOFMD ");
1482 if (code & kNoVertex) s.Append("NOVERTEX ");
1483 if (code & kBadVertex) s.Append("BADVERTEX ");
1484 return s.Data();
1485}
c8b1a7db 1486#define PF(N,V,...) \
1487 AliForwardUtil::PrintField(N,V, ## __VA_ARGS__)
1488#define PFB(N,FLAG) \
1489 do { \
1490 AliForwardUtil::PrintName(N); \
1491 std::cout << std::boolalpha << (FLAG) << std::noboolalpha << std::endl; \
1492 } while(false)
1493#define PFV(N,VALUE) \
1494 do { \
1495 AliForwardUtil::PrintName(N); \
1496 std::cout << (VALUE) << std::endl; } while(false)
1497
0bd4b00f 1498//____________________________________________________________________
1499void
1500AliFMDEventInspector::Print(Option_t*) const
1501{
7984e5f7 1502 //
1503 // Print information
1504 //
1505 // option Not used
1506 //
c8b1a7db 1507 AliForwardUtil::PrintTask(*this);
0bd4b00f 1508 TString sNN(AliForwardUtil::CenterOfMassEnergyString(fEnergy));
1509 sNN.Strip(TString::kBoth, '0');
1510 sNN.ReplaceAll("GeV", " GeV");
1511 TString field(AliForwardUtil::MagneticFieldString(fField));
1512 field.ReplaceAll("p", "+");
1513 field.ReplaceAll("m", "-");
1514 field.ReplaceAll("kG", " kG");
c8b1a7db 1515
1516 gROOT->IncreaseDirLevel();
0b7de667 1517 PFV("Production", "");
1518 gROOT->IncreaseDirLevel();
1519 PF("Period", "LHC%02d%c", fProdYear, fProdLetter);
1520 PFB("MC anchor", fProdMC);
1521 PFV("AliROOT Revision", fProdSVN);
1522 gROOT->DecreaseDirLevel();
c8b1a7db 1523 PFV("Vertex bins", fVtxAxis.GetNbins());
1524 PF("Vertex Range", "[%+6.1f,%+6.1f]", fVtxAxis.GetXmin(), fVtxAxis.GetXmax());
1525 PFV("Low flux cut", fLowFluxCut );
1526 PFV("Max(delta v_z)", fMaxVzErr );
e5c41d3e 1527 PF("Pile-up methods", "spd:%s,tracks:%s,out-of-bunch:%s",
1528 (fPileupFlags & kSPD ? "yes" : "no"),
1529 (fPileupFlags & kTracks ? "yes" : "no"),
1530 (fPileupFlags & kOutOfBunch ? "yes" : "no"));
c8b1a7db 1531 PFV("Min(nContrib_pileup)", fMinPileupContrib );
1532 PFV("Min(v-pileup)", fMinPileupDistance );
1533 PFV("System", AliForwardUtil::CollisionSystemString(fCollisionSystem));
1534 PFV("CMS energy per nucleon", sNN);
1535 PFV("Field", field);
0ccdab7b 1536 PFB("Satellite events", AllowDisplaced());
1537 // PFB("Use 2012 pA vertex", fUsepA2012Vertex );
1538 // PFB("Use PWG-UD vertex", fUseFirstPhysicsVertex);
1539 TString vtxMethod("normal");
1540 switch(fVtxMethod) {
1541 case kNormal: vtxMethod = "normal" ; break;
1542 case kpA2012: vtxMethod = "pA 2012"; break;
1543 case kpA2013: vtxMethod = "pA 2013"; break;
1544 case kPWGUD: vtxMethod = "PWG-UD"; break;
1545 case kDisplaced: vtxMethod = "Satellite"; break;
1546 }
1547 PFV("IP method", vtxMethod);
c8b1a7db 1548 PFB("Simulation input", fMC );
1549 PFV("Centrality method", fCentMethod);
1550 PFV("Centrality axis", (!fCentAxis ? "none" : ""));
1551 if (!fCentAxis) {return; }
d8244e9e 1552 Int_t nBin = fCentAxis->GetNbins();
d8244e9e 1553 for (Int_t i = 0; i < nBin; i++) {
0b7de667 1554 if (i != 0 && (i % 10) == 0) std::cout << '\n';
1555 if ((i % 10) == 0) std::cout << " ";
d8244e9e 1556 std::cout << std::setw(5) << fCentAxis->GetBinLowEdge(i+1) << '-';
1557 }
1558 std::cout << std::setw(5) << fCentAxis->GetBinUpEdge(nBin) << std::endl;
c8b1a7db 1559 gROOT->DecreaseDirLevel();
0bd4b00f 1560}
1561
1562
8565b10b 1563//
1564// EOF
1565//
1566