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 "AliFMDMCEventInspector.h"
19 #include "AliAODForwardMult.h"
20 #include "AliForwardUtil.h"
21 #include "AliCentrality.h"
22 #include "AliESDEvent.h"
23 #include "AliMCEvent.h"
25 #include "AliGenPythiaEventHeader.h"
26 #include "AliGenDPMjetEventHeader.h"
27 #include "AliGenHijingEventHeader.h"
28 // #include "AliGenHydjetEventHeader.h"
29 #include "AliGenEposEventHeader.h"
30 #include "AliGenHerwigEventHeader.h"
31 #include "AliGenGeVSimEventHeader.h"
32 #include "AliAnalysisManager.h"
33 #include "AliMCEventHandler.h"
34 #include "AliHeader.h"
37 #include <TParticle.h>
39 #include <TParameter.h>
41 //====================================================================
42 AliFMDMCEventInspector::AliFMDMCEventInspector()
43 : AliFMDEventInspector(),
62 //____________________________________________________________________
63 AliFMDMCEventInspector::AliFMDMCEventInspector(const char* /* name */)
64 : AliFMDEventInspector("fmdEventInspector"),
82 // name Name of object
87 //____________________________________________________________________
88 AliFMDMCEventInspector::AliFMDMCEventInspector(const AliFMDMCEventInspector& o)
89 : AliFMDEventInspector(o),
107 // o Object to copy from
111 //____________________________________________________________________
112 AliFMDMCEventInspector::~AliFMDMCEventInspector()
118 //____________________________________________________________________
119 AliFMDMCEventInspector&
120 AliFMDMCEventInspector::operator=(const AliFMDMCEventInspector& o)
123 // Assignement operator
126 // o Object to assign from
129 // Reference to this object
131 AliFMDEventInspector::operator=(o);
135 //____________________________________________________________________
137 AliFMDMCEventInspector::SetupForData(const TAxis& vtxAxis)
140 // Initialize the object
143 // vtxAxis Vertex axis in use
146 // We temporary disable the displaced vertices so we can initialize
147 // the routine ourselves.
148 Bool_t saveDisplaced = AllowDisplaced();
149 if (saveDisplaced) SetVertexMethod(kNormal);
150 AliFMDEventInspector::SetupForData(vtxAxis);
151 if (saveDisplaced) SetVertexMethod(kDisplaced);
156 Int_t nVtx = vtxAxis.GetNbins();
157 Double_t lVtx = vtxAxis.GetXmin();
158 Double_t hVtx = vtxAxis.GetXmax();
159 fHVertex = new TH1F("vertex", "True vertex distribution", nVtx, lVtx, hVtx);
160 fHVertex->SetXTitle("v_{z} [cm]");
161 fHVertex->SetYTitle("# of events");
162 fHVertex->SetFillColor(kGreen+1);
163 fHVertex->SetFillStyle(3001);
164 fHVertex->SetDirectory(0);
165 // fHVertex->Sumw2();
166 fList->Add(fHVertex);
168 fHPhiR = new TH1F("phiR", "Event plane", 120, 0, 2*TMath::Pi());
169 fHPhiR->SetXTitle("#Phi_{R} [radians]");
170 fHPhiR->SetYTitle("# of events");
171 fHPhiR->SetFillColor(kGreen+1);
172 fHPhiR->SetFillStyle(3001);
173 fHPhiR->SetDirectory(0);
176 fHB = new TH1F("b", "Impact parameter", 5*maxB, 0, maxB);
177 fHB->SetXTitle("b [fm]");
178 fHB->SetYTitle("# of events");
179 fHB->SetFillColor(kGreen+1);
180 fHB->SetFillStyle(3001);
181 fHB->SetDirectory(0);
184 fHMcC = static_cast<TH1F*>(fHCent->Clone("mcC"));
185 fHMcC->SetFillColor(kCyan+2);
186 fHMcC->SetDirectory(0);
189 fHBvsPart = new TH2F("bVsParticipants", "Impact parameter vs Participants",
190 5*maxB, 0, maxB, maxPart, -.5, maxPart-.5);
191 fHBvsPart->SetXTitle("b [fm]");
192 fHBvsPart->SetYTitle("# of participants");
193 fHBvsPart->SetZTitle("Events");
194 fHBvsPart->SetDirectory(0);
195 fList->Add(fHBvsPart);
197 fHBvsBin = new TH2F("bVsBinary", "Impact parameter vs Binary Collisions",
198 5*maxB, 0, maxB, maxBin, -.5, maxBin-.5);
199 fHBvsBin->SetXTitle("b [fm]");
200 fHBvsBin->SetYTitle("# of binary collisions");
201 fHBvsBin->SetZTitle("Events");
202 fHBvsBin->SetDirectory(0);
203 fList->Add(fHBvsBin);
205 fHBvsCent = new TH2F("bVsCentrality", "Impact parameter vs Centrality",
206 5*maxB, 0, maxB, fCentAxis->GetNbins(),
207 fCentAxis->GetXbins()->GetArray());
208 fHBvsCent->SetXTitle("b [fm]");
209 fHBvsCent->SetYTitle("Centrality [%]");
210 fHBvsCent->SetZTitle("Event");
211 fHBvsCent->SetDirectory(0);
212 fList->Add(fHBvsCent);
215 fHVzComp = new TH2F("vzComparison", "v_{z} truth vs reconstructed",
216 10*nVtx, lVtx, hVtx, 10*nVtx, lVtx, hVtx);
217 fHVzComp->SetXTitle("True v_{z} [cm]");
218 fHVzComp->SetYTitle("Reconstructed v_{z} [cm]");
219 fHVzComp->SetZTitle("Events");
220 fHVzComp->SetDirectory(0);
221 fList->Add(fHVzComp);
223 fHCentVsPart = new TH2F("centralityVsParticipans",
224 "# of participants vs Centrality",
225 maxPart, -.5, maxPart-.5, fCentAxis->GetNbins(),
226 fCentAxis->GetXbins()->GetArray());
227 fHCentVsPart->SetXTitle("Participants");
228 fHCentVsPart->SetYTitle("Centrality [%]");
229 fHCentVsPart->SetZTitle("Event");
230 fHCentVsPart->SetDirectory(0);
231 fList->Add(fHCentVsPart);
233 fHCentVsBin = new TH2F("centralityVsBinary",
234 "# of binary collisions vs Centrality",
235 maxBin, -.5, maxBin-.5, fCentAxis->GetNbins(),
236 fCentAxis->GetXbins()->GetArray());
237 fHCentVsBin->SetXTitle("Binary collisions");
238 fHCentVsBin->SetYTitle("Centrality [%]");
239 fHCentVsBin->SetZTitle("Event");
240 fHCentVsBin->SetDirectory(0);
241 fList->Add(fHCentVsBin);
243 Int_t nC = fHCent->GetNbinsX();
244 Double_t cL = fHCent->GetXaxis()->GetXmin();
245 Double_t cH = fHCent->GetXaxis()->GetXmax();
246 fHCentVsMcC = new TH2F("centralityRecoVsMC",
247 "Centrality from reconstruction vs MC derived",
248 nC, cL, cH, nC, cL, cH);
249 fHCentVsMcC->SetDirectory(0);
250 fHCentVsMcC->SetStats(0);
251 fHCentVsMcC->SetXTitle("Centralty from Reco [%]");
252 fHCentVsMcC->SetYTitle("Centralty derived from Impact Par. [%]");
253 fHCentVsMcC->SetZTitle("Events");
254 fList->Add(fHCentVsMcC);
256 if (AllowDisplaced()) fDisplacedVertex.SetupForData(fList, "", true);
261 TString& AppendField(TString& s, bool test, const char* f)
264 if (!s.IsNull()) s.Append(",");
270 //____________________________________________________________________
272 AliFMDMCEventInspector::ReadProductionDetails(AliMCEvent* event)
274 //Assign MC only triggers : True NSD etc.
275 AliHeader* header = event->Header();
276 AliGenEventHeader* genHeader = header->GenEventHeader();
277 AliCollisionGeometry* colGeometry =
278 dynamic_cast<AliCollisionGeometry*>(genHeader);
279 AliGenPythiaEventHeader* pythiaHeader =
280 dynamic_cast<AliGenPythiaEventHeader*>(genHeader);
281 AliGenDPMjetEventHeader* dpmHeader =
282 dynamic_cast<AliGenDPMjetEventHeader*>(genHeader);
283 AliGenGeVSimEventHeader* gevHeader =
284 dynamic_cast<AliGenGeVSimEventHeader*>(genHeader);
285 AliGenHerwigEventHeader* herwigHeader =
286 dynamic_cast<AliGenHerwigEventHeader*>(genHeader);
287 AliGenHijingEventHeader* hijingHeader =
288 dynamic_cast<AliGenHijingEventHeader*>(genHeader);
289 // AliGenHydjetEventHeader* hydjetHeader =
290 // dynamic_cast<AliGenHydjetEventHeader*>(genHeader);
291 AliGenEposEventHeader* eposHeader =
292 dynamic_cast<AliGenEposEventHeader*>(genHeader);
294 AppendField(fProduction, colGeometry, "Geometry");
295 AppendField(fProduction, pythiaHeader, "Pythia");
296 AppendField(fProduction, dpmHeader, "DPM");
297 AppendField(fProduction, gevHeader, "GevSim");
298 AppendField(fProduction, herwigHeader, "Herwig");
299 AppendField(fProduction, hijingHeader, "Hijing");
300 // AppendField(fProduction, hydjetHeader, "Hydjet");
301 AppendField(fProduction, eposHeader, "EPOS");
304 //____________________________________________________________________
306 AliFMDMCEventInspector::ProcessMC(AliMCEvent* event,
321 // triggers On return, the triggers fired
322 // ivz On return, the found vertex bin (1-based). A zero
323 // means outside of the defined vertex range
324 // vz On return, the z position of the interaction
325 // b On return, the impact parameter - < 0 if not available
326 // c On return, centrality estimate - < 0 if not available
327 // phiR On return, the event plane angle - < 0 if not available
330 // 0 (or kOk) on success, otherwise a bit mask of error codes
333 // Check that we have an event
335 AliWarning("No MC event found for input event");
339 //Assign MC only triggers : True NSD etc.
340 AliHeader* header = event->Header();
341 AliGenEventHeader* genHeader = header->GenEventHeader();
342 AliCollisionGeometry* colGeometry =
343 dynamic_cast<AliCollisionGeometry*>(genHeader);
344 AliGenPythiaEventHeader* pythiaHeader =
345 dynamic_cast<AliGenPythiaEventHeader*>(genHeader);
346 AliGenDPMjetEventHeader* dpmHeader =
347 dynamic_cast<AliGenDPMjetEventHeader*>(genHeader);
348 AliGenGeVSimEventHeader* gevHeader =
349 dynamic_cast<AliGenGeVSimEventHeader*>(genHeader);
350 AliGenHerwigEventHeader* herwigHeader =
351 dynamic_cast<AliGenHerwigEventHeader*>(genHeader);
352 // AliGenHijingEventHeader* hijingHeader =
353 // dynamic_cast<AliGenHijingEventHeader*>(genHeader);
354 // AliGenHydjetEventHeader* hydjetHeader =
355 // dynamic_cast<AliGenHydjetEventHeader*>(genHeader);
356 // AliGenEposEventHeader* eposHeader =
357 // dynamic_cast<AliGenEposEventHeader*>(genHeader);
359 // Check if this is a single diffractive event
361 Double_t phi = -1111;
369 b = colGeometry->ImpactParameter();
370 phi = colGeometry->ReactionPlaneAngle();
371 npart = (colGeometry->ProjectileParticipants() +
372 colGeometry->TargetParticipants());
373 nbin = colGeometry->NN();
375 if (fDebug && !colGeometry) {
376 AliWarningF("Collision header of class %s is not a CollisionHeader",
377 genHeader->ClassName());
381 Int_t pythiaType = pythiaHeader->ProcessType();
382 egSD = true; // We have SD flag in EG
383 if (pythiaType <= 100) {
387 if (pythiaType==92 || pythiaType==93) sd = true;
391 if (pythiaType==103 || pythiaType==104) sd = true;
393 b = pythiaHeader->GetImpactParameter();
394 npart = 2; // Always 2 protons
395 nbin = 1; // Always 1 binary collision
399 if (b < 3.5) c = 2.5; //0-5%
400 else if (b < 4.95) c = 7.5; //5-10%
401 else if (b < 6.98) c = 15; //10-20%
402 else if (b < 8.55) c = 25; //20-30%
403 else if (b < 9.88) c = 35; //30-40%
404 else if (b < 11.04) c = 45; //40-50%
405 else c = 55; //50-60%
407 // Updated 4th of November 2014 from
408 // cern.ch/twiki/bin/view/ALICE/CentStudies#Tables_with_centrality_bins_AN1
411 if (0.00 >= b && b < 1.57) { c=0.5; np=403.8; nc=1861; }
412 else if (1.57 >= b && b < 2.22) { c=1.5; np=393.6; nc=1766; }
413 else if (2.22 >= b && b < 2.71) { c=2.5; np=382.9; nc=1678; }
414 else if (2.71 >= b && b < 3.13) { c=3.5; np=372; nc=1597; }
415 else if (3.13 >= b && b < 3.50) { c=4.5; np=361.1; nc=1520; }
416 else if (3.50 >= b && b < 4.94) { c=7.5; np=329.4; nc=1316; }
417 else if (4.94 >= b && b < 6.05) { c=12.5; np=281.2; nc=1032; }
418 else if (6.05 >= b && b < 6.98) { c=17.5; np=239; nc=809.8; }
419 else if (6.98 >= b && b < 7.81) { c=22.5; np=202.1; nc=629.6; }
420 else if (7.81 >= b && b < 8.55) { c=27.5; np=169.5; nc=483.7; }
421 else if (8.55 >= b && b < 9.23) { c=32.5; np=141; nc=366.7; }
422 else if (9.23 >= b && b < 9.88) { c=37.5; np=116; nc=273.4; }
423 else if (9.88 >= b && b < 10.47) { c=42.5; np=94.11; nc=199.4; }
424 else if (10.47 >= b && b < 11.04) { c=47.5; np=75.3; nc=143.1; }
425 else if (11.04 >= b && b < 11.58) { c=52.5; np=59.24; nc=100.1; }
426 else if (11.58 >= b && b < 12.09) { c=57.5; np=45.58; nc=68.46; }
427 else if (12.09 >= b && b < 12.58) { c=62.5; np=34.33; nc=45.79; }
428 else if (12.58 >= b && b < 13.05) { c=67.5; np=25.21; nc=29.92; }
429 else if (13.05 >= b && b < 13.52) { c=72.5; np=17.96; nc=19.08; }
430 else if (13.52 >= b && b < 13.97) { c=77.5; np=12.58; nc=12.07; }
431 else if (13.97 >= b && b < 14.43) { c=82.5; np=8.812; nc=7.682; }
432 else if (14.43 >= b && b < 14.96) { c=87.5; np=6.158; nc=4.904; }
433 else if (14.96 >= b && b < 15.67) { c=92.5; np=4.376; nc=3.181; }
434 else if (15.67 >= b && b < 20.00) { c=97.5; np=3.064; nc=1.994; }
435 // Be careful to round off
436 if (npart <= 0) npart = Int_t(np+.5);
437 if (nbin <= 0) nbin = Int_t(nc+.5)/2;
440 if(dpmHeader) { // Also an AliCollisionGeometry
441 Int_t processType = dpmHeader->ProcessType();
442 egSD = true; // We have SD flag in EG
446 if (processType == 5 || processType == 6) sd = kTRUE;
448 // The below - or rather a different implementation with some
449 // errors - was proposed by Cvetan - I don't think it's right
452 // https://cern.ch/twiki/pub/ALICE/PAPaperCentrality/normalization.pdf
453 // https://cern.ch/twiki/bin/view/ALICE/PAMCProductionStudies
455 Int_t nsd1=0, nsd2=0, ndd=0;
456 Int_t npP = dpm->ProjectileParticipants();
457 Int_t npT = dpm->TargetParticipants();
458 // Get the numbeer of single and double diffractive participants
459 dpm->GetNDiffractive(nsd1,nsd2,ndd);
460 // Check if all partipants are single/double diffractive
461 if ((ndd == 0) && ((npP == nsd1) || (npT == nsd2))) sd = true;
462 else if (ndd == (npP + npT)) dd = true;
463 // Printf("Projectile: %3d (%3d) Target: %3d (%3d) DD: %3d Process: %d",
464 // npP, nsd1, npT, nsd2, ndd, type);
468 phi = gevHeader->GetEventPlane();
471 Int_t processType = herwigHeader->ProcessType();
472 egSD = true; // We have SD flag in EG
474 if (processType == 5 || processType == 6) sd = kTRUE;
475 npart = 2; // Always 2 protons
476 nbin = 1; // Always 1 binary collision
478 // if (hijingHeader) {
479 // b = hijingHeader->ImpactParameter();
480 // phi = hijingHeader->ReactionPlaneAngle();
482 // if (hydjetHeader) {
483 // b = hydjetHeader->ImpactParameter();
484 // phi = hydjetHeader->ReactionPlaneAngle();
487 // b = eposHeader->ImpactParameter();
488 // phi = eposHeader->ReactionPlaneAngle();
491 // Normalize event plane angle to [0,2pi]
492 if (phi <= -1111) phiR = -1;
495 if (phi < 0) phi += 2*TMath::Pi();
496 else if (phi > 2*TMath::Pi()) phi -= 2*TMath::Pi();
502 // Do a check on particles - but only if the EG does not give it or
503 // the impact parameter is large enough
504 if (!egSD && (b < 0 || b > 15)) sd = IsSingleDiffractive(event->Stack());
508 triggers |= AliAODForwardMult::kMCNSD;
509 fHTriggers->Fill(kMCNSD+0.5);
512 // Get the primary vertex from EG
514 genHeader->PrimaryVertex(vtx);
517 DMSG(fDebug, 2, "vz=%f, phiR=%f, b=%f, npart=%d, nbin=%d",
518 vz, phiR, b, npart, nbin);
524 fHBvsPart->Fill(b, npart);
525 fHBvsBin->Fill(b, nbin);
527 if(AllowDisplaced()) {
529 // Put the vertex at fixed locations
531 Double_t ratio = zvtx/37.5;
532 if(ratio > 0) ratio = ratio + 0.5;
533 if(ratio < 0) ratio = ratio - 0.5;
534 Int_t ratioInt = Int_t(ratio);
535 zvtx = 37.5*((Double_t)ratioInt);
536 if(TMath::Abs(zvtx) > 999)
539 if (!fDisplacedVertex.ProcessMC(event))
541 if (fDisplacedVertex.IsSatellite())
542 vz = fDisplacedVertex.GetVertexZ();
545 // Check for the vertex bin
546 ivz = fVtxAxis.FindBin(vz);
547 if (ivz <= 0 || ivz > fHEventsTr->GetXaxis()->GetNbins()) {
549 AliWarning(Form("Vertex @ %f outside of range [%f,%f]",
550 vz, fVtxAxis.GetXmin(), fVtxAxis.GetXmax())); }
558 //____________________________________________________________________
560 AliFMDMCEventInspector::ReadCentrality(const AliESDEvent& esd,
562 UShort_t& qual) const
565 // Read centrality from event
569 // cent On return, the centrality or negative if not found
572 // False on error, true otherwise
574 Bool_t ret = AliFMDEventInspector::ReadCentrality(esd, cent, qual);
576 AliCentrality* centObj = const_cast<AliESDEvent&>(esd).GetCentrality();
577 if (!centObj) return ret;
579 // For MC, we allow `bad' centrality selections
580 cent = centObj->GetCentralityPercentileUnchecked(fCentMethod);
585 //____________________________________________________________________
587 Double_t rapidity(TParticle* p, Double_t mass)
589 Double_t pt = p->Pt();
590 Double_t pz = p->Pz();
591 Double_t ee = TMath::Sqrt(pt*pt+pz*pz+mass*mass);
592 if (TMath::Abs(ee - TMath::Abs(pz)) < 1e-9) return TMath::Sign(1e30, pz);
593 return .5 * TMath::Log((ee + pz) / (ee - pz));
597 //____________________________________________________________________
599 AliFMDMCEventInspector::IsSingleDiffractive(AliStack* stack,
601 Double_t xiMax) const
603 // Re-implementation of AliPWG0Helper::IsHadronLevelSingleDiffrative
605 // This is re-implemented here to be indendent of the PWG0 library.
606 TParticle* p1 = 0; // Particle with least y
607 TParticle* p2 = 0; // Particle with largest y
608 Double_t y1 = 1e10; // y of p1
609 Double_t y2 = -1e10; // y of p2
611 // Loop over primaries
612 for (Int_t i = 0; i < stack->GetNprimary(); i++) {
613 TParticle* p = stack->Particle(i);
616 Int_t pdg = TMath::Abs(p->GetPdgCode());
617 Int_t c1 = p->GetFirstDaughter();
618 Int_t s = p->GetStatusCode();
619 Int_t mfl = Int_t(pdg/TMath::Power(10,Int_t(TMath::Log10(pdg))));
621 // Select final state charm and beauty
622 if (c1 > -1 || s != 1) mfl = 0;
624 // Check if this is a primary, pi0, Sigma0, ???, or most
625 // significant digit is larger than or equal to 4
626 if (!(stack->IsPhysicalPrimary(i) ||
632 Int_t m1 = p->GetFirstMother();
634 TParticle* pm1 = stack->Particle(m1);
635 Int_t mpdg = TMath::Abs(pm1->GetPdgCode());
636 // Check if mother is a p0, Simga0, or ???
637 if (mpdg == 111 || mpdg == 3124 || mpdg == 3212) continue;
640 // Calculate the rapidity of the particle
641 Double_t mm = (pdg != 3124 ? p->GetMass() : 1.5195);
642 Double_t yy = rapidity(p, mm);
644 // Check if the rapidity of this particle is further out than any
645 // of the preceding particles
655 if (!p1 || !p2) return false;
657 // Calculate rapidities assuming protons
658 y1 = TMath::Abs(rapidity(p1, 0.938));
659 y2 = TMath::Abs(rapidity(p2, 0.938));
661 // Check if both or just one is a proton
662 Int_t pdg1 = p1->GetPdgCode();
663 Int_t pdg2 = p2->GetPdgCode();
665 if (pdg1 == 2212 && pdg2 == 2212)
666 arm = (y1 > y2 ? 0 : 1);
667 else if (pdg1 == 2212)
669 else if (pdg2 == 2212)
675 Double_t m02s = (fEnergy > 0 ? 1 - 2 * p1->Energy() / fEnergy : 0);
676 Double_t m12s = (fEnergy > 0 ? 1 - 2 * p2->Energy() / fEnergy : 0);
678 if (arm == 0 && m02s > xiMin && m02s < xiMax) return true;
679 if (arm == 1 && m12s > xiMin && m12s < xiMax) return true;
684 //____________________________________________________________________
686 AliFMDMCEventInspector::CompareResults(Double_t vz, Double_t trueVz,
687 Double_t cent, Double_t mcC,
689 Int_t npart, Int_t nbin)
691 fHVzComp->Fill(trueVz, vz);
692 fHBvsCent->Fill(b, cent);
693 fHCentVsPart->Fill(npart, cent);
694 fHCentVsBin->Fill(nbin, cent);
695 fHCentVsMcC->Fill(cent, mcC);