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 if (period.Length() > 0) {
646 TObjArray* pp = TPRegexp("LHC([0-9]+)([a-z]+)").MatchS(period);
647 fProdYear = static_cast<TObjString*>(pp->At(1))->String().Atoi();
648 fProdLetter = static_cast<TObjString*>(pp->At(2))->String()[0];
652 out->Add(AliForwardUtil::MakeParameter("year", fProdYear));
653 out->Add(AliForwardUtil::MakeParameter("letter", Int_t(fProdLetter)));
654 out->Add(AliForwardUtil::MakeParameter("alirootSVN", fProdSVN));
655 out->Add(AliForwardUtil::MakeParameter("rootSVN", rootSVN));
656 out->Add(AliForwardUtil::MakeParameter("pass", fProdPass));
657 out->Add(AliForwardUtil::MakeParameter("mc", fProdMC));
663 //____________________________________________________________________
665 AliFMDEventInspector::CreateOutputObjects(TList* dir)
668 // Define the output histograms. These are put in a sub list of the
669 // passed list. The histograms are merged before the parent task calls
670 // AliAnalysisTaskSE::Terminate
672 // dir Directory to add to
674 DGUARD(fDebug,1,"Define output from AliFMDEventInspector");
676 fList->SetName(GetName());
681 //____________________________________________________________________
683 AliFMDEventInspector::Process(const AliESDEvent* event,
696 // triggers On return, the triggers fired
697 // lowFlux On return, true if the event is considered a low-flux
698 // event (according to the setting of fLowFluxCut)
699 // ivz On return, the found vertex bin (1-based). A zero
700 // means outside of the defined vertex range
701 // vz On return, the z position of the interaction
702 // cent On return, the centrality - if not available < 0
705 // 0 (or kOk) on success, otherwise a bit mask of error codes
707 DGUARD(fDebug,1,"Process event in AliFMDEventInspector");
708 // --- Check that we have an event ---------------------------------
710 AliWarning("No ESD event found for input event");
715 // --- Process satellite event information is requested ------------
716 if (fUseDisplacedVertices) {
717 if (!fDisplacedVertex.Process(event))
718 AliWarning("Failed to process satellite event");
721 // --- Read trigger information from the ESD and store in AOD object
722 if (!ReadTriggers(*event, triggers, nClusters)) {
724 AliWarning("Failed to read triggers from ESD"); }
729 // --- Check if this is a high-flux event --------------------------
730 const AliMultiplicity* testmult = event->GetMultiplicity();
733 AliWarning("No central multiplicity object found"); }
736 lowFlux = testmult->GetNumberOfTracklets() < fLowFluxCut;
738 fHType->Fill(lowFlux ? 0 : 1);
740 // --- Get the interaction point -----------------------------------
741 Bool_t vzOk = ReadVertex(*event, ip);
742 fHEventsTr->Fill(ip.Z());
745 AliWarning("Failed to read vertex from ESD"); }
750 // --- Read centrality information
753 if (!ReadCentrality(*event, cent, qual)) {
755 AliWarning("Failed to get centrality");
757 // --- check centrality cut
759 if(fMinCent > -0.0001 && cent < fMinCent) return kNoEvent;
760 if(fMaxCent > -0.0001 && cent > fMaxCent) return kNoEvent;
761 if (cent >= 0) fHCent->Fill(cent);
762 if (qual == 0) fHCentVsQual->Fill(0., cent);
765 for (UShort_t i = 0; i < 4; i++)
766 if (qual & (1 << i)) fHCentVsQual->Fill(Double_t(i+1), cent);
770 fHEventsTrVtx->Fill(ip.Z());
772 // --- Get the vertex bin ------------------------------------------
773 ivz = fVtxAxis.FindBin(ip.Z());
774 if (ivz <= 0 || ivz > fVtxAxis.GetNbins()) {
776 AliWarning(Form("Vertex @ %f outside of range [%f,%f]",
777 ip.Z(), fVtxAxis.GetXmin(), fVtxAxis.GetXmax()));
783 fHEventsAccepted->Fill(ip.Z());
784 fHEventsAcceptedXY->Fill(ip.X(),ip.Y());
786 // --- Check the FMD ESD data --------------------------------------
787 if (!event->GetFMDData()) {
789 AliWarning("No FMD data found in ESD"); }
798 //____________________________________________________________________
800 AliFMDEventInspector::ReadCentrality(const AliESDEvent& esd,
802 UShort_t& qual) const
805 // Read centrality from event
809 // cent On return, the centrality or negative if not found
812 // False on error, true otherwise
814 DGUARD(fDebug,2,"Read the centrality in AliFMDEventInspector");
818 AliCentrality* centObj = const_cast<AliESDEvent&>(esd).GetCentrality();
820 cent = centObj->GetCentralityPercentile(fCentMethod);
821 qual = centObj->GetQuality();
824 // We overwrite with satellite events, so we can be sure to get the
825 // centrality determination from the satellite vertex selection
826 if (fUseDisplacedVertices && fDisplacedVertex.IsSatellite()) {
827 cent = fDisplacedVertex.GetCentralityPercentile();
834 //____________________________________________________________________
836 AliFMDEventInspector::CheckpAExtraV0(const AliESDEvent& esd) const
838 if (fCollisionSystem != AliForwardUtil::kPPb) return true;
840 AliVVZERO* esdV0 = esd.GetVZEROData();
841 if ((esdV0->GetV0ADecision()!=1) || (esdV0->GetV0CDecision()!=1))
846 //____________________________________________________________________
848 AliFMDEventInspector::ReadTriggers(const AliESDEvent& esd, UInt_t& triggers,
852 // Read the trigger information from the ESD event
856 // triggers On return, contains the trigger bits
859 // @c true on success, @c false otherwise
861 DGUARD(fDebug,2,"Read the triggers in AliFMDEventInspector");
864 // Get the analysis manager - should always be there
865 AliAnalysisManager* am = AliAnalysisManager::GetAnalysisManager();
866 DMSG(fDebug,10,"Got analysis manager %p", am);
868 AliWarning("No analysis manager defined!");
872 // Get the input handler - should always be there
873 AliInputEventHandler* ih =
874 static_cast<AliInputEventHandler*>(am->GetInputEventHandler());
875 DMSG(fDebug,10,"Got input handler %p", ih);
877 AliWarning("No input handler");
881 // Check if this is a collision candidate (MB)
883 // Historic remark: Note, that we should use the value cached in the
884 // input handler rather than calling IsCollisionCandiate directly
885 // on the AliPhysicsSelection obejct. If we called the latter
886 // then the AliPhysicsSelection object would overcount by a factor
888 UInt_t trgMask = ih->IsEventSelected();
889 Bool_t offline = trgMask;
890 Bool_t fastonly = (trgMask & AliVEvent::kFastOnly);
891 TString trigStr = esd.GetFiredTriggerClasses();
893 if (trigStr.IsNull()) fHTrgStatus->Fill(kNoTrgWords);
894 if (fHWords) fHWords->Fill(trigStr.Data(), 1);
896 if(fUseDisplacedVertices) {
897 DMSG(fDebug,3,"Using displaced vertex stuff");
898 // if (TMath::Abs(fDisplacedVertex.GetVertexZ()) >= 999) offline = false;
899 if (fDisplacedVertex.IsSatellite())
900 triggers |= AliAODForwardMult::kSatellite;
903 if (CheckFastPartition(fastonly)) {
904 fHTrgStatus->Fill(kPP2760Fast);
908 if (offline && CheckCosmics(trigStr)) {
909 fHTrgStatus->Fill(kMUON);
912 if (offline) fHTrgStatus->Fill(kTriggered);
914 if (trgMask & AliVEvent::kMB) f += fHTrgStatus->Fill(kMinBias);
915 if (trgMask & AliVEvent::kCINT5) f += fHTrgStatus->Fill(kMinBiasNoSPD);
916 if (trgMask & AliVEvent::kINT7) f += fHTrgStatus->Fill(kV0AndTrg);
917 if (trgMask & AliVEvent::kHighMult) f += fHTrgStatus->Fill(kHighMult);
918 if (trgMask & AliVEvent::kCentral) f += fHTrgStatus->Fill(kCentral);
919 if (trgMask & AliVEvent::kSemiCentral) f += fHTrgStatus->Fill(kSemiCentral);
920 if (trgMask & AliVEvent::kDG5) f += fHTrgStatus->Fill(kDiffractive);
921 if (trgMask & AliVEvent::kUserDefined) f += fHTrgStatus->Fill(kUser);
922 if (f <= 0) fHTrgStatus->Fill(kOther);
924 // if (!CheckpAExtraV0(esd)) offline = false;
926 DMSG(fDebug,2,"Event is %striggered by off-line", offline ? "" : "NOT ");
928 if (offline) triggers |= AliAODForwardMult::kOffline;
929 // Only flag as in-elastic if a min-bias trigger is here
930 if (trgMask & AliVEvent::kMB) {
931 triggers |= AliAODForwardMult::kInel;
932 CheckINELGT0(esd, nClusters, triggers);
935 CheckNSD(esd,triggers);
936 CheckPileup(esd, triggers);
937 CheckEmpty(trigStr, triggers);
938 // if (CheckPileup(esd, triggers)) fHTriggers->Fill(kPileUp+.5);
939 // if (CheckEmpty(trigStr, triggers)) fHTriggers->Fill(kEmpty+.5);
941 CheckWords(esd, triggers);
943 #define TEST_TRIG_BIN(RET,BIN,TRIGGERS) \
944 do { switch (BIN) { \
945 case kInel: RET = triggers & AliAODForwardMult::kInel; break; \
946 case kInelGt0: RET = triggers & AliAODForwardMult::kInelGt0; break; \
947 case kNSD: RET = triggers & AliAODForwardMult::kNSD; break; \
948 case kV0AND: RET = triggers & AliAODForwardMult::kV0AND; break; \
949 case kEmpty: RET = triggers & AliAODForwardMult::kEmpty; break; \
950 case kA: RET = triggers & AliAODForwardMult::kA; break; \
951 case kB: RET = triggers & AliAODForwardMult::kB; break; \
952 case kC: RET = triggers & AliAODForwardMult::kC; break; \
953 case kE: RET = triggers & AliAODForwardMult::kE; break; \
954 case kPileUp: RET = triggers & AliAODForwardMult::kPileUp; break; \
955 case kMCNSD: RET = triggers & AliAODForwardMult::kMCNSD; break; \
956 case kSatellite:RET = triggers & AliAODForwardMult::kSatellite; break; \
957 case kOffline: RET = triggers & AliAODForwardMult::kOffline; break; \
958 default: RET = false; } } while(false)
961 AliWarning("Histogram of triggers not defined - has init been called");
965 for (Int_t i = 0; i < kOffline+1; i++) {
967 TEST_TRIG_BIN(hasX, i, triggers);
969 fHTriggers->Fill(i+.5);
970 for (Int_t j = 0; j < kOffline+1; j++) {
972 TEST_TRIG_BIN(hasY, j, triggers);
975 fHTriggerCorr->Fill(i+.5, j+.5);
981 //____________________________________________________________________
983 AliFMDEventInspector::CheckFastPartition(bool fastonly) const
985 // For the 2.76 TeV p+p run, the FMD ran in the slow partition
986 // so it received no triggers from the fast partition. Therefore
987 // the fast triggers are removed here but not for MC where all
988 // triggers are fast.
989 if (TMath::Abs(fEnergy - 2750.) > 20) return false;
990 if (fCollisionSystem != AliForwardUtil::kPP) return false;
991 if (fMC) return false; // All MC events for pp @ 2.76TeV are `fast'
993 DMSG(fDebug,1,"Fast trigger in pp @ sqrt(s)=2.76TeV removed");
998 //____________________________________________________________________
1000 AliFMDEventInspector::CheckCosmics(const TString& trigStr) const
1002 // MUON triggers are not strictly minimum bias (MB) so they are
1004 if(trigStr.Contains("CMUS1")) {
1005 DMSG(fDebug,1,"Cosmic trigger ins't min-bias, removed");
1011 //____________________________________________________________________
1013 AliFMDEventInspector::CheckINELGT0(const AliESDEvent& esd,
1014 UShort_t& nClusters,
1015 UInt_t& triggers) const
1019 // If this is inel, see if we have a tracklet
1020 const AliMultiplicity* spdmult = esd.GetMultiplicity();
1022 AliWarning("No SPD multiplicity");
1026 // Check if we have one or more tracklets
1027 // in the range -1 < eta < 1 to set the INEL>0
1030 // Also count tracklets as a single cluster
1031 Int_t n = spdmult->GetNumberOfTracklets();
1032 for (Int_t j = 0; j < n; j++) {
1033 if(TMath::Abs(spdmult->GetEta(j)) < 1) nClusters++;
1035 // If we at this point had non-zero nClusters, it's INEL>0
1036 if (nClusters > 0) triggers |= AliAODForwardMult::kInelGt0;
1038 // Loop over single clusters
1039 n = spdmult->GetNumberOfSingleClusters();
1040 for (Int_t j = 0; j < n; j++) {
1041 Double_t eta = -TMath::Log(TMath::Tan(spdmult->GetThetaSingle(j)/2.));
1042 if (TMath::Abs(eta) < 1) nClusters++;
1044 if (nClusters > 0) triggers |= AliAODForwardMult::kNClusterGt0;
1046 return triggers & AliAODForwardMult::kNClusterGt0;
1049 //____________________________________________________________________
1051 AliFMDEventInspector::CheckNSD(const AliESDEvent& esd, UInt_t& triggers) const
1053 // Analyse some trigger stuff
1054 AliTriggerAnalysis ta;
1055 if (ta.IsOfflineTriggerFired(&esd, AliTriggerAnalysis::kV0AND)) {
1056 triggers |= AliAODForwardMult::kV0AND;
1058 triggers |= AliAODForwardMult::kNSD;
1060 if (ta.IsOfflineTriggerFired(&esd, AliTriggerAnalysis::kNSD1))
1061 triggers |= AliAODForwardMult::kNSD;
1062 return triggers & AliAODForwardMult::kNSD;
1064 //____________________________________________________________________
1066 AliFMDEventInspector::CheckPileup(const AliESDEvent& esd,
1067 UInt_t& triggers) const
1069 // Check for multiple vertices (pile-up) with at least 3
1070 // contributors and at least 0.8cm from the primary vertex
1071 // if(fCollisionSystem != AliForwardUtil::kPP) return false;
1073 // Check for standard SPD pile-up
1074 Bool_t spdPileup = esd.IsPileupFromSPD(fMinPileupContrib,fMinPileupDistance);
1076 // Check for multi-vertex pileup
1077 Bool_t mvPileup = false; // CheckMultiVertex(esd);
1079 // Check for out-of-bunch pileup
1080 Bool_t outPileup = (esd.GetHeader()->GetIRInt2ClosestInteractionMap() != 0 ||
1081 esd.GetHeader()->GetIRInt1ClosestInteractionMap() != 0);
1084 Bool_t pileup = spdPileup || mvPileup || outPileup;
1085 if (pileup) triggers |= AliAODForwardMult::kPileUp;
1089 //____________________________________________________________________
1091 AliFMDEventInspector::CheckMultiVertex(const AliESDEvent& esd,
1092 Bool_t checkOtherBC) const
1094 // Adapted from AliAnalysisUtils
1097 const Double_t maxChi2nu = 5;
1099 // Number of vertices
1100 Int_t n = esd.GetNumberOfPileupVerticesTracks();
1102 // No additional vertices from tracks -> no pileup
1106 const AliESDVertex* primary = esd.GetPrimaryVertexTracks();
1107 if (primary->GetStatus() != 1)
1108 // No good primary vertex, but many candidates -> pileup
1111 // Bunch crossing number
1112 Int_t bcPrimary = primary->GetBC();
1114 for (Int_t i = 0; i < n; i++) {
1115 const AliESDVertex* other = esd.GetPileupVertexTracks(i);
1117 if (other->GetNContributors() < fMinPileupContrib)
1118 // Not enough contributors to this vertex
1121 if (other->GetChi2perNDF() > maxChi2nu)
1122 // Poorly determined vertex
1125 Int_t bcOther = other->GetBC();
1126 if (bcOther != AliVTrack::kTOFBCNA && TMath::Abs(bcOther-bcPrimary) > 2)
1127 // Pile-up from other BC
1130 // Calculate the distance
1132 Double_t dx = primary->GetX() - other->GetX();
1133 Double_t dy = primary->GetY() - other->GetY();
1134 Double_t dz = primary->GetZ() - other->GetZ();
1135 Double_t covPrimary[6], covOther[6];
1136 primary->GetCovarianceMatrix(covPrimary);
1137 other->GetCovarianceMatrix(covOther);
1139 v(0,0) = covPrimary[0] + covOther[0]; // diagonal
1140 v(1,1) = covPrimary[2] + covOther[2]; // diagonal
1141 v(2,2) = covPrimary[5] + covOther[5]; // diagonal
1142 v(1,0) = v(0,1) = covPrimary[1]+covOther[1]; // Band
1143 v(0,2) = v(1,2) = v(2,0) = v(2,1) = 0; // Off-diagonal+band
1147 // Question if kStatus bit is every set after InvertFast?
1149 d = (v(0,0) * dx * dx + v(1,1) * dy * dy + v(2,2) * dz * dz +
1150 2 * (v(0,1) * dx * dy + v(0,2) * dx * dz + v(1,2) * dy * dz));
1152 if (d < 0 || TMath::Sqrt(d) < fMinPileupDistance)
1153 // Bad distance, or not fare enough from each other
1156 // Well separated vertices -> pileup
1162 //____________________________________________________________________
1164 AliFMDEventInspector::CheckEmpty(const TString& trigStr, UInt_t& triggers) const
1166 if (trigStr.Contains("CBEAMB-ABCE-NOPF-ALL")) {
1167 triggers |= AliAODForwardMult::kEmpty;
1172 //____________________________________________________________________
1174 AliFMDEventInspector::CheckWords(const AliESDEvent& esd, UInt_t& triggers) const
1177 TIter nextColl(&fCollWords);
1178 while ((word = nextColl())) {
1179 DMSG(fDebug,10,"Checking if %s trigger %s is fired",
1180 word->GetTitle(), word->GetName());
1181 if (!esd.IsTriggerClassFired(word->GetName())) continue;
1183 TString beamSide = word->GetTitle();
1184 DMSG(fDebug,10,"Found it - this is a %s trigger", beamSide.Data());
1186 if (!beamSide.EqualTo("B")) continue;
1187 triggers |= AliAODForwardMult::kB;
1188 break; // No more to do here
1190 TIter nextBg(&fBgWords);
1191 UInt_t all = (AliAODForwardMult::kA |
1192 AliAODForwardMult::kC |
1193 AliAODForwardMult::kE);
1194 while ((word = nextBg())) {
1195 DMSG(fDebug,10,"Checking if %s trigger %s is fired",
1196 word->GetTitle(), word->GetName());
1197 if (!esd.IsTriggerClassFired(word->GetName())) continue;
1199 TString beamSide = word->GetTitle();
1200 DMSG(fDebug,10,"Found it - this is a %s trigger", beamSide.Data());
1202 if (beamSide.Contains("A")) triggers |= AliAODForwardMult::kA;
1203 if (beamSide.Contains("C")) triggers |= AliAODForwardMult::kC;
1204 if (beamSide.Contains("E")) triggers |= AliAODForwardMult::kE;
1206 if ((triggers & all) == all) break; // No more to do
1212 //____________________________________________________________________
1214 AliFMDEventInspector::ReadVertex(const AliESDEvent& esd, TVector3& ip)
1217 // Read the vertex information from the ESD event
1221 // vz On return, the vertex Z position
1224 // @c true on success, @c false otherwise
1226 DGUARD(fDebug,2,"Read the vertex in AliFMDEventInspector");
1227 ip.SetXYZ(1024, 1024, 0);
1229 EVtxStatus s = kNoVtx;
1230 if (fUseDisplacedVertices && fDisplacedVertex.IsSatellite()) {
1232 ip.SetZ(fDisplacedVertex.GetVertexZ());
1234 else if (fUseFirstPhysicsVertex)
1235 s = CheckPWGUDVertex(esd, ip);
1236 else if (fUsepA2012Vertex)
1237 s = CheckpA2012Vertex(esd,ip);
1239 s = CheckVertex(esd, ip);
1241 fHVtxStatus->Fill(s);
1246 //____________________________________________________________________
1247 AliFMDEventInspector::EVtxStatus
1248 AliFMDEventInspector::CheckPWGUDVertex(const AliESDEvent& esd,
1251 // This is the code used by the 1st physics people
1252 const AliESDVertex* vertex = esd.GetPrimaryVertex();
1253 if (!vertex || !vertex->GetStatus()) {
1254 DMSG(fDebug,2,"No primary vertex (%p) or bad status %d",
1255 vertex, (vertex ? vertex->GetStatus() : -1));
1258 const AliESDVertex* vertexSPD = esd.GetPrimaryVertexSPD();
1259 if (!vertexSPD || !vertexSPD->GetStatus()) {
1260 DMSG(fDebug,2,"No primary SPD vertex (%p) or bad status %d",
1261 vertexSPD, (vertexSPD ? vertexSPD->GetStatus() : -1));
1265 // if vertex is from SPD vertexZ, require more stringent cuts
1266 if (vertex->IsFromVertexerZ()) {
1267 if (vertex->GetDispersion() > fMaxVzErr ||
1268 vertex->GetZRes() > 1.25 * fMaxVzErr) {
1269 DMSG(fDebug,2,"Dispersion %f > %f or resolution %f > %f",
1270 vertex->GetDispersion(), fMaxVzErr,
1271 vertex->GetZRes(), 1.25 * fMaxVzErr);
1275 ip.SetZ(vertex->GetZ());
1277 if(!vertex->IsFromVertexerZ()) {
1278 ip.SetX(vertex->GetX());
1279 ip.SetY(vertex->GetY());
1283 //____________________________________________________________________
1284 AliFMDEventInspector::EVtxStatus
1285 AliFMDEventInspector::CheckpA2012Vertex(const AliESDEvent& esd,
1288 const AliESDVertex *vertex = esd.GetPrimaryVertexSPD();
1289 if (!vertex) return kNoSPDVtx;
1290 if (vertex->GetNContributors() <= 0) return kFewContrib;
1292 TString vtxTyp = vertex->GetTitle();
1293 if (vtxTyp.Contains("vertexer: Z")) return kNotVtxZ;
1295 if (vertex->GetDispersion() >= 0.04 || vertex->GetZRes()>=0.25)
1298 ip.SetX(vertex->GetX());
1299 ip.SetY(vertex->GetY());
1300 ip.SetZ(vertex->GetZ());
1305 //____________________________________________________________________
1306 AliFMDEventInspector::EVtxStatus
1307 AliFMDEventInspector::CheckVertex(const AliESDEvent& esd,
1310 // Use standard SPD vertex (perhaps preferable for Pb+Pb)
1312 const AliESDVertex* vertex = esd.GetPrimaryVertexSPD();
1315 AliWarning("No SPD vertex found in ESD"); }
1319 // #if 0 // Check disabled - seem to kill a lot of PbPb events
1320 // Check that enough tracklets contributed
1321 if(vertex->GetNContributors() <= 0) {
1322 DMSG(fDebug,2,"Number of contributors to vertex is %d<=0",
1323 vertex->GetNContributors());
1329 // Check that the uncertainty isn't too large
1330 if (vertex->GetZRes() > fMaxVzErr) {
1331 DMSG(fDebug,2,"Uncertaintity in Z of vertex is too large %f > %f",
1332 vertex->GetZRes(), fMaxVzErr);
1336 // Get the z coordiante
1337 ip.SetZ(vertex->GetZ());
1338 const AliESDVertex* vertexXY = esd.GetPrimaryVertex();
1341 if(!vertexXY->IsFromVertexerZ()) {
1342 ip.SetX(vertexXY->GetX());
1343 ip.SetY(vertexXY->GetY());
1348 //____________________________________________________________________
1350 AliFMDEventInspector::ReadRunDetails(const AliESDEvent* esd)
1353 // Read the collision system, collision energy, and L3 field setting
1357 // esd ESD to get information from
1360 // true on success, false
1362 // AliInfo(Form("Parameters from 1st ESD event: cms=%s, sNN=%f, field=%f",
1363 // esd->GetBeamType(), 2*esd->GetBeamEnergy(),
1364 // esd->GetMagneticField()));
1365 DGUARD(fDebug,2,"Read the run details in AliFMDEventInspector");
1366 const char* sys = esd->GetBeamType();
1367 Float_t cms = 2 * esd->GetBeamEnergy();
1368 Float_t fld = esd->GetMagneticField();
1369 fCollisionSystem = AliForwardUtil::ParseCollisionSystem(sys);
1370 fEnergy = AliForwardUtil::ParseCenterOfMassEnergy(fCollisionSystem,
1372 fField = AliForwardUtil::ParseMagneticField(fld);
1373 fRunNumber = esd->GetRunNumber();
1376 if (fCollisionSystem == AliForwardUtil::kUnknown) {
1377 AliWarningF("Unknown collision system: %s - please check", sys);
1381 AliWarningF("Unknown CMS energy: %f (%d) - please check", cms, fEnergy);
1384 if (TMath::Abs(fField) > 10) {
1385 AliWarningF("Unknown L3 field setting: %f (%d) - please check", fld,fField);
1393 //____________________________________________________________________
1395 AliFMDEventInspector::CodeString(UInt_t code)
1399 if (code & kNoEvent) s.Append("NOEVENT ");
1400 if (code & kNoTriggers) s.Append("NOTRIGGERS ");
1401 if (code & kNoSPD) s.Append("NOSPD ");
1402 if (code & kNoFMD) s.Append("NOFMD ");
1403 if (code & kNoVertex) s.Append("NOVERTEX ");
1404 if (code & kBadVertex) s.Append("BADVERTEX ");
1407 #define PF(N,V,...) \
1408 AliForwardUtil::PrintField(N,V, ## __VA_ARGS__)
1409 #define PFB(N,FLAG) \
1411 AliForwardUtil::PrintName(N); \
1412 std::cout << std::boolalpha << (FLAG) << std::noboolalpha << std::endl; \
1414 #define PFV(N,VALUE) \
1416 AliForwardUtil::PrintName(N); \
1417 std::cout << (VALUE) << std::endl; } while(false)
1419 //____________________________________________________________________
1421 AliFMDEventInspector::Print(Option_t*) const
1424 // Print information
1428 AliForwardUtil::PrintTask(*this);
1429 TString sNN(AliForwardUtil::CenterOfMassEnergyString(fEnergy));
1430 sNN.Strip(TString::kBoth, '0');
1431 sNN.ReplaceAll("GeV", " GeV");
1432 TString field(AliForwardUtil::MagneticFieldString(fField));
1433 field.ReplaceAll("p", "+");
1434 field.ReplaceAll("m", "-");
1435 field.ReplaceAll("kG", " kG");
1437 gROOT->IncreaseDirLevel();
1438 PFV("Production", "");
1439 gROOT->IncreaseDirLevel();
1440 PF("Period", "LHC%02d%c", fProdYear, fProdLetter);
1441 PFB("MC anchor", fProdMC);
1442 PFV("AliROOT Revision", fProdSVN);
1443 gROOT->DecreaseDirLevel();
1444 PFV("Vertex bins", fVtxAxis.GetNbins());
1445 PF("Vertex Range", "[%+6.1f,%+6.1f]", fVtxAxis.GetXmin(), fVtxAxis.GetXmax());
1446 PFV("Low flux cut", fLowFluxCut );
1447 PFV("Max(delta v_z)", fMaxVzErr );
1448 PFV("Min(nContrib_pileup)", fMinPileupContrib );
1449 PFV("Min(v-pileup)", fMinPileupDistance );
1450 PFV("System", AliForwardUtil::CollisionSystemString(fCollisionSystem));
1451 PFV("CMS energy per nucleon", sNN);
1452 PFV("Field", field);
1453 PFB("Satellite events", fUseDisplacedVertices);
1454 PFB("Use 2012 pA vertex", fUsepA2012Vertex );
1455 PFB("Use PWG-UD vertex", fUseFirstPhysicsVertex);
1456 PFB("Simulation input", fMC );
1457 PFV("Centrality method", fCentMethod);
1458 PFV("Centrality axis", (!fCentAxis ? "none" : ""));
1459 if (!fCentAxis) {return; }
1460 Int_t nBin = fCentAxis->GetNbins();
1461 for (Int_t i = 0; i < nBin; i++) {
1462 if (i != 0 && (i % 10) == 0) std::cout << '\n';
1463 if ((i % 10) == 0) std::cout << " ";
1464 std::cout << std::setw(5) << fCentAxis->GetBinLowEdge(i+1) << '-';
1466 std::cout << std::setw(5) << fCentAxis->GetBinUpEdge(nBin) << std::endl;
1467 gROOT->DecreaseDirLevel();