2 // This class inspects the event
5 // - AliESDFMD object possibly corrected for sharing
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
12 // Note, that these are added to the master output list
17 #include "AliFMDEventInspector.h"
18 #include "AliProdInfo.h"
20 #include "AliESDEvent.h"
21 #include "AliMultiplicity.h"
22 #include "AliAnalysisManager.h"
23 #include "AliMCEventHandler.h"
24 #include "AliInputEventHandler.h"
25 #include "AliTriggerAnalysis.h"
26 #include "AliPhysicsSelection.h"
27 #include "AliOADBPhysicsSelection.h"
28 #include "AliAODForwardMult.h"
29 #include "AliForwardUtil.h"
30 #include "AliCentrality.h"
33 #include <TDirectory.h>
35 #include <TParameter.h>
36 #include <TMatrixDSym.h>
40 #include "AliMCEvent.h"
41 #include "AliHeader.h"
42 #include "AliGenEventHeader.h"
43 #include "AliCollisionGeometry.h"
44 #include "AliVVZERO.h"
46 //====================================================================
48 AliPhysicsSelection* GetPhysicsSelection()
50 AliAnalysisManager* am = AliAnalysisManager::GetAnalysisManager();
52 // Get the input handler - should always be there
53 AliInputEventHandler* ih =
54 dynamic_cast<AliInputEventHandler*>(am->GetInputEventHandler());
56 Warning("GetPhysicsSelection", "No input handler");
59 // Get the physics selection - should always be there
60 AliPhysicsSelection* ps =
61 dynamic_cast<AliPhysicsSelection*>(ih->GetEventSelection());
63 Warning("GetPhysicsSelection", "No physics selection");
70 //====================================================================
71 const char* AliFMDEventInspector::fgkFolderName = "fmdEventInspector";
73 //____________________________________________________________________
74 AliFMDEventInspector::AliFMDEventInspector()
79 fHEventsAcceptedXY(0),
94 fCollisionSystem(kUnknown),
98 fUseFirstPhysicsVertex(false),
100 fMinPileupContrib(3),
101 fMinPileupDistance(0.8),
102 fUseDisplacedVertices(false),
109 fUsepA2012Vertex(false),
121 DGUARD(fDebug,1,"Default CTOR of AliFMDEventInspector");
124 //____________________________________________________________________
125 AliFMDEventInspector::AliFMDEventInspector(const char* name)
126 : TNamed(fgkFolderName, name),
130 fHEventsAcceptedXY(0),
145 fCollisionSystem(kUnknown),
149 fUseFirstPhysicsVertex(false),
151 fMinPileupContrib(3),
152 fMinPileupDistance(0.8),
153 fUseDisplacedVertices(false),
160 fUsepA2012Vertex(false),
173 // name Name of object
175 DGUARD(fDebug,1,"Named CTOR of AliFMDEventInspector: %s", name);
176 if (!GetPhysicsSelection()) {
177 AliFatal("No physics selection defined in manager\n"
178 "=======================================================\n"
179 " The use of AliFMDEventInspector _requires_ a valid\n"
180 " AliPhysicsSelection registered with the input handler.\n\n"
181 " Please check our train setup\n"
182 "=======================================================\n");
186 //____________________________________________________________________
187 AliFMDEventInspector::~AliFMDEventInspector()
192 DGUARD(fDebug,1,"DTOR of AliFMDEventInspector");
193 // if (fList) delete fList;
196 //____________________________________________________________________
198 AliFMDEventInspector::SetCentralityMethod(ECentMethod m)
201 case kV0Multiplicity: fCentMethod = "VOM"; break; // VZERO multiplicity
202 case kV0Amplitude: fCentMethod = "V0A"; break; // VZERO amplitude
203 case kV0Charge: fCentMethod = "V0C"; break; // VZERO charge
204 case kFMDRough: fCentMethod = "FMD"; break; // FMD scaled energy l
205 case kNTracks: fCentMethod = "TRK"; break; // Number of tracks
206 case kLTracks: fCentMethod = "TKL"; break; // Number of tracks
207 case kCL0: fCentMethod = "CL0"; break; //
208 case kCL1: fCentMethod = "CL1"; break; //
209 case kCND: fCentMethod = "CND"; break; //
210 case kNParticles: fCentMethod = "NPA"; break; // Neutral particles
211 case kNeutrons: fCentMethod = "ZNA"; break; // ZDC neutron amplitu
212 case kV0vsFMD: fCentMethod = "V0MvsFMD"; break; // VZERO versus FMD
213 case kV0vsNTracks: fCentMethod = "TKLvsVOM"; break; // Tracks versus VZERO
214 case kZEMvsZDC: fCentMethod = "ZEMvsZDC"; break; // ZDC
215 default: fCentMethod = "V0M"; break;
219 //____________________________________________________________________
221 AliFMDEventInspector::SetMinCentrality(Double_t minCent)
224 "*******************************************************\n"
225 "* Setting centrality cuts in this stage is deprecated *\n"
226 "*******************************************************");
229 //____________________________________________________________________
231 AliFMDEventInspector::SetMaxCentrality(Double_t maxCent)
234 "*******************************************************\n"
235 "* Setting centrality cuts in this stage is deprecated *\n"
236 "*******************************************************");
240 //____________________________________________________________________
242 AliFMDEventInspector::FetchHistograms(const TList* d,
246 TH1I*& hTriggers) const
249 // Fetch our histograms from the passed list
253 // hEventsTr On return, pointer to histogram, or null
254 // hEventsTrVtx On return, pointer to histogram, or null
255 // hTriggers On return, pointer to histogram, or null
258 // true on success, false otherwise
260 DGUARD(fDebug,3,"Fetch histograms in AliFMDEventInspector");
265 TList* dd = dynamic_cast<TList*>(d->FindObject(GetName()));
266 if (!dd) return kFALSE;
268 hEventsTr = dynamic_cast<TH1I*>(dd->FindObject("nEventsTr"));
269 hEventsTrVtx = dynamic_cast<TH1I*>(dd->FindObject("nEventsTrVtx"));
270 hEventsAcc = dynamic_cast<TH1I*>(dd->FindObject("nEventsAccepted"));
271 hTriggers = dynamic_cast<TH1I*>(dd->FindObject("triggers"));
276 !hTriggers) return kFALSE;
279 //____________________________________________________________________
281 AliFMDEventInspector::CacheConfiguredTriggerClasses(TList& cache,
282 const TList* classes,
283 AliOADBPhysicsSelection* o)
285 TIter nextClass(classes);
286 TObjString* trigClass = 0;
287 // Loop over all trigger classes. Trigger classes have the format
289 // class := positive_words SPACE(s) negative_words
297 while ((trigClass = static_cast<TObjString*>(nextClass()))) {
298 // Tokenize on space to get positive and negative parts
299 TString side = o->GetBeamSide(trigClass->String());
300 TObjArray* parts = trigClass->String().Tokenize(" ");
301 TObjString* part = 0;
302 TIter nextPart(parts);
303 while ((part = static_cast<TObjString*>(nextPart()))) {
304 // We only care about the positive ones
305 if (part->GetName()[0] != '+') continue;
306 part->String().Remove(0,1);
308 // Tokenize on a comma to get the words
309 TObjArray* words = part->String().Tokenize(",");
310 TObjString* word = 0;
311 TIter nextWord(words);
312 while ((word = static_cast<TObjString*>(nextWord()))) {
313 TNamed* store = new TNamed(word->String(), side);
315 DMSG(fDebug,3,"Caching %s trigger word %s",
316 store->GetTitle(), store->GetName());
324 //____________________________________________________________________
326 AliFMDEventInspector::SetupForData(const TAxis& vtxAxis)
329 // Initialize the object - this is called on the first seen event.
332 // vtxAxis Vertex axis in use
334 DGUARD(fDebug,1,"Initialize in AliFMDEventInspector");
336 // Get the physics selection - should always be there
337 AliPhysicsSelection* ps = GetPhysicsSelection();
339 AliWarning("No physics selection");
342 // Get the configured triggers
343 AliOADBPhysicsSelection* oadb =
344 const_cast<AliOADBPhysicsSelection*>(ps->GetOADBPhysicsSelection());
346 AliWarning("No OADB physics selection object");
349 // Get the configured trigger words from the physics selection
350 const TList* collTriggClasses = ps->GetCollisionTriggerClasses();
351 const TList* bgTriggClasses = ps->GetBGTriggerClasses();
352 if (!collTriggClasses) {
353 AliWarning("No configured collision trigger classes");
356 if (!bgTriggClasses) {
357 AliWarning("No configured background trigger classes");
360 CacheConfiguredTriggerClasses(fCollWords, collTriggClasses, oadb);
361 CacheConfiguredTriggerClasses(fBgWords, bgTriggClasses, oadb);
367 if ((fMinCent < 0 && fMaxCent < 0) || fMaxCent <= fMinCent) {
369 // -1.5 -0.5 0.5 1.5 ... 89.5 ... 100.5
370 // ----- 92 number --------- ---- 1 ---
372 // -0.5 0.5 1.5 ... 89.5 ... 100.5
373 // ----- 91 number ---- ---- 1 ---
375 for (Int_t i = 0; i < 91; i++) limits[i] = -.5 + i;
379 Int_t n = Int_t(fMaxCent-fMinCent+2);
381 for (Int_t i = 0; i < n; i++) {
382 limits[i] = fMinCent + i - .5;
386 fVtxAxis.Set(vtxAxis.GetNbins(), vtxAxis.GetXmin(), vtxAxis.GetXmax());
388 fCentAxis = new TAxis(limits.GetSize()-1, limits.GetArray());
389 fHEventsTr = new TH1I("nEventsTr", "Number of events w/trigger",
390 4*vtxAxis.GetNbins(),
392 2*vtxAxis.GetXmax());
393 fHEventsTr->SetXTitle("v_{z} [cm]");
394 fHEventsTr->SetYTitle("# of events");
395 fHEventsTr->SetFillColor(kRed+1);
396 fHEventsTr->SetFillStyle(3001);
397 fHEventsTr->SetDirectory(0);
398 // fHEventsTr->Sumw2();
399 fList->Add(fHEventsTr);
401 fHEventsTrVtx = static_cast<TH1I*>(fHEventsTr->Clone("nEventsTrVtx"));
402 fHEventsTrVtx->SetTitle("Number of events w/trigger and vertex");
403 fHEventsTrVtx->SetFillColor(kBlue+1);
404 fHEventsTrVtx->SetDirectory(0);
405 // fHEventsTrVtx->Sumw2();
406 fList->Add(fHEventsTrVtx);
408 fHEventsAccepted = new TH1I("nEventsAccepted",
409 "Number of events w/trigger and vertex in range",
410 2*vtxAxis.GetNbins(),
412 2*vtxAxis.GetXmax());
413 fHEventsAccepted->SetXTitle("v_{z} [cm]");
414 fHEventsAccepted->SetYTitle("# of events");
415 fHEventsAccepted->SetFillColor(kGreen+1);
416 fHEventsAccepted->SetFillStyle(3001);
417 fHEventsAccepted->SetDirectory(0);
418 // fHEventsAccepted->Sumw2();
419 fList->Add(fHEventsAccepted);
421 fHEventsAcceptedXY = new TH2D("nEventsAcceptedXY",
422 "XY vertex w/trigger and Z vertex in range",
423 1000,-1,1,1000,-1,1);
425 fHEventsAcceptedXY->SetXTitle("v_{x} [cm]");
426 fHEventsAcceptedXY->SetYTitle("v_{y} [cm]");
427 fHEventsAcceptedXY->SetDirectory(0);
428 // fHEventsAccepted->Sumw2();
429 fList->Add(fHEventsAcceptedXY);
432 fHTriggers = new TH1I("triggers", "Triggers", kOffline+1, 0, kOffline+1);
433 fHTriggers->SetFillColor(kRed+1);
434 fHTriggers->SetFillStyle(3001);
435 fHTriggers->SetStats(0);
436 fHTriggers->SetDirectory(0);
438 fHTriggerCorr = new TH2I("triggerCorr", "Trigger correlation",
439 kOffline+1, 0, kOffline+1,
440 kOffline+1, 0, kOffline+1);
441 fHTriggerCorr->SetStats(0);
442 fHTriggerCorr->SetDirectory(0);
443 fHTriggerCorr->SetXTitle("Requirement");
444 fHTriggerCorr->SetYTitle("Companion");
446 Int_t binNum[] = { kInel +1,
459 const char* binLbl[] = { "INEL",
472 for (Int_t i = 0; i < kOffline+1; i++) {
473 fHTriggers->GetXaxis()->SetBinLabel(binNum[i], binLbl[i]);
474 fHTriggerCorr->GetXaxis()->SetBinLabel(binNum[i], binLbl[i]);
475 fHTriggerCorr->GetYaxis()->SetBinLabel(binNum[i], binLbl[i]);
477 fList->Add(fHTriggers);
478 fList->Add(fHTriggerCorr);
481 fHType = new TH1I("type", Form("Event type (cut: SPD mult>%d)",
482 fLowFluxCut), 2, -.5, 1.5);
483 fHType->SetFillColor(kRed+1);
484 fHType->SetFillStyle(3001);
486 fHType->SetDirectory(0);
487 fHType->GetXaxis()->SetBinLabel(1,"Low-flux");
488 fHType->GetXaxis()->SetBinLabel(2,"High-flux");
492 // This histogram disabled as it causes problems in the merge
493 fHWords = new TH1I("words", "Trigger words seen", 1, 0, 0);
494 fHWords->SetFillColor(kBlue+1);
495 fHWords->SetFillStyle(3001);
496 fHWords->SetStats(0);
497 fHWords->SetDirectory(0);
498 fHWords->SetBit(TH1::kCanRebin);
502 fHCent = new TH1F("cent", "Centrality", limits.GetSize()-1,limits.GetArray());
503 fHCent->SetFillColor(kBlue+1);
504 fHCent->SetFillStyle(3001);
506 fHCent->SetDirectory(0);
507 fHCent->SetXTitle("Centrality [%]");
508 fHCent->SetYTitle("Events");
511 fHCentVsQual = new TH2F("centVsQuality", "Quality vs Centrality",
512 5, 0, 5, limits.GetSize()-1, limits.GetArray());
513 fHCentVsQual->SetXTitle("Quality");
514 fHCentVsQual->SetYTitle("Centrality [%]");
515 fHCentVsQual->SetZTitle("Events");
516 fHCentVsQual->GetXaxis()->SetBinLabel(1, "OK");
517 fHCentVsQual->GetXaxis()->SetBinLabel(2, "Outside v_{z} cut");
518 fHCentVsQual->GetXaxis()->SetBinLabel(3, "V0 vs SPD outlier");
519 fHCentVsQual->GetXaxis()->SetBinLabel(4, "V0 vs TPC outlier");
520 fHCentVsQual->GetXaxis()->SetBinLabel(5, "V0 vs ZDC outlier");
521 fHCentVsQual->SetDirectory(0);
522 fList->Add(fHCentVsQual);
524 fHStatus = new TH1I("status", "Status", 8, 1, 9);
525 fHStatus->SetFillColor(kBlue+1);
526 fHStatus->SetFillStyle(3001);
527 fHStatus->SetStats(0);
528 fHStatus->SetDirectory(0);
529 TAxis* xAxis = fHStatus->GetXaxis();
530 xAxis->SetBinLabel(1, "OK");
531 xAxis->SetBinLabel(2, "No event");
532 xAxis->SetBinLabel(3, "No triggers");
533 xAxis->SetBinLabel(4, "No SPD");
534 xAxis->SetBinLabel(5, "No FMD");
535 xAxis->SetBinLabel(6, "No vertex");
536 xAxis->SetBinLabel(7, "Bad vertex");
537 xAxis->SetBinLabel(8, "No centrality");
538 fList->Add(fHStatus);
540 fHVtxStatus = new TH1I("vtxStatus","Vertex Status",
541 kNotVtxZ,kVtxOK,kNotVtxZ+1);
542 fHVtxStatus->SetFillColor(kGreen+1);
543 fHVtxStatus->SetFillStyle(3001);
544 fHVtxStatus->SetStats(0);
545 fHVtxStatus->SetDirectory(0);
546 xAxis = fHVtxStatus->GetXaxis();
547 xAxis->SetBinLabel(kVtxOK, "OK");
548 xAxis->SetBinLabel(kNoVtx, "None/bad status");
549 xAxis->SetBinLabel(kNoSPDVtx, "No SPD/bad status");
550 xAxis->SetBinLabel(kFewContrib, "N_{contrib} <= 0");
551 xAxis->SetBinLabel(kUncertain, Form("#delta z > %4.2f", fMaxVzErr));
552 xAxis->SetBinLabel(kNotVtxZ, "Not Z vertexer");
553 fList->Add(fHVtxStatus);
555 fHTrgStatus = new TH1I("trgStatus", "Trigger Status",
556 kOther, kNoTrgWords, kOther+1);
557 fHTrgStatus->SetFillColor(kMagenta+1);
558 fHTrgStatus->SetFillStyle(3001);
559 fHTrgStatus->SetStats(0);
560 fHTrgStatus->SetDirectory(0);
561 xAxis = fHTrgStatus->GetXaxis();
562 xAxis->SetBinLabel(kNoTrgWords, "No words");
563 xAxis->SetBinLabel(kPP2760Fast, "FAST in pp@#sqrt{s}=2.76TeV");
564 xAxis->SetBinLabel(kMUON, "Muon trigger");
565 xAxis->SetBinLabel(kTriggered, "Triggered");
566 xAxis->SetBinLabel(kMinBias, "CINT1 (V0A||V0C||FASTOR)");
567 xAxis->SetBinLabel(kMinBiasNoSPD, "CINT5 (V0A||V0C)");
568 xAxis->SetBinLabel(kV0AndTrg, "CINT7 (V0A&&V0C)");
569 xAxis->SetBinLabel(kHighMult, "N>>0");
570 xAxis->SetBinLabel(kCentral, "Central");
571 xAxis->SetBinLabel(kSemiCentral, "Semi-central");
572 xAxis->SetBinLabel(kDiffractive, "Diffractive");
573 xAxis->SetBinLabel(kUser, "User");
574 xAxis->SetBinLabel(kOther, "Other");
575 fList->Add(fHTrgStatus);
577 if (fUseDisplacedVertices) fDisplacedVertex.SetupForData(fList, "", false);
580 //____________________________________________________________________
582 AliFMDEventInspector::StoreInformation()
584 // Write TNamed objects to output list containing information about
585 // the running conditions
586 DGUARD(fDebug,2,"Store information from AliFMDEventInspector");
590 fList->Add(AliForwardUtil::MakeParameter("sys", fCollisionSystem));
591 fList->Add(AliForwardUtil::MakeParameter("sNN", fEnergy));
592 fList->Add(AliForwardUtil::MakeParameter("field", fField));
593 fList->Add(AliForwardUtil::MakeParameter("runNo", fRunNumber));
594 fList->Add(AliForwardUtil::MakeParameter("lowFlux", fLowFluxCut));
595 fList->Add(AliForwardUtil::MakeParameter("fpVtx",fUseFirstPhysicsVertex));
596 fList->Add(AliForwardUtil::MakeParameter("v0and",fUseV0AND));
597 fList->Add(AliForwardUtil::MakeParameter("nPileUp", fMinPileupContrib));
598 fList->Add(AliForwardUtil::MakeParameter("dPileup", fMinPileupDistance));
599 fList->Add(AliForwardUtil::MakeParameter("satellite", fUseDisplacedVertices));
600 fList->Add(AliForwardUtil::MakeParameter("alirootRev",
601 AliForwardUtil::AliROOTRevision()));
602 fList->Add(AliForwardUtil::MakeParameter("alirootBranch",
603 AliForwardUtil::AliROOTBranch()));
604 fList->Add(AliForwardUtil::MakeParameter("mc", fMC));
608 //____________________________________________________________________
610 AliFMDEventInspector::StoreProduction()
614 AliAnalysisManager *mgr=AliAnalysisManager::GetAnalysisManager();
615 AliVEventHandler *inputHandler=mgr->GetInputEventHandler();
617 AliWarning("Got no input handler");
620 TList *uiList = inputHandler->GetUserInfo();
622 AliWarning("Got no user list from input tree");
626 AliProdInfo p(uiList);
628 if (p.GetAlirootSvnVersion() <= 0) return;
630 // Make our output list
631 TList* out = new TList;
633 out->SetName("production");
634 // out->SetTitle("ESD production details");
637 TString period = p.GetLHCPeriod();
638 // TString aliROOTVersion = p.GetAlirootVersion();
639 fProdSVN = p.GetAlirootSvnVersion();
640 // TString rootVersion = p.GetRootVersion();
641 Int_t rootSVN = p.GetRootSvnVersion();
642 fProdPass = p.GetRecoPass();
645 TObjArray* pp = TPRegexp("LHC([0-9]+)([a-z]+)").MatchS(period);
646 fProdYear = static_cast<TObjString*>(pp->At(1))->String().Atoi();
647 fProdLetter = static_cast<TObjString*>(pp->At(2))->String()[0];
650 out->Add(AliForwardUtil::MakeParameter("year", fProdYear));
651 out->Add(AliForwardUtil::MakeParameter("letter", Int_t(fProdLetter)));
652 out->Add(AliForwardUtil::MakeParameter("alirootSVN", fProdSVN));
653 out->Add(AliForwardUtil::MakeParameter("rootSVN", rootSVN));
654 out->Add(AliForwardUtil::MakeParameter("pass", fProdPass));
655 out->Add(AliForwardUtil::MakeParameter("mc", fProdMC));
661 //____________________________________________________________________
663 AliFMDEventInspector::CreateOutputObjects(TList* dir)
666 // Define the output histograms. These are put in a sub list of the
667 // passed list. The histograms are merged before the parent task calls
668 // AliAnalysisTaskSE::Terminate
670 // dir Directory to add to
672 DGUARD(fDebug,1,"Define output from AliFMDEventInspector");
674 fList->SetName(GetName());
679 //____________________________________________________________________
681 AliFMDEventInspector::Process(const AliESDEvent* event,
694 // triggers On return, the triggers fired
695 // lowFlux On return, true if the event is considered a low-flux
696 // event (according to the setting of fLowFluxCut)
697 // ivz On return, the found vertex bin (1-based). A zero
698 // means outside of the defined vertex range
699 // vz On return, the z position of the interaction
700 // cent On return, the centrality - if not available < 0
703 // 0 (or kOk) on success, otherwise a bit mask of error codes
705 DGUARD(fDebug,1,"Process event in AliFMDEventInspector");
706 // --- Check that we have an event ---------------------------------
708 AliWarning("No ESD event found for input event");
713 // --- Process satellite event information is requested ------------
714 if (fUseDisplacedVertices) {
715 if (!fDisplacedVertex.Process(event))
716 AliWarning("Failed to process satellite event");
719 // --- Read trigger information from the ESD and store in AOD object
720 if (!ReadTriggers(*event, triggers, nClusters)) {
722 AliWarning("Failed to read triggers from ESD"); }
727 // --- Check if this is a high-flux event --------------------------
728 const AliMultiplicity* testmult = event->GetMultiplicity();
731 AliWarning("No central multiplicity object found"); }
734 lowFlux = testmult->GetNumberOfTracklets() < fLowFluxCut;
736 fHType->Fill(lowFlux ? 0 : 1);
738 // --- Get the interaction point -----------------------------------
739 Bool_t vzOk = ReadVertex(*event, ip);
740 fHEventsTr->Fill(ip.Z());
743 AliWarning("Failed to read vertex from ESD"); }
748 // --- Read centrality information
751 if (!ReadCentrality(*event, cent, qual)) {
753 AliWarning("Failed to get centrality");
755 // --- check centrality cut
757 if(fMinCent > -0.0001 && cent < fMinCent) return kNoEvent;
758 if(fMaxCent > -0.0001 && cent > fMaxCent) return kNoEvent;
759 if (cent >= 0) fHCent->Fill(cent);
760 if (qual == 0) fHCentVsQual->Fill(0., cent);
763 for (UShort_t i = 0; i < 4; i++)
764 if (qual & (1 << i)) fHCentVsQual->Fill(Double_t(i+1), cent);
768 fHEventsTrVtx->Fill(ip.Z());
770 // --- Get the vertex bin ------------------------------------------
771 ivz = fVtxAxis.FindBin(ip.Z());
772 if (ivz <= 0 || ivz > fVtxAxis.GetNbins()) {
774 AliWarning(Form("Vertex @ %f outside of range [%f,%f]",
775 ip.Z(), fVtxAxis.GetXmin(), fVtxAxis.GetXmax()));
781 fHEventsAccepted->Fill(ip.Z());
782 fHEventsAcceptedXY->Fill(ip.X(),ip.Y());
784 // --- Check the FMD ESD data --------------------------------------
785 if (!event->GetFMDData()) {
787 AliWarning("No FMD data found in ESD"); }
796 //____________________________________________________________________
798 AliFMDEventInspector::ReadCentrality(const AliESDEvent& esd,
800 UShort_t& qual) const
803 // Read centrality from event
807 // cent On return, the centrality or negative if not found
810 // False on error, true otherwise
812 DGUARD(fDebug,2,"Read the centrality in AliFMDEventInspector");
816 AliCentrality* centObj = const_cast<AliESDEvent&>(esd).GetCentrality();
818 cent = centObj->GetCentralityPercentile(fCentMethod);
819 qual = centObj->GetQuality();
822 // We overwrite with satellite events, so we can be sure to get the
823 // centrality determination from the satellite vertex selection
824 if (fUseDisplacedVertices && fDisplacedVertex.IsSatellite()) {
825 cent = fDisplacedVertex.GetCentralityPercentile();
832 //____________________________________________________________________
834 AliFMDEventInspector::CheckpAExtraV0(const AliESDEvent& esd) const
836 if (fCollisionSystem != AliForwardUtil::kPPb) return true;
838 AliVVZERO* esdV0 = esd.GetVZEROData();
839 if ((esdV0->GetV0ADecision()!=1) || (esdV0->GetV0CDecision()!=1))
844 //____________________________________________________________________
846 AliFMDEventInspector::ReadTriggers(const AliESDEvent& esd, UInt_t& triggers,
850 // Read the trigger information from the ESD event
854 // triggers On return, contains the trigger bits
857 // @c true on success, @c false otherwise
859 DGUARD(fDebug,2,"Read the triggers in AliFMDEventInspector");
862 // Get the analysis manager - should always be there
863 AliAnalysisManager* am = AliAnalysisManager::GetAnalysisManager();
864 DMSG(fDebug,10,"Got analysis manager %p", am);
866 AliWarning("No analysis manager defined!");
870 // Get the input handler - should always be there
871 AliInputEventHandler* ih =
872 static_cast<AliInputEventHandler*>(am->GetInputEventHandler());
873 DMSG(fDebug,10,"Got input handler %p", ih);
875 AliWarning("No input handler");
879 // Check if this is a collision candidate (MB)
881 // Historic remark: Note, that we should use the value cached in the
882 // input handler rather than calling IsCollisionCandiate directly
883 // on the AliPhysicsSelection obejct. If we called the latter
884 // then the AliPhysicsSelection object would overcount by a factor
886 UInt_t trgMask = ih->IsEventSelected();
887 Bool_t offline = trgMask;
888 Bool_t fastonly = (trgMask & AliVEvent::kFastOnly);
889 TString trigStr = esd.GetFiredTriggerClasses();
891 if (trigStr.IsNull()) fHTrgStatus->Fill(kNoTrgWords);
892 if (fHWords) fHWords->Fill(trigStr.Data(), 1);
894 if(fUseDisplacedVertices) {
895 DMSG(fDebug,3,"Using displaced vertex stuff");
896 // if (TMath::Abs(fDisplacedVertex.GetVertexZ()) >= 999) offline = false;
897 if (fDisplacedVertex.IsSatellite())
898 triggers |= AliAODForwardMult::kSatellite;
901 if (CheckFastPartition(fastonly)) {
902 fHTrgStatus->Fill(kPP2760Fast);
906 if (offline && CheckCosmics(trigStr)) {
907 fHTrgStatus->Fill(kMUON);
910 if (offline) fHTrgStatus->Fill(kTriggered);
912 if (trgMask & AliVEvent::kMB) f += fHTrgStatus->Fill(kMinBias);
913 if (trgMask & AliVEvent::kCINT5) f += fHTrgStatus->Fill(kMinBiasNoSPD);
914 if (trgMask & AliVEvent::kINT7) f += fHTrgStatus->Fill(kV0AndTrg);
915 if (trgMask & AliVEvent::kHighMult) f += fHTrgStatus->Fill(kHighMult);
916 if (trgMask & AliVEvent::kCentral) f += fHTrgStatus->Fill(kCentral);
917 if (trgMask & AliVEvent::kSemiCentral) f += fHTrgStatus->Fill(kSemiCentral);
918 if (trgMask & AliVEvent::kDG5) f += fHTrgStatus->Fill(kDiffractive);
919 if (trgMask & AliVEvent::kUserDefined) f += fHTrgStatus->Fill(kUser);
920 if (f <= 0) fHTrgStatus->Fill(kOther);
922 // if (!CheckpAExtraV0(esd)) offline = false;
924 DMSG(fDebug,2,"Event is %striggered by off-line", offline ? "" : "NOT ");
926 if (offline) triggers |= AliAODForwardMult::kOffline;
927 // Only flag as in-elastic if a min-bias trigger is here
928 if (trgMask & AliVEvent::kMB) {
929 triggers |= AliAODForwardMult::kInel;
930 CheckINELGT0(esd, nClusters, triggers);
933 CheckNSD(esd,triggers);
934 CheckPileup(esd, triggers);
935 CheckEmpty(trigStr, triggers);
936 // if (CheckPileup(esd, triggers)) fHTriggers->Fill(kPileUp+.5);
937 // if (CheckEmpty(trigStr, triggers)) fHTriggers->Fill(kEmpty+.5);
939 CheckWords(esd, triggers);
941 #define TEST_TRIG_BIN(RET,BIN,TRIGGERS) \
942 do { switch (BIN) { \
943 case kInel: RET = triggers & AliAODForwardMult::kInel; break; \
944 case kInelGt0: RET = triggers & AliAODForwardMult::kInelGt0; break; \
945 case kNSD: RET = triggers & AliAODForwardMult::kNSD; break; \
946 case kV0AND: RET = triggers & AliAODForwardMult::kV0AND; break; \
947 case kEmpty: RET = triggers & AliAODForwardMult::kEmpty; break; \
948 case kA: RET = triggers & AliAODForwardMult::kA; break; \
949 case kB: RET = triggers & AliAODForwardMult::kB; break; \
950 case kC: RET = triggers & AliAODForwardMult::kC; break; \
951 case kE: RET = triggers & AliAODForwardMult::kE; break; \
952 case kPileUp: RET = triggers & AliAODForwardMult::kPileUp; break; \
953 case kMCNSD: RET = triggers & AliAODForwardMult::kMCNSD; break; \
954 case kSatellite:RET = triggers & AliAODForwardMult::kSatellite; break; \
955 case kOffline: RET = triggers & AliAODForwardMult::kOffline; break; \
956 default: RET = false; } } while(false)
959 AliWarning("Histogram of triggers not defined - has init been called");
963 for (Int_t i = 0; i < kOffline+1; i++) {
965 TEST_TRIG_BIN(hasX, i, triggers);
967 fHTriggers->Fill(i+.5);
968 for (Int_t j = 0; j < kOffline+1; j++) {
970 TEST_TRIG_BIN(hasY, j, triggers);
973 fHTriggerCorr->Fill(i+.5, j+.5);
979 //____________________________________________________________________
981 AliFMDEventInspector::CheckFastPartition(bool fastonly) const
983 // For the 2.76 TeV p+p run, the FMD ran in the slow partition
984 // so it received no triggers from the fast partition. Therefore
985 // the fast triggers are removed here but not for MC where all
986 // triggers are fast.
987 if (TMath::Abs(fEnergy - 2750.) > 20) return false;
988 if (fCollisionSystem != AliForwardUtil::kPP) return false;
989 if (fMC) return false; // All MC events for pp @ 2.76TeV are `fast'
991 DMSG(fDebug,1,"Fast trigger in pp @ sqrt(s)=2.76TeV removed");
996 //____________________________________________________________________
998 AliFMDEventInspector::CheckCosmics(const TString& trigStr) const
1000 // MUON triggers are not strictly minimum bias (MB) so they are
1002 if(trigStr.Contains("CMUS1")) {
1003 DMSG(fDebug,1,"Cosmic trigger ins't min-bias, removed");
1009 //____________________________________________________________________
1011 AliFMDEventInspector::CheckINELGT0(const AliESDEvent& esd,
1012 UShort_t& nClusters,
1013 UInt_t& triggers) const
1017 // If this is inel, see if we have a tracklet
1018 const AliMultiplicity* spdmult = esd.GetMultiplicity();
1020 AliWarning("No SPD multiplicity");
1024 // Check if we have one or more tracklets
1025 // in the range -1 < eta < 1 to set the INEL>0
1028 // Also count tracklets as a single cluster
1029 Int_t n = spdmult->GetNumberOfTracklets();
1030 for (Int_t j = 0; j < n; j++) {
1031 if(TMath::Abs(spdmult->GetEta(j)) < 1) nClusters++;
1033 // If we at this point had non-zero nClusters, it's INEL>0
1034 if (nClusters > 0) triggers |= AliAODForwardMult::kInelGt0;
1036 // Loop over single clusters
1037 n = spdmult->GetNumberOfSingleClusters();
1038 for (Int_t j = 0; j < n; j++) {
1039 Double_t eta = -TMath::Log(TMath::Tan(spdmult->GetThetaSingle(j)/2.));
1040 if (TMath::Abs(eta) < 1) nClusters++;
1042 if (nClusters > 0) triggers |= AliAODForwardMult::kNClusterGt0;
1044 return triggers & AliAODForwardMult::kNClusterGt0;
1047 //____________________________________________________________________
1049 AliFMDEventInspector::CheckNSD(const AliESDEvent& esd, UInt_t& triggers) const
1051 // Analyse some trigger stuff
1052 AliTriggerAnalysis ta;
1053 if (ta.IsOfflineTriggerFired(&esd, AliTriggerAnalysis::kV0AND)) {
1054 triggers |= AliAODForwardMult::kV0AND;
1056 triggers |= AliAODForwardMult::kNSD;
1058 if (ta.IsOfflineTriggerFired(&esd, AliTriggerAnalysis::kNSD1))
1059 triggers |= AliAODForwardMult::kNSD;
1060 return triggers & AliAODForwardMult::kNSD;
1062 //____________________________________________________________________
1064 AliFMDEventInspector::CheckPileup(const AliESDEvent& esd,
1065 UInt_t& triggers) const
1067 // Check for multiple vertices (pile-up) with at least 3
1068 // contributors and at least 0.8cm from the primary vertex
1069 // if(fCollisionSystem != AliForwardUtil::kPP) return false;
1071 // Check for standard SPD pile-up
1072 Bool_t spdPileup = esd.IsPileupFromSPD(fMinPileupContrib,fMinPileupDistance);
1074 // Check for multi-vertex pileup
1075 Bool_t mvPileup = false; // CheckMultiVertex(esd);
1077 // Check for out-of-bunch pileup
1078 Bool_t outPileup = (esd.GetHeader()->GetIRInt2ClosestInteractionMap() != 0 ||
1079 esd.GetHeader()->GetIRInt1ClosestInteractionMap() != 0);
1082 Bool_t pileup = spdPileup || mvPileup || outPileup;
1083 if (pileup) triggers |= AliAODForwardMult::kPileUp;
1087 //____________________________________________________________________
1089 AliFMDEventInspector::CheckMultiVertex(const AliESDEvent& esd,
1090 Bool_t checkOtherBC) const
1092 // Adapted from AliAnalysisUtils
1095 const Double_t maxChi2nu = 5;
1097 // Number of vertices
1098 Int_t n = esd.GetNumberOfPileupVerticesTracks();
1100 // No additional vertices from tracks -> no pileup
1104 const AliESDVertex* primary = esd.GetPrimaryVertexTracks();
1105 if (primary->GetStatus() != 1)
1106 // No good primary vertex, but many candidates -> pileup
1109 // Bunch crossing number
1110 Int_t bcPrimary = primary->GetBC();
1112 for (Int_t i = 0; i < n; i++) {
1113 const AliESDVertex* other = esd.GetPileupVertexTracks(i);
1115 if (other->GetNContributors() < fMinPileupContrib)
1116 // Not enough contributors to this vertex
1119 if (other->GetChi2perNDF() > maxChi2nu)
1120 // Poorly determined vertex
1123 Int_t bcOther = other->GetBC();
1124 if (bcOther != AliVTrack::kTOFBCNA && TMath::Abs(bcOther-bcPrimary) > 2)
1125 // Pile-up from other BC
1128 // Calculate the distance
1130 Double_t dx = primary->GetX() - other->GetX();
1131 Double_t dy = primary->GetY() - other->GetY();
1132 Double_t dz = primary->GetZ() - other->GetZ();
1133 Double_t covPrimary[6], covOther[6];
1134 primary->GetCovarianceMatrix(covPrimary);
1135 other->GetCovarianceMatrix(covOther);
1137 v(0,0) = covPrimary[0] + covOther[0]; // diagonal
1138 v(1,1) = covPrimary[2] + covOther[2]; // diagonal
1139 v(2,2) = covPrimary[5] + covOther[5]; // diagonal
1140 v(1,0) = v(0,1) = covPrimary[1]+covOther[1]; // Band
1141 v(0,2) = v(1,2) = v(2,0) = v(2,1) = 0; // Off-diagonal+band
1145 // Question if kStatus bit is every set after InvertFast?
1147 d = (v(0,0) * dx * dx + v(1,1) * dy * dy + v(2,2) * dz * dz +
1148 2 * (v(0,1) * dx * dy + v(0,2) * dx * dz + v(1,2) * dy * dz));
1150 if (d < 0 || TMath::Sqrt(d) < fMinPileupDistance)
1151 // Bad distance, or not fare enough from each other
1154 // Well separated vertices -> pileup
1160 //____________________________________________________________________
1162 AliFMDEventInspector::CheckEmpty(const TString& trigStr, UInt_t& triggers) const
1164 if (trigStr.Contains("CBEAMB-ABCE-NOPF-ALL")) {
1165 triggers |= AliAODForwardMult::kEmpty;
1170 //____________________________________________________________________
1172 AliFMDEventInspector::CheckWords(const AliESDEvent& esd, UInt_t& triggers) const
1175 TIter nextColl(&fCollWords);
1176 while ((word = nextColl())) {
1177 DMSG(fDebug,10,"Checking if %s trigger %s is fired",
1178 word->GetTitle(), word->GetName());
1179 if (!esd.IsTriggerClassFired(word->GetName())) continue;
1181 TString beamSide = word->GetTitle();
1182 DMSG(fDebug,10,"Found it - this is a %s trigger", beamSide.Data());
1184 if (!beamSide.EqualTo("B")) continue;
1185 triggers |= AliAODForwardMult::kB;
1186 break; // No more to do here
1188 TIter nextBg(&fBgWords);
1189 UInt_t all = (AliAODForwardMult::kA |
1190 AliAODForwardMult::kC |
1191 AliAODForwardMult::kE);
1192 while ((word = nextBg())) {
1193 DMSG(fDebug,10,"Checking if %s trigger %s is fired",
1194 word->GetTitle(), word->GetName());
1195 if (!esd.IsTriggerClassFired(word->GetName())) continue;
1197 TString beamSide = word->GetTitle();
1198 DMSG(fDebug,10,"Found it - this is a %s trigger", beamSide.Data());
1200 if (beamSide.Contains("A")) triggers |= AliAODForwardMult::kA;
1201 if (beamSide.Contains("C")) triggers |= AliAODForwardMult::kC;
1202 if (beamSide.Contains("E")) triggers |= AliAODForwardMult::kE;
1204 if ((triggers & all) == all) break; // No more to do
1210 //____________________________________________________________________
1212 AliFMDEventInspector::ReadVertex(const AliESDEvent& esd, TVector3& ip)
1215 // Read the vertex information from the ESD event
1219 // vz On return, the vertex Z position
1222 // @c true on success, @c false otherwise
1224 DGUARD(fDebug,2,"Read the vertex in AliFMDEventInspector");
1225 ip.SetXYZ(1024, 1024, 0);
1227 EVtxStatus s = kNoVtx;
1228 if (fUseDisplacedVertices && fDisplacedVertex.IsSatellite()) {
1230 ip.SetZ(fDisplacedVertex.GetVertexZ());
1232 else if (fUseFirstPhysicsVertex)
1233 s = CheckPWGUDVertex(esd, ip);
1234 else if (fUsepA2012Vertex)
1235 s = CheckpA2012Vertex(esd,ip);
1237 s = CheckVertex(esd, ip);
1239 fHVtxStatus->Fill(s);
1244 //____________________________________________________________________
1245 AliFMDEventInspector::EVtxStatus
1246 AliFMDEventInspector::CheckPWGUDVertex(const AliESDEvent& esd,
1249 // This is the code used by the 1st physics people
1250 const AliESDVertex* vertex = esd.GetPrimaryVertex();
1251 if (!vertex || !vertex->GetStatus()) {
1252 DMSG(fDebug,2,"No primary vertex (%p) or bad status %d",
1253 vertex, (vertex ? vertex->GetStatus() : -1));
1256 const AliESDVertex* vertexSPD = esd.GetPrimaryVertexSPD();
1257 if (!vertexSPD || !vertexSPD->GetStatus()) {
1258 DMSG(fDebug,2,"No primary SPD vertex (%p) or bad status %d",
1259 vertexSPD, (vertexSPD ? vertexSPD->GetStatus() : -1));
1263 // if vertex is from SPD vertexZ, require more stringent cuts
1264 if (vertex->IsFromVertexerZ()) {
1265 if (vertex->GetDispersion() > fMaxVzErr ||
1266 vertex->GetZRes() > 1.25 * fMaxVzErr) {
1267 DMSG(fDebug,2,"Dispersion %f > %f or resolution %f > %f",
1268 vertex->GetDispersion(), fMaxVzErr,
1269 vertex->GetZRes(), 1.25 * fMaxVzErr);
1273 ip.SetZ(vertex->GetZ());
1275 if(!vertex->IsFromVertexerZ()) {
1276 ip.SetX(vertex->GetX());
1277 ip.SetY(vertex->GetY());
1281 //____________________________________________________________________
1282 AliFMDEventInspector::EVtxStatus
1283 AliFMDEventInspector::CheckpA2012Vertex(const AliESDEvent& esd,
1286 const AliESDVertex *vertex = esd.GetPrimaryVertexSPD();
1287 if (!vertex) return kNoSPDVtx;
1288 if (vertex->GetNContributors() <= 0) return kFewContrib;
1290 TString vtxTyp = vertex->GetTitle();
1291 if (vtxTyp.Contains("vertexer: Z")) return kNotVtxZ;
1293 if (vertex->GetDispersion() >= 0.04 || vertex->GetZRes()>=0.25)
1296 ip.SetX(vertex->GetX());
1297 ip.SetY(vertex->GetY());
1298 ip.SetZ(vertex->GetZ());
1303 //____________________________________________________________________
1304 AliFMDEventInspector::EVtxStatus
1305 AliFMDEventInspector::CheckVertex(const AliESDEvent& esd,
1308 // Use standard SPD vertex (perhaps preferable for Pb+Pb)
1310 const AliESDVertex* vertex = esd.GetPrimaryVertexSPD();
1313 AliWarning("No SPD vertex found in ESD"); }
1317 // #if 0 // Check disabled - seem to kill a lot of PbPb events
1318 // Check that enough tracklets contributed
1319 if(vertex->GetNContributors() <= 0) {
1320 DMSG(fDebug,2,"Number of contributors to vertex is %d<=0",
1321 vertex->GetNContributors());
1327 // Check that the uncertainty isn't too large
1328 if (vertex->GetZRes() > fMaxVzErr) {
1329 DMSG(fDebug,2,"Uncertaintity in Z of vertex is too large %f > %f",
1330 vertex->GetZRes(), fMaxVzErr);
1334 // Get the z coordiante
1335 ip.SetZ(vertex->GetZ());
1336 const AliESDVertex* vertexXY = esd.GetPrimaryVertex();
1339 if(!vertexXY->IsFromVertexerZ()) {
1340 ip.SetX(vertexXY->GetX());
1341 ip.SetY(vertexXY->GetY());
1346 //____________________________________________________________________
1348 AliFMDEventInspector::ReadRunDetails(const AliESDEvent* esd)
1351 // Read the collision system, collision energy, and L3 field setting
1355 // esd ESD to get information from
1358 // true on success, false
1360 // AliInfo(Form("Parameters from 1st ESD event: cms=%s, sNN=%f, field=%f",
1361 // esd->GetBeamType(), 2*esd->GetBeamEnergy(),
1362 // esd->GetMagneticField()));
1363 DGUARD(fDebug,2,"Read the run details in AliFMDEventInspector");
1364 const char* sys = esd->GetBeamType();
1365 Float_t cms = 2 * esd->GetBeamEnergy();
1366 Float_t fld = esd->GetMagneticField();
1367 fCollisionSystem = AliForwardUtil::ParseCollisionSystem(sys);
1368 fEnergy = AliForwardUtil::ParseCenterOfMassEnergy(fCollisionSystem,
1370 fField = AliForwardUtil::ParseMagneticField(fld);
1371 fRunNumber = esd->GetRunNumber();
1374 if (fCollisionSystem == AliForwardUtil::kUnknown) {
1375 AliWarningF("Unknown collision system: %s - please check", sys);
1379 AliWarningF("Unknown CMS energy: %f (%d) - please check", cms, fEnergy);
1382 if (TMath::Abs(fField) > 10) {
1383 AliWarningF("Unknown L3 field setting: %f (%d) - please check", fld,fField);
1391 //____________________________________________________________________
1393 AliFMDEventInspector::CodeString(UInt_t code)
1397 if (code & kNoEvent) s.Append("NOEVENT ");
1398 if (code & kNoTriggers) s.Append("NOTRIGGERS ");
1399 if (code & kNoSPD) s.Append("NOSPD ");
1400 if (code & kNoFMD) s.Append("NOFMD ");
1401 if (code & kNoVertex) s.Append("NOVERTEX ");
1402 if (code & kBadVertex) s.Append("BADVERTEX ");
1405 #define PF(N,V,...) \
1406 AliForwardUtil::PrintField(N,V, ## __VA_ARGS__)
1407 #define PFB(N,FLAG) \
1409 AliForwardUtil::PrintName(N); \
1410 std::cout << std::boolalpha << (FLAG) << std::noboolalpha << std::endl; \
1412 #define PFV(N,VALUE) \
1414 AliForwardUtil::PrintName(N); \
1415 std::cout << (VALUE) << std::endl; } while(false)
1417 //____________________________________________________________________
1419 AliFMDEventInspector::Print(Option_t*) const
1422 // Print information
1426 AliForwardUtil::PrintTask(*this);
1427 TString sNN(AliForwardUtil::CenterOfMassEnergyString(fEnergy));
1428 sNN.Strip(TString::kBoth, '0');
1429 sNN.ReplaceAll("GeV", " GeV");
1430 TString field(AliForwardUtil::MagneticFieldString(fField));
1431 field.ReplaceAll("p", "+");
1432 field.ReplaceAll("m", "-");
1433 field.ReplaceAll("kG", " kG");
1435 gROOT->IncreaseDirLevel();
1436 PFV("Production", "");
1437 gROOT->IncreaseDirLevel();
1438 PF("Period", "LHC%02d%c", fProdYear, fProdLetter);
1439 PFB("MC anchor", fProdMC);
1440 PFV("AliROOT Revision", fProdSVN);
1441 gROOT->DecreaseDirLevel();
1442 PFV("Vertex bins", fVtxAxis.GetNbins());
1443 PF("Vertex Range", "[%+6.1f,%+6.1f]", fVtxAxis.GetXmin(), fVtxAxis.GetXmax());
1444 PFV("Low flux cut", fLowFluxCut );
1445 PFV("Max(delta v_z)", fMaxVzErr );
1446 PFV("Min(nContrib_pileup)", fMinPileupContrib );
1447 PFV("Min(v-pileup)", fMinPileupDistance );
1448 PFV("System", AliForwardUtil::CollisionSystemString(fCollisionSystem));
1449 PFV("CMS energy per nucleon", sNN);
1450 PFV("Field", field);
1451 PFB("Satellite events", fUseDisplacedVertices);
1452 PFB("Use 2012 pA vertex", fUsepA2012Vertex );
1453 PFB("Use PWG-UD vertex", fUseFirstPhysicsVertex);
1454 PFB("Simulation input", fMC );
1455 PFV("Centrality method", fCentMethod);
1456 PFV("Centrality axis", (!fCentAxis ? "none" : ""));
1457 if (!fCentAxis) {return; }
1458 Int_t nBin = fCentAxis->GetNbins();
1459 for (Int_t i = 0; i < nBin; i++) {
1460 if (i != 0 && (i % 10) == 0) std::cout << '\n';
1461 if ((i % 10) == 0) std::cout << " ";
1462 std::cout << std::setw(5) << fCentAxis->GetBinLowEdge(i+1) << '-';
1464 std::cout << std::setw(5) << fCentAxis->GetBinUpEdge(nBin) << std::endl;
1465 gROOT->DecreaseDirLevel();