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 //====================================================================
47 const char* AliFMDEventInspector::fgkFolderName = "fmdEventInspector";
49 //____________________________________________________________________
50 AliFMDEventInspector::AliFMDEventInspector()
55 fHEventsAcceptedXY(0),
70 fCollisionSystem(kUnknown),
74 fUseFirstPhysicsVertex(false),
77 fMinPileupDistance(0.8),
78 fUseDisplacedVertices(false),
85 fUsepA2012Vertex(false),
97 DGUARD(fDebug,1,"Default CTOR of AliFMDEventInspector");
100 //____________________________________________________________________
101 AliFMDEventInspector::AliFMDEventInspector(const char* name)
102 : TNamed(fgkFolderName, name),
106 fHEventsAcceptedXY(0),
121 fCollisionSystem(kUnknown),
125 fUseFirstPhysicsVertex(false),
127 fMinPileupContrib(3),
128 fMinPileupDistance(0.8),
129 fUseDisplacedVertices(false),
136 fUsepA2012Vertex(false),
149 // name Name of object
151 DGUARD(fDebug,1,"Named CTOR of AliFMDEventInspector: %s", name);
154 //____________________________________________________________________
155 AliFMDEventInspector::~AliFMDEventInspector()
160 DGUARD(fDebug,1,"DTOR of AliFMDEventInspector");
161 // if (fList) delete fList;
164 //____________________________________________________________________
166 AliFMDEventInspector::SetCentralityMethod(ECentMethod m)
169 case kV0Multiplicity: fCentMethod = "VOM"; break; // VZERO multiplicity
170 case kV0Amplitude: fCentMethod = "V0A"; break; // VZERO amplitude
171 case kV0Charge: fCentMethod = "V0C"; break; // VZERO charge
172 case kFMDRough: fCentMethod = "FMD"; break; // FMD scaled energy l
173 case kNTracks: fCentMethod = "TRK"; break; // Number of tracks
174 case kLTracks: fCentMethod = "TKL"; break; // Number of tracks
175 case kCL0: fCentMethod = "CL0"; break; //
176 case kCL1: fCentMethod = "CL1"; break; //
177 case kCND: fCentMethod = "CND"; break; //
178 case kNParticles: fCentMethod = "NPA"; break; // Neutral particles
179 case kNeutrons: fCentMethod = "ZNA"; break; // ZDC neutron amplitu
180 case kV0vsFMD: fCentMethod = "V0MvsFMD"; break; // VZERO versus FMD
181 case kV0vsNTracks: fCentMethod = "TKLvsVOM"; break; // Tracks versus VZERO
182 case kZEMvsZDC: fCentMethod = "ZEMvsZDC"; break; // ZDC
183 default: fCentMethod = "V0M"; break;
187 //____________________________________________________________________
189 AliFMDEventInspector::SetMinCentrality(Double_t minCent)
192 "*******************************************************\n"
193 "* Setting centrality cuts in this stage is deprecated *\n"
194 "*******************************************************");
197 //____________________________________________________________________
199 AliFMDEventInspector::SetMaxCentrality(Double_t maxCent)
202 "*******************************************************\n"
203 "* Setting centrality cuts in this stage is deprecated *\n"
204 "*******************************************************");
208 //____________________________________________________________________
210 AliFMDEventInspector::FetchHistograms(const TList* d,
214 TH1I*& hTriggers) const
217 // Fetch our histograms from the passed list
221 // hEventsTr On return, pointer to histogram, or null
222 // hEventsTrVtx On return, pointer to histogram, or null
223 // hTriggers On return, pointer to histogram, or null
226 // true on success, false otherwise
228 DGUARD(fDebug,3,"Fetch histograms in AliFMDEventInspector");
233 TList* dd = dynamic_cast<TList*>(d->FindObject(GetName()));
234 if (!dd) return kFALSE;
236 hEventsTr = dynamic_cast<TH1I*>(dd->FindObject("nEventsTr"));
237 hEventsTrVtx = dynamic_cast<TH1I*>(dd->FindObject("nEventsTrVtx"));
238 hEventsAcc = dynamic_cast<TH1I*>(dd->FindObject("nEventsAccepted"));
239 hTriggers = dynamic_cast<TH1I*>(dd->FindObject("triggers"));
244 !hTriggers) return kFALSE;
247 //____________________________________________________________________
249 AliFMDEventInspector::CacheConfiguredTriggerClasses(TList& cache,
250 const TList* classes,
251 AliOADBPhysicsSelection* o)
253 TIter nextClass(classes);
254 TObjString* trigClass = 0;
255 // Loop over all trigger classes. Trigger classes have the format
257 // class := positive_words SPACE(s) negative_words
265 while ((trigClass = static_cast<TObjString*>(nextClass()))) {
266 // Tokenize on space to get positive and negative parts
267 TString side = o->GetBeamSide(trigClass->String());
268 TObjArray* parts = trigClass->String().Tokenize(" ");
269 TObjString* part = 0;
270 TIter nextPart(parts);
271 while ((part = static_cast<TObjString*>(nextPart()))) {
272 // We only care about the positive ones
273 if (part->GetName()[0] != '+') continue;
274 part->String().Remove(0,1);
276 // Tokenize on a comma to get the words
277 TObjArray* words = part->String().Tokenize(",");
278 TObjString* word = 0;
279 TIter nextWord(words);
280 while ((word = static_cast<TObjString*>(nextWord()))) {
281 TNamed* store = new TNamed(word->String(), side);
283 DMSG(fDebug,3,"Caching %s trigger word %s",
284 store->GetTitle(), store->GetName());
292 //____________________________________________________________________
294 AliFMDEventInspector::SetupForData(const TAxis& vtxAxis)
297 // Initialize the object - this is called on the first seen event.
300 // vtxAxis Vertex axis in use
302 DGUARD(fDebug,1,"Initialize in AliFMDEventInspector");
304 AliAnalysisManager* am = AliAnalysisManager::GetAnalysisManager();
306 // Get the input handler - should always be there
307 AliInputEventHandler* ih =
308 static_cast<AliInputEventHandler*>(am->GetInputEventHandler());
310 AliWarning("No input handler");
313 // Get the physics selection - should always be there
314 AliPhysicsSelection* ps =
315 static_cast<AliPhysicsSelection*>(ih->GetEventSelection());
317 AliWarning("No physics selection");
320 // Get the configured triggers
321 AliOADBPhysicsSelection* oadb =
322 const_cast<AliOADBPhysicsSelection*>(ps->GetOADBPhysicsSelection());
324 AliWarning("No OADB physics selection object");
327 // Get the configured trigger words from the physics selection
328 const TList* collTriggClasses = ps->GetCollisionTriggerClasses();
329 const TList* bgTriggClasses = ps->GetBGTriggerClasses();
330 if (!collTriggClasses) {
331 AliWarning("No configured collision trigger classes");
334 if (!bgTriggClasses) {
335 AliWarning("No configured background trigger classes");
338 CacheConfiguredTriggerClasses(fCollWords, collTriggClasses, oadb);
339 CacheConfiguredTriggerClasses(fBgWords, bgTriggClasses, oadb);
345 if ((fMinCent < 0 && fMaxCent < 0) || fMaxCent <= fMinCent) {
346 // -1.5 -0.5 0.5 1.5 ... 89.5 ... 100.5
347 // ----- 92 number --------- ---- 1 ---
349 for (Int_t i = 0; i < 92; i++) limits[i] = -1.5 + i;
353 Int_t n = fMaxCent-fMinCent+2;
355 for (Int_t i = 0; i < n; i++) {
356 limits[i] = fMinCent + i - .5;
360 fVtxAxis.Set(vtxAxis.GetNbins(), vtxAxis.GetXmin(), vtxAxis.GetXmax());
362 fCentAxis = new TAxis(limits.GetSize()-1, limits.GetArray());
363 fHEventsTr = new TH1I("nEventsTr", "Number of events w/trigger",
364 4*vtxAxis.GetNbins(),
366 2*vtxAxis.GetXmax());
367 fHEventsTr->SetXTitle("v_{z} [cm]");
368 fHEventsTr->SetYTitle("# of events");
369 fHEventsTr->SetFillColor(kRed+1);
370 fHEventsTr->SetFillStyle(3001);
371 fHEventsTr->SetDirectory(0);
372 // fHEventsTr->Sumw2();
373 fList->Add(fHEventsTr);
375 fHEventsTrVtx = static_cast<TH1I*>(fHEventsTr->Clone("nEventsTrVtx"));
376 fHEventsTrVtx->SetTitle("Number of events w/trigger and vertex");
377 fHEventsTrVtx->SetFillColor(kBlue+1);
378 fHEventsTrVtx->SetDirectory(0);
379 // fHEventsTrVtx->Sumw2();
380 fList->Add(fHEventsTrVtx);
382 fHEventsAccepted = new TH1I("nEventsAccepted",
383 "Number of events w/trigger and vertex in range",
384 2*vtxAxis.GetNbins(),
386 2*vtxAxis.GetXmax());
387 fHEventsAccepted->SetXTitle("v_{z} [cm]");
388 fHEventsAccepted->SetYTitle("# of events");
389 fHEventsAccepted->SetFillColor(kGreen+1);
390 fHEventsAccepted->SetFillStyle(3001);
391 fHEventsAccepted->SetDirectory(0);
392 // fHEventsAccepted->Sumw2();
393 fList->Add(fHEventsAccepted);
395 fHEventsAcceptedXY = new TH2D("nEventsAcceptedXY",
396 "XY vertex w/trigger and Z vertex in range",
397 1000,-1,1,1000,-1,1);
399 fHEventsAcceptedXY->SetXTitle("v_{x} [cm]");
400 fHEventsAcceptedXY->SetYTitle("v_{y} [cm]");
401 fHEventsAcceptedXY->SetDirectory(0);
402 // fHEventsAccepted->Sumw2();
403 fList->Add(fHEventsAcceptedXY);
406 fHTriggers = new TH1I("triggers", "Triggers", kOffline+1, 0, kOffline+1);
407 fHTriggers->SetFillColor(kRed+1);
408 fHTriggers->SetFillStyle(3001);
409 fHTriggers->SetStats(0);
410 fHTriggers->SetDirectory(0);
412 fHTriggerCorr = new TH2I("triggerCorr", "Trigger correlation",
413 kOffline+1, 0, kOffline+1,
414 kOffline+1, 0, kOffline+1);
415 fHTriggerCorr->SetStats(0);
416 fHTriggerCorr->SetDirectory(0);
417 fHTriggerCorr->SetXTitle("Requirement");
418 fHTriggerCorr->SetYTitle("Companion");
420 Int_t binNum[] = { kInel +1,
433 const char* binLbl[] = { "INEL",
446 for (Int_t i = 0; i < kOffline+1; i++) {
447 fHTriggers->GetXaxis()->SetBinLabel(binNum[i], binLbl[i]);
448 fHTriggerCorr->GetXaxis()->SetBinLabel(binNum[i], binLbl[i]);
449 fHTriggerCorr->GetYaxis()->SetBinLabel(binNum[i], binLbl[i]);
451 fList->Add(fHTriggers);
452 fList->Add(fHTriggerCorr);
455 fHType = new TH1I("type", Form("Event type (cut: SPD mult>%d)",
456 fLowFluxCut), 2, -.5, 1.5);
457 fHType->SetFillColor(kRed+1);
458 fHType->SetFillStyle(3001);
460 fHType->SetDirectory(0);
461 fHType->GetXaxis()->SetBinLabel(1,"Low-flux");
462 fHType->GetXaxis()->SetBinLabel(2,"High-flux");
466 // This histogram disabled as it causes problems in the merge
467 fHWords = new TH1I("words", "Trigger words seen", 1, 0, 0);
468 fHWords->SetFillColor(kBlue+1);
469 fHWords->SetFillStyle(3001);
470 fHWords->SetStats(0);
471 fHWords->SetDirectory(0);
472 fHWords->SetBit(TH1::kCanRebin);
476 fHCent = new TH1F("cent", "Centrality", limits.GetSize()-1,limits.GetArray());
477 fHCent->SetFillColor(kBlue+1);
478 fHCent->SetFillStyle(3001);
480 fHCent->SetDirectory(0);
481 fHCent->SetXTitle("Centrality [%]");
482 fHCent->SetYTitle("Events");
485 fHCentVsQual = new TH2F("centVsQuality", "Quality vs Centrality",
486 5, 0, 5, limits.GetSize()-1, limits.GetArray());
487 fHCentVsQual->SetXTitle("Quality");
488 fHCentVsQual->SetYTitle("Centrality [%]");
489 fHCentVsQual->SetZTitle("Events");
490 fHCentVsQual->GetXaxis()->SetBinLabel(1, "OK");
491 fHCentVsQual->GetXaxis()->SetBinLabel(2, "Outside v_{z} cut");
492 fHCentVsQual->GetXaxis()->SetBinLabel(3, "V0 vs SPD outlier");
493 fHCentVsQual->GetXaxis()->SetBinLabel(4, "V0 vs TPC outlier");
494 fHCentVsQual->GetXaxis()->SetBinLabel(5, "V0 vs ZDC outlier");
495 fHCentVsQual->SetDirectory(0);
496 fList->Add(fHCentVsQual);
498 fHStatus = new TH1I("status", "Status", 7, 1, 8);
499 fHStatus->SetFillColor(kBlue+1);
500 fHStatus->SetFillStyle(3001);
501 fHStatus->SetStats(0);
502 fHStatus->SetDirectory(0);
503 TAxis* xAxis = fHStatus->GetXaxis();
504 xAxis->SetBinLabel(1, "OK");
505 xAxis->SetBinLabel(2, "No event");
506 xAxis->SetBinLabel(3, "No triggers");
507 xAxis->SetBinLabel(4, "No SPD");
508 xAxis->SetBinLabel(5, "No FMD");
509 xAxis->SetBinLabel(6, "No vertex");
510 xAxis->SetBinLabel(7, "Bad vertex");
511 fList->Add(fHStatus);
513 fHVtxStatus = new TH1I("vtxStatus","Vertex Status",
514 kNotVtxZ,kVtxOK,kNotVtxZ+1);
515 fHVtxStatus->SetFillColor(kGreen+1);
516 fHVtxStatus->SetFillStyle(3001);
517 fHVtxStatus->SetStats(0);
518 fHVtxStatus->SetDirectory(0);
519 xAxis = fHVtxStatus->GetXaxis();
520 xAxis->SetBinLabel(kVtxOK, "OK");
521 xAxis->SetBinLabel(kNoVtx, "None/bad status");
522 xAxis->SetBinLabel(kNoSPDVtx, "No SPD/bad status");
523 xAxis->SetBinLabel(kFewContrib, "N_{contrib} <= 0");
524 xAxis->SetBinLabel(kUncertain, Form("#delta z > %4.2f", fMaxVzErr));
525 xAxis->SetBinLabel(kNotVtxZ, "Not Z vertexer");
526 fList->Add(fHVtxStatus);
528 fHTrgStatus = new TH1I("trgStatus", "Trigger Status",
529 kOther, kNoTrgWords, kOther+1);
530 fHTrgStatus->SetFillColor(kMagenta+1);
531 fHTrgStatus->SetFillStyle(3001);
532 fHTrgStatus->SetStats(0);
533 fHTrgStatus->SetDirectory(0);
534 xAxis = fHTrgStatus->GetXaxis();
535 xAxis->SetBinLabel(kNoTrgWords, "No words");
536 xAxis->SetBinLabel(kPP2760Fast, "FAST in pp@#sqrt{s}=2.76TeV");
537 xAxis->SetBinLabel(kMUON, "Muon trigger");
538 xAxis->SetBinLabel(kTriggered, "Triggered");
539 xAxis->SetBinLabel(kMinBias, "CINT1 (V0A||V0C||FASTOR)");
540 xAxis->SetBinLabel(kMinBiasNoSPD, "CINT5 (V0A||V0C)");
541 xAxis->SetBinLabel(kV0AndTrg, "CINT7 (V0A&&V0C)");
542 xAxis->SetBinLabel(kHighMult, "N>>0");
543 xAxis->SetBinLabel(kCentral, "Central");
544 xAxis->SetBinLabel(kSemiCentral, "Semi-central");
545 xAxis->SetBinLabel(kDiffractive, "Diffractive");
546 xAxis->SetBinLabel(kUser, "User");
547 xAxis->SetBinLabel(kOther, "Other");
548 fList->Add(fHTrgStatus);
550 if (fUseDisplacedVertices) fDisplacedVertex.SetupForData(fList, "", false);
553 //____________________________________________________________________
555 AliFMDEventInspector::StoreInformation()
557 // Write TNamed objects to output list containing information about
558 // the running conditions
559 DGUARD(fDebug,2,"Store information from AliFMDEventInspector");
563 fList->Add(AliForwardUtil::MakeParameter("sys", fCollisionSystem));
564 fList->Add(AliForwardUtil::MakeParameter("sNN", fEnergy));
565 fList->Add(AliForwardUtil::MakeParameter("field", fField));
566 fList->Add(AliForwardUtil::MakeParameter("runNo", fRunNumber));
567 fList->Add(AliForwardUtil::MakeParameter("lowFlux", fLowFluxCut));
568 fList->Add(AliForwardUtil::MakeParameter("fpVtx",fUseFirstPhysicsVertex));
569 fList->Add(AliForwardUtil::MakeParameter("v0and",fUseV0AND));
570 fList->Add(AliForwardUtil::MakeParameter("nPileUp", fMinPileupContrib));
571 fList->Add(AliForwardUtil::MakeParameter("dPileup", fMinPileupDistance));
572 fList->Add(AliForwardUtil::MakeParameter("satellite", fUseDisplacedVertices));
573 fList->Add(AliForwardUtil::MakeParameter("alirootRev",
574 AliForwardUtil::AliROOTRevision()));
575 fList->Add(AliForwardUtil::MakeParameter("alirootBranch",
576 AliForwardUtil::AliROOTBranch()));
577 fList->Add(AliForwardUtil::MakeParameter("mc", fMC));
581 //____________________________________________________________________
583 AliFMDEventInspector::StoreProduction()
587 AliAnalysisManager *mgr=AliAnalysisManager::GetAnalysisManager();
588 AliVEventHandler *inputHandler=mgr->GetInputEventHandler();
590 AliWarning("Got no input handler");
593 TList *uiList = inputHandler->GetUserInfo();
595 AliWarning("Got no user list from input tree");
599 AliProdInfo p(uiList);
601 if (p.GetAlirootSvnVersion() <= 0) return;
603 // Make our output list
604 TList* out = new TList;
606 out->SetName("production");
607 // out->SetTitle("ESD production details");
610 TString period = p.GetLHCPeriod();
611 // TString aliROOTVersion = p.GetAlirootVersion();
612 fProdSVN = p.GetAlirootSvnVersion();
613 // TString rootVersion = p.GetRootVersion();
614 Int_t rootSVN = p.GetRootSvnVersion();
615 fProdPass = p.GetRecoPass();
618 TObjArray* pp = TPRegexp("LHC([0-9]+)([a-z]+)").MatchS(period);
619 fProdYear = static_cast<TObjString*>(pp->At(1))->String().Atoi();
620 fProdLetter = static_cast<TObjString*>(pp->At(2))->String()[0];
623 out->Add(AliForwardUtil::MakeParameter("year", fProdYear));
624 out->Add(AliForwardUtil::MakeParameter("letter", Int_t(fProdLetter)));
625 out->Add(AliForwardUtil::MakeParameter("alirootSVN", fProdSVN));
626 out->Add(AliForwardUtil::MakeParameter("rootSVN", rootSVN));
627 out->Add(AliForwardUtil::MakeParameter("pass", fProdPass));
628 out->Add(AliForwardUtil::MakeParameter("mc", fProdMC));
634 //____________________________________________________________________
636 AliFMDEventInspector::CreateOutputObjects(TList* dir)
639 // Define the output histograms. These are put in a sub list of the
640 // passed list. The histograms are merged before the parent task calls
641 // AliAnalysisTaskSE::Terminate
643 // dir Directory to add to
645 DGUARD(fDebug,1,"Define output from AliFMDEventInspector");
647 fList->SetName(GetName());
652 //____________________________________________________________________
654 AliFMDEventInspector::Process(const AliESDEvent* event,
667 // triggers On return, the triggers fired
668 // lowFlux On return, true if the event is considered a low-flux
669 // event (according to the setting of fLowFluxCut)
670 // ivz On return, the found vertex bin (1-based). A zero
671 // means outside of the defined vertex range
672 // vz On return, the z position of the interaction
673 // cent On return, the centrality - if not available < 0
676 // 0 (or kOk) on success, otherwise a bit mask of error codes
678 DGUARD(fDebug,1,"Process event in AliFMDEventInspector");
679 // --- Check that we have an event ---------------------------------
681 AliWarning("No ESD event found for input event");
686 // --- Process satellite event information is requested ------------
687 if (fUseDisplacedVertices) {
688 if (!fDisplacedVertex.Process(event))
689 AliWarning("Failed to process satellite event");
692 // --- Read trigger information from the ESD and store in AOD object
693 if (!ReadTriggers(*event, triggers, nClusters)) {
695 AliWarning("Failed to read triggers from ESD"); }
700 // --- Check if this is a high-flux event --------------------------
701 const AliMultiplicity* testmult = event->GetMultiplicity();
704 AliWarning("No central multiplicity object found"); }
707 lowFlux = testmult->GetNumberOfTracklets() < fLowFluxCut;
709 fHType->Fill(lowFlux ? 0 : 1);
711 // --- Get the interaction point -----------------------------------
712 Bool_t vzOk = ReadVertex(*event, ip);
713 fHEventsTr->Fill(ip.Z());
716 AliWarning("Failed to read vertex from ESD"); }
721 // --- Read centrality information
724 if (!ReadCentrality(*event, cent, qual)) {
726 AliWarning("Failed to get centrality");
728 // --- check centrality cut
730 if(fMinCent > -0.0001 && cent < fMinCent) return kNoEvent;
731 if(fMaxCent > -0.0001 && cent > fMaxCent) return kNoEvent;
733 if (qual == 0) fHCentVsQual->Fill(0., cent);
735 for (UShort_t i = 0; i < 4; i++)
736 if (qual & (1 << i)) fHCentVsQual->Fill(Double_t(i+1), cent);
740 fHEventsTrVtx->Fill(ip.Z());
742 // --- Get the vertex bin ------------------------------------------
743 ivz = fVtxAxis.FindBin(ip.Z());
744 if (ivz <= 0 || ivz > fVtxAxis.GetNbins()) {
746 AliWarning(Form("Vertex @ %f outside of range [%f,%f]",
747 ip.Z(), fVtxAxis.GetXmin(), fVtxAxis.GetXmax()));
753 fHEventsAccepted->Fill(ip.Z());
754 fHEventsAcceptedXY->Fill(ip.X(),ip.Y());
756 // --- Check the FMD ESD data --------------------------------------
757 if (!event->GetFMDData()) {
759 AliWarning("No FMD data found in ESD"); }
768 //____________________________________________________________________
770 AliFMDEventInspector::ReadCentrality(const AliESDEvent& esd,
772 UShort_t& qual) const
775 // Read centrality from event
779 // cent On return, the centrality or negative if not found
782 // False on error, true otherwise
784 DGUARD(fDebug,2,"Read the centrality in AliFMDEventInspector");
788 AliCentrality* centObj = const_cast<AliESDEvent&>(esd).GetCentrality();
790 cent = centObj->GetCentralityPercentile(fCentMethod);
791 qual = centObj->GetQuality();
794 // We overwrite with satellite events, so we can be sure to get the
795 // centrality determination from the satellite vertex selection
796 if (fUseDisplacedVertices && fDisplacedVertex.IsSatellite()) {
797 cent = fDisplacedVertex.GetCentralityPercentile();
804 //____________________________________________________________________
806 AliFMDEventInspector::CheckpAExtraV0(const AliESDEvent& esd) const
808 if (fCollisionSystem != AliForwardUtil::kPPb) return true;
810 AliVVZERO* esdV0 = esd.GetVZEROData();
811 if ((esdV0->GetV0ADecision()!=1) || (esdV0->GetV0CDecision()!=1))
816 //____________________________________________________________________
818 AliFMDEventInspector::ReadTriggers(const AliESDEvent& esd, UInt_t& triggers,
822 // Read the trigger information from the ESD event
826 // triggers On return, contains the trigger bits
829 // @c true on success, @c false otherwise
831 DGUARD(fDebug,2,"Read the triggers in AliFMDEventInspector");
834 // Get the analysis manager - should always be there
835 AliAnalysisManager* am = AliAnalysisManager::GetAnalysisManager();
836 DMSG(fDebug,10,"Got analysis manager %p", am);
838 AliWarning("No analysis manager defined!");
842 // Get the input handler - should always be there
843 AliInputEventHandler* ih =
844 static_cast<AliInputEventHandler*>(am->GetInputEventHandler());
845 DMSG(fDebug,10,"Got input handler %p", ih);
847 AliWarning("No input handler");
851 // Check if this is a collision candidate (MB)
853 // Historic remark: Note, that we should use the value cached in the
854 // input handler rather than calling IsCollisionCandiate directly
855 // on the AliPhysicsSelection obejct. If we called the latter
856 // then the AliPhysicsSelection object would overcount by a factor
858 UInt_t trgMask = ih->IsEventSelected();
859 Bool_t offline = trgMask;
860 Bool_t fastonly = (trgMask & AliVEvent::kFastOnly);
861 TString trigStr = esd.GetFiredTriggerClasses();
863 if (trigStr.IsNull()) fHTrgStatus->Fill(kNoTrgWords);
864 if (fHWords) fHWords->Fill(trigStr.Data(), 1);
866 if(fUseDisplacedVertices) {
867 DMSG(fDebug,3,"Using displaced vertex stuff");
868 // if (TMath::Abs(fDisplacedVertex.GetVertexZ()) >= 999) offline = false;
869 if (fDisplacedVertex.IsSatellite())
870 triggers |= AliAODForwardMult::kSatellite;
873 if (CheckFastPartition(fastonly)) {
874 fHTrgStatus->Fill(kPP2760Fast);
878 if (offline && CheckCosmics(trigStr)) {
879 fHTrgStatus->Fill(kMUON);
882 if (offline) fHTrgStatus->Fill(kTriggered);
884 if (trgMask & AliVEvent::kMB) f += fHTrgStatus->Fill(kMinBias);
885 if (trgMask & AliVEvent::kCINT5) f += fHTrgStatus->Fill(kMinBiasNoSPD);
886 if (trgMask & AliVEvent::kINT7) f += fHTrgStatus->Fill(kV0AndTrg);
887 if (trgMask & AliVEvent::kHighMult) f += fHTrgStatus->Fill(kHighMult);
888 if (trgMask & AliVEvent::kCentral) f += fHTrgStatus->Fill(kCentral);
889 if (trgMask & AliVEvent::kSemiCentral) f += fHTrgStatus->Fill(kSemiCentral);
890 if (trgMask & AliVEvent::kDG5) f += fHTrgStatus->Fill(kDiffractive);
891 if (trgMask & AliVEvent::kUserDefined) f += fHTrgStatus->Fill(kUser);
892 if (f <= 0) fHTrgStatus->Fill(kOther);
894 // if (!CheckpAExtraV0(esd)) offline = false;
896 DMSG(fDebug,2,"Event is %striggered by off-line", offline ? "" : "NOT ");
898 if (offline) triggers |= AliAODForwardMult::kOffline;
899 // Only flag as in-elastic if a min-bias trigger is here
900 if (trgMask & AliVEvent::kMB) {
901 triggers |= AliAODForwardMult::kInel;
902 CheckINELGT0(esd, nClusters, triggers);
905 CheckNSD(esd,triggers);
906 CheckPileup(esd, triggers);
907 CheckEmpty(trigStr, triggers);
908 // if (CheckPileup(esd, triggers)) fHTriggers->Fill(kPileUp+.5);
909 // if (CheckEmpty(trigStr, triggers)) fHTriggers->Fill(kEmpty+.5);
911 CheckWords(esd, triggers);
913 #define TEST_TRIG_BIN(RET,BIN,TRIGGERS) \
914 do { switch (BIN) { \
915 case kInel: RET = triggers & AliAODForwardMult::kInel; break; \
916 case kInelGt0: RET = triggers & AliAODForwardMult::kInelGt0; break; \
917 case kNSD: RET = triggers & AliAODForwardMult::kNSD; break; \
918 case kV0AND: RET = triggers & AliAODForwardMult::kV0AND; break; \
919 case kEmpty: RET = triggers & AliAODForwardMult::kEmpty; break; \
920 case kA: RET = triggers & AliAODForwardMult::kA; break; \
921 case kB: RET = triggers & AliAODForwardMult::kB; break; \
922 case kC: RET = triggers & AliAODForwardMult::kC; break; \
923 case kE: RET = triggers & AliAODForwardMult::kE; break; \
924 case kPileUp: RET = triggers & AliAODForwardMult::kPileUp; break; \
925 case kMCNSD: RET = triggers & AliAODForwardMult::kMCNSD; break; \
926 case kSatellite:RET = triggers & AliAODForwardMult::kSatellite; break; \
927 case kOffline: RET = triggers & AliAODForwardMult::kOffline; break; \
928 default: RET = false; } } while(false)
931 AliWarning("Histogram of triggers not defined - has init been called");
935 for (Int_t i = 0; i < kOffline+1; i++) {
937 TEST_TRIG_BIN(hasX, i, triggers);
939 fHTriggers->Fill(i+.5);
940 for (Int_t j = 0; j < kOffline+1; j++) {
942 TEST_TRIG_BIN(hasY, j, triggers);
945 fHTriggerCorr->Fill(i+.5, j+.5);
951 //____________________________________________________________________
953 AliFMDEventInspector::CheckFastPartition(bool fastonly) const
955 // For the 2.76 TeV p+p run, the FMD ran in the slow partition
956 // so it received no triggers from the fast partition. Therefore
957 // the fast triggers are removed here but not for MC where all
958 // triggers are fast.
959 if (TMath::Abs(fEnergy - 2750.) > 20) return false;
960 if (fCollisionSystem != AliForwardUtil::kPP) return false;
961 if (fMC) return false; // All MC events for pp @ 2.76TeV are `fast'
963 DMSG(fDebug,1,"Fast trigger in pp @ sqrt(s)=2.76TeV removed");
968 //____________________________________________________________________
970 AliFMDEventInspector::CheckCosmics(const TString& trigStr) const
972 // MUON triggers are not strictly minimum bias (MB) so they are
974 if(trigStr.Contains("CMUS1")) {
975 DMSG(fDebug,1,"Cosmic trigger ins't min-bias, removed");
981 //____________________________________________________________________
983 AliFMDEventInspector::CheckINELGT0(const AliESDEvent& esd,
985 UInt_t& triggers) const
989 // If this is inel, see if we have a tracklet
990 const AliMultiplicity* spdmult = esd.GetMultiplicity();
992 AliWarning("No SPD multiplicity");
996 // Check if we have one or more tracklets
997 // in the range -1 < eta < 1 to set the INEL>0
1000 // Also count tracklets as a single cluster
1001 Int_t n = spdmult->GetNumberOfTracklets();
1002 for (Int_t j = 0; j < n; j++) {
1003 if(TMath::Abs(spdmult->GetEta(j)) < 1) nClusters++;
1005 // If we at this point had non-zero nClusters, it's INEL>0
1006 if (nClusters > 0) triggers |= AliAODForwardMult::kInelGt0;
1008 // Loop over single clusters
1009 n = spdmult->GetNumberOfSingleClusters();
1010 for (Int_t j = 0; j < n; j++) {
1011 Double_t eta = -TMath::Log(TMath::Tan(spdmult->GetThetaSingle(j)/2.));
1012 if (TMath::Abs(eta) < 1) nClusters++;
1014 if (nClusters > 0) triggers |= AliAODForwardMult::kNClusterGt0;
1016 return triggers & AliAODForwardMult::kNClusterGt0;
1019 //____________________________________________________________________
1021 AliFMDEventInspector::CheckNSD(const AliESDEvent& esd, UInt_t& triggers) const
1023 // Analyse some trigger stuff
1024 AliTriggerAnalysis ta;
1025 if (ta.IsOfflineTriggerFired(&esd, AliTriggerAnalysis::kV0AND)) {
1026 triggers |= AliAODForwardMult::kV0AND;
1028 triggers |= AliAODForwardMult::kNSD;
1030 if (ta.IsOfflineTriggerFired(&esd, AliTriggerAnalysis::kNSD1))
1031 triggers |= AliAODForwardMult::kNSD;
1032 return triggers & AliAODForwardMult::kNSD;
1034 //____________________________________________________________________
1036 AliFMDEventInspector::CheckPileup(const AliESDEvent& esd,
1037 UInt_t& triggers) const
1039 // Check for multiple vertices (pile-up) with at least 3
1040 // contributors and at least 0.8cm from the primary vertex
1041 // if(fCollisionSystem != AliForwardUtil::kPP) return false;
1043 // Check for standard SPD pile-up
1044 Bool_t spdPileup = esd.IsPileupFromSPD(fMinPileupContrib,fMinPileupDistance);
1046 // Check for multi-vertex pileup
1047 Bool_t mvPileup = false; // CheckMultiVertex(esd);
1049 // Check for out-of-bunch pileup
1050 Bool_t outPileup = (esd.GetHeader()->GetIRInt2ClosestInteractionMap() != 0 ||
1051 esd.GetHeader()->GetIRInt1ClosestInteractionMap() != 0);
1054 Bool_t pileup = spdPileup || mvPileup || outPileup;
1055 if (pileup) triggers |= AliAODForwardMult::kPileUp;
1059 //____________________________________________________________________
1061 AliFMDEventInspector::CheckMultiVertex(const AliESDEvent& esd,
1062 Bool_t checkOtherBC) const
1064 // Adapted from AliAnalysisUtils
1067 const Double_t maxChi2nu = 5;
1069 // Number of vertices
1070 Int_t n = esd.GetNumberOfPileupVerticesTracks();
1072 // No additional vertices from tracks -> no pileup
1076 const AliESDVertex* primary = esd.GetPrimaryVertexTracks();
1077 if (primary->GetStatus() != 1)
1078 // No good primary vertex, but many candidates -> pileup
1081 // Bunch crossing number
1082 Int_t bcPrimary = primary->GetBC();
1084 for (Int_t i = 0; i < n; i++) {
1085 const AliESDVertex* other = esd.GetPileupVertexTracks(i);
1087 if (other->GetNContributors() < fMinPileupContrib)
1088 // Not enough contributors to this vertex
1091 if (other->GetChi2perNDF() > maxChi2nu)
1092 // Poorly determined vertex
1095 Int_t bcOther = other->GetBC();
1096 if (bcOther != AliVTrack::kTOFBCNA && TMath::Abs(bcOther-bcPrimary) > 2)
1097 // Pile-up from other BC
1100 // Calculate the distance
1102 Double_t dx = primary->GetX() - other->GetX();
1103 Double_t dy = primary->GetY() - other->GetY();
1104 Double_t dz = primary->GetZ() - other->GetZ();
1105 Double_t covPrimary[6], covOther[6];
1106 primary->GetCovarianceMatrix(covPrimary);
1107 other->GetCovarianceMatrix(covOther);
1109 v(0,0) = covPrimary[0] + covOther[0]; // diagonal
1110 v(1,1) = covPrimary[2] + covOther[2]; // diagonal
1111 v(2,2) = covPrimary[5] + covOther[5]; // diagonal
1112 v(1,0) = v(0,1) = covPrimary[1]+covOther[1]; // Band
1113 v(0,2) = v(1,2) = v(2,0) = v(2,1) = 0; // Off-diagonal+band
1117 // Question if kStatus bit is every set after InvertFast?
1119 d = (v(0,0) * dx * dx + v(1,1) * dy * dy + v(2,2) * dz * dz +
1120 2 * (v(0,1) * dx * dy + v(0,2) * dx * dz + v(1,2) * dy * dz));
1122 if (d < 0 || TMath::Sqrt(d) < fMinPileupDistance)
1123 // Bad distance, or not fare enough from each other
1126 // Well separated vertices -> pileup
1132 //____________________________________________________________________
1134 AliFMDEventInspector::CheckEmpty(const TString& trigStr, UInt_t& triggers) const
1136 if (trigStr.Contains("CBEAMB-ABCE-NOPF-ALL")) {
1137 triggers |= AliAODForwardMult::kEmpty;
1142 //____________________________________________________________________
1144 AliFMDEventInspector::CheckWords(const AliESDEvent& esd, UInt_t& triggers) const
1147 TIter nextColl(&fCollWords);
1148 while ((word = nextColl())) {
1149 DMSG(fDebug,10,"Checking if %s trigger %s is fired",
1150 word->GetTitle(), word->GetName());
1151 if (!esd.IsTriggerClassFired(word->GetName())) continue;
1153 TString beamSide = word->GetTitle();
1154 DMSG(fDebug,10,"Found it - this is a %s trigger", beamSide.Data());
1156 if (!beamSide.EqualTo("B")) continue;
1157 triggers |= AliAODForwardMult::kB;
1158 break; // No more to do here
1160 TIter nextBg(&fBgWords);
1161 UInt_t all = (AliAODForwardMult::kA |
1162 AliAODForwardMult::kC |
1163 AliAODForwardMult::kE);
1164 while ((word = nextBg())) {
1165 DMSG(fDebug,10,"Checking if %s trigger %s is fired",
1166 word->GetTitle(), word->GetName());
1167 if (!esd.IsTriggerClassFired(word->GetName())) continue;
1169 TString beamSide = word->GetTitle();
1170 DMSG(fDebug,10,"Found it - this is a %s trigger", beamSide.Data());
1172 if (beamSide.Contains("A")) triggers |= AliAODForwardMult::kA;
1173 if (beamSide.Contains("C")) triggers |= AliAODForwardMult::kC;
1174 if (beamSide.Contains("E")) triggers |= AliAODForwardMult::kE;
1176 if ((triggers & all) == all) break; // No more to do
1182 //____________________________________________________________________
1184 AliFMDEventInspector::ReadVertex(const AliESDEvent& esd, TVector3& ip)
1187 // Read the vertex information from the ESD event
1191 // vz On return, the vertex Z position
1194 // @c true on success, @c false otherwise
1196 DGUARD(fDebug,2,"Read the vertex in AliFMDEventInspector");
1197 ip.SetXYZ(1024, 1024, 0);
1199 EVtxStatus s = kNoVtx;
1200 if (fUseDisplacedVertices && fDisplacedVertex.IsSatellite()) {
1202 ip.SetZ(fDisplacedVertex.GetVertexZ());
1204 else if (fUseFirstPhysicsVertex)
1205 s = CheckPWGUDVertex(esd, ip);
1206 else if (fUsepA2012Vertex)
1207 s = CheckpA2012Vertex(esd,ip);
1209 s = CheckVertex(esd, ip);
1211 fHVtxStatus->Fill(s);
1216 //____________________________________________________________________
1217 AliFMDEventInspector::EVtxStatus
1218 AliFMDEventInspector::CheckPWGUDVertex(const AliESDEvent& esd,
1221 // This is the code used by the 1st physics people
1222 const AliESDVertex* vertex = esd.GetPrimaryVertex();
1223 if (!vertex || !vertex->GetStatus()) {
1224 DMSG(fDebug,2,"No primary vertex (%p) or bad status %d",
1225 vertex, (vertex ? vertex->GetStatus() : -1));
1228 const AliESDVertex* vertexSPD = esd.GetPrimaryVertexSPD();
1229 if (!vertexSPD || !vertexSPD->GetStatus()) {
1230 DMSG(fDebug,2,"No primary SPD vertex (%p) or bad status %d",
1231 vertexSPD, (vertexSPD ? vertexSPD->GetStatus() : -1));
1235 // if vertex is from SPD vertexZ, require more stringent cuts
1236 if (vertex->IsFromVertexerZ()) {
1237 if (vertex->GetDispersion() > fMaxVzErr ||
1238 vertex->GetZRes() > 1.25 * fMaxVzErr) {
1239 DMSG(fDebug,2,"Dispersion %f > %f or resolution %f > %f",
1240 vertex->GetDispersion(), fMaxVzErr,
1241 vertex->GetZRes(), 1.25 * fMaxVzErr);
1245 ip.SetZ(vertex->GetZ());
1247 if(!vertex->IsFromVertexerZ()) {
1248 ip.SetX(vertex->GetX());
1249 ip.SetY(vertex->GetY());
1253 //____________________________________________________________________
1254 AliFMDEventInspector::EVtxStatus
1255 AliFMDEventInspector::CheckpA2012Vertex(const AliESDEvent& esd,
1258 const AliESDVertex *vertex = esd.GetPrimaryVertexSPD();
1259 if (!vertex) return kNoSPDVtx;
1260 if (vertex->GetNContributors() <= 0) return kFewContrib;
1262 TString vtxTyp = vertex->GetTitle();
1263 if (vtxTyp.Contains("vertexer: Z")) return kNotVtxZ;
1265 if (vertex->GetDispersion() >= 0.04 || vertex->GetZRes()>=0.25)
1268 ip.SetX(vertex->GetX());
1269 ip.SetY(vertex->GetY());
1270 ip.SetZ(vertex->GetZ());
1275 //____________________________________________________________________
1276 AliFMDEventInspector::EVtxStatus
1277 AliFMDEventInspector::CheckVertex(const AliESDEvent& esd,
1280 // Use standard SPD vertex (perhaps preferable for Pb+Pb)
1282 const AliESDVertex* vertex = esd.GetPrimaryVertexSPD();
1285 AliWarning("No SPD vertex found in ESD"); }
1289 // #if 0 // Check disabled - seem to kill a lot of PbPb events
1290 // Check that enough tracklets contributed
1291 if(vertex->GetNContributors() <= 0) {
1292 DMSG(fDebug,2,"Number of contributors to vertex is %d<=0",
1293 vertex->GetNContributors());
1299 // Check that the uncertainty isn't too large
1300 if (vertex->GetZRes() > fMaxVzErr) {
1301 DMSG(fDebug,2,"Uncertaintity in Z of vertex is too large %f > %f",
1302 vertex->GetZRes(), fMaxVzErr);
1306 // Get the z coordiante
1307 ip.SetZ(vertex->GetZ());
1308 const AliESDVertex* vertexXY = esd.GetPrimaryVertex();
1311 if(!vertexXY->IsFromVertexerZ()) {
1312 ip.SetX(vertexXY->GetX());
1313 ip.SetY(vertexXY->GetY());
1318 //____________________________________________________________________
1320 AliFMDEventInspector::ReadRunDetails(const AliESDEvent* esd)
1323 // Read the collision system, collision energy, and L3 field setting
1327 // esd ESD to get information from
1330 // true on success, false
1332 // AliInfo(Form("Parameters from 1st ESD event: cms=%s, sNN=%f, field=%f",
1333 // esd->GetBeamType(), 2*esd->GetBeamEnergy(),
1334 // esd->GetMagneticField()));
1335 DGUARD(fDebug,2,"Read the run details in AliFMDEventInspector");
1336 const char* sys = esd->GetBeamType();
1337 Float_t cms = 2 * esd->GetBeamEnergy();
1338 Float_t fld = esd->GetMagneticField();
1339 fCollisionSystem = AliForwardUtil::ParseCollisionSystem(sys);
1340 fEnergy = AliForwardUtil::ParseCenterOfMassEnergy(fCollisionSystem,
1342 fField = AliForwardUtil::ParseMagneticField(fld);
1343 fRunNumber = esd->GetRunNumber();
1346 if (fCollisionSystem == AliForwardUtil::kUnknown) {
1347 AliWarningF("Unknown collision system: %s - please check", sys);
1351 AliWarningF("Unknown CMS energy: %f (%d) - please check", cms, fEnergy);
1354 if (TMath::Abs(fField) > 10) {
1355 AliWarningF("Unknown L3 field setting: %f (%d) - please check", fld,fField);
1363 //____________________________________________________________________
1365 AliFMDEventInspector::CodeString(UInt_t code)
1369 if (code & kNoEvent) s.Append("NOEVENT ");
1370 if (code & kNoTriggers) s.Append("NOTRIGGERS ");
1371 if (code & kNoSPD) s.Append("NOSPD ");
1372 if (code & kNoFMD) s.Append("NOFMD ");
1373 if (code & kNoVertex) s.Append("NOVERTEX ");
1374 if (code & kBadVertex) s.Append("BADVERTEX ");
1377 #define PF(N,V,...) \
1378 AliForwardUtil::PrintField(N,V, ## __VA_ARGS__)
1379 #define PFB(N,FLAG) \
1381 AliForwardUtil::PrintName(N); \
1382 std::cout << std::boolalpha << (FLAG) << std::noboolalpha << std::endl; \
1384 #define PFV(N,VALUE) \
1386 AliForwardUtil::PrintName(N); \
1387 std::cout << (VALUE) << std::endl; } while(false)
1389 //____________________________________________________________________
1391 AliFMDEventInspector::Print(Option_t*) const
1394 // Print information
1398 AliForwardUtil::PrintTask(*this);
1399 TString sNN(AliForwardUtil::CenterOfMassEnergyString(fEnergy));
1400 sNN.Strip(TString::kBoth, '0');
1401 sNN.ReplaceAll("GeV", " GeV");
1402 TString field(AliForwardUtil::MagneticFieldString(fField));
1403 field.ReplaceAll("p", "+");
1404 field.ReplaceAll("m", "-");
1405 field.ReplaceAll("kG", " kG");
1407 gROOT->IncreaseDirLevel();
1408 PFV("Production", "");
1409 gROOT->IncreaseDirLevel();
1410 PF("Period", "LHC%02d%c", fProdYear, fProdLetter);
1411 PFB("MC anchor", fProdMC);
1412 PFV("AliROOT Revision", fProdSVN);
1413 gROOT->DecreaseDirLevel();
1414 PFV("Vertex bins", fVtxAxis.GetNbins());
1415 PF("Vertex Range", "[%+6.1f,%+6.1f]", fVtxAxis.GetXmin(), fVtxAxis.GetXmax());
1416 PFV("Low flux cut", fLowFluxCut );
1417 PFV("Max(delta v_z)", fMaxVzErr );
1418 PFV("Min(nContrib_pileup)", fMinPileupContrib );
1419 PFV("Min(v-pileup)", fMinPileupDistance );
1420 PFV("System", AliForwardUtil::CollisionSystemString(fCollisionSystem));
1421 PFV("CMS energy per nucleon", sNN);
1422 PFV("Field", field);
1423 PFB("Satellite events", fUseDisplacedVertices);
1424 PFB("Use 2012 pA vertex", fUsepA2012Vertex );
1425 PFB("Use PWG-UD vertex", fUseFirstPhysicsVertex);
1426 PFB("Simulation input", fMC );
1427 PFV("Centrality method", fCentMethod);
1428 PFV("Centrality axis", (!fCentAxis ? "none" : ""));
1429 if (!fCentAxis) {return; }
1430 Int_t nBin = fCentAxis->GetNbins();
1431 for (Int_t i = 0; i < nBin; i++) {
1432 if (i != 0 && (i % 10) == 0) std::cout << '\n';
1433 if ((i % 10) == 0) std::cout << " ";
1434 std::cout << std::setw(5) << fCentAxis->GetBinLowEdge(i+1) << '-';
1436 std::cout << std::setw(5) << fCentAxis->GetBinUpEdge(nBin) << std::endl;
1437 gROOT->DecreaseDirLevel();