3 #include "AliMultiplicityTask.h"
13 #include <TParticle.h>
16 #include <TObjString.h>
20 #include <AliESDVertex.h>
21 #include <AliESDEvent.h>
23 #include <AliHeader.h>
24 #include <AliGenEventHeader.h>
25 #include <AliMultiplicity.h>
26 #include <AliAnalysisManager.h>
27 #include <AliMCEventHandler.h>
28 #include <AliMCEvent.h>
29 #include <AliESDInputHandler.h>
31 #include "AliESDtrackCuts.h"
32 #include "AliPWG0Helper.h"
33 #include "dNdEta/AliMultiplicityCorrection.h"
34 #include "AliCorrection.h"
35 #include "AliCorrectionMatrix3D.h"
37 ClassImp(AliMultiplicityTask)
39 AliMultiplicityTask::AliMultiplicityTask(const char* opt) :
40 AliAnalysisTask("AliMultiplicityTask", ""),
43 fAnalysisMode(AliPWG0Helper::kSPD),
47 fSystSkipParticles(kFALSE),
48 fSelectProcessType(0),
54 // Constructor. Initialization of pointers
57 for (Int_t i = 0; i<4; i++)
58 fParticleCorrection[i] = 0;
60 // Define input and output slots here
61 DefineInput(0, TChain::Class());
62 DefineOutput(0, TList::Class());
65 AliMultiplicityTask::~AliMultiplicityTask()
71 // histograms are in the output list and deleted when the output
72 // list is deleted by the TSelector dtor
80 //________________________________________________________________________
81 void AliMultiplicityTask::ConnectInputData(Option_t *)
86 Printf("AliMultiplicityTask::ConnectInputData called");
88 TTree* tree = dynamic_cast<TTree*> (GetInputData(0));
90 Printf("ERROR: Could not read tree from input slot 0");
92 // Disable all branches and enable only the needed ones
93 //tree->SetBranchStatus("*", 0);
95 tree->SetBranchStatus("fTriggerMask", 1);
96 tree->SetBranchStatus("fSPDVertex*", 1);
98 if (fAnalysisMode == AliPWG0Helper::kSPD)
99 tree->SetBranchStatus("fSPDMult*", 1);
101 if (fAnalysisMode == AliPWG0Helper::kTPC || fAnalysisMode == AliPWG0Helper::kTPCITS) {
102 AliESDtrackCuts::EnableNeededBranches(tree);
103 tree->SetBranchStatus("fTracks.fLabel", 1);
106 AliESDInputHandler *esdH = dynamic_cast<AliESDInputHandler*> (AliAnalysisManager::GetAnalysisManager()->GetInputEventHandler());
109 Printf("ERROR: Could not get ESDInputHandler");
111 fESD = esdH->GetEvent();
115 void AliMultiplicityTask::CreateOutputObjects()
117 // create result objects and add to output list
122 fMultiplicity = new AliMultiplicityCorrection("Multiplicity", "Multiplicity");
123 fOutput->Add(fMultiplicity);
125 if (fOption.Contains("skip-particles"))
127 fSystSkipParticles = kTRUE;
128 AliInfo("WARNING: Systematic study enabled. Particles will be skipped.");
131 if (fOption.Contains("particle-efficiency"))
132 for (Int_t i = 0; i<4; i++)
134 fParticleCorrection[i] = new AliCorrection(Form("correction_%d", i), Form("correction_%d", i));
135 fOutput->Add(fParticleCorrection[i]);
138 if (fOption.Contains("only-process-type-nd"))
139 fSelectProcessType = 1;
141 if (fOption.Contains("only-process-type-sd"))
142 fSelectProcessType = 2;
144 if (fOption.Contains("only-process-type-dd"))
145 fSelectProcessType = 3;
147 if (fSelectProcessType != 0)
148 AliInfo(Form("WARNING: Systematic study enabled. Only considering process type %d", fSelectProcessType));
150 if (fOption.Contains("pt-spectrum-hist"))
152 TFile* file = TFile::Open("ptspectrum_fit.root");
155 TString subStr(fOption(fOption.Index("pt-spectrum")+17, 3));
156 TString histName(Form("ptspectrum_%s", subStr.Data()));
157 AliInfo(Form("Pt-Spectrum modification. Using %s.", histName.Data()));
158 fPtSpectrum = (TH1*) file->Get(histName);
160 AliError("Histogram not found");
163 AliError("Could not open ptspectrum_fit.root. Pt Spectrum study could not be enabled.");
166 AliInfo("WARNING: Systematic study enabled. Pt spectrum will be modified");
169 if (fOption.Contains("pt-spectrum-func"))
173 Printf("Using function from input list for systematic p_t study");
177 fPtSpectrum = new TH1F("fPtSpectrum", "fPtSpectrum", 1, 0, 100);
178 fPtSpectrum->SetBinContent(1, 1);
182 AliInfo("WARNING: Systematic study enabled. Pt spectrum will be modified");
185 if (fOption.Contains("particle-species")) {
186 fParticleSpecies = new TNtuple("fParticleSpecies", "fParticleSpecies", "vtx:Pi_True:K_True:p_True:o_True:Pi_Rec:K_Rec:p_Rec:o_Rec:nolabel:doublePrim:doubleCount");
187 fOutput->Add(fParticleSpecies);
190 // TODO set seed for random generator
193 void AliMultiplicityTask::Exec(Option_t*)
197 // Check prerequisites
200 AliDebug(AliLog::kError, "ESD not available");
205 Bool_t eventTriggered = AliPWG0Helper::IsEventTriggered(fESD->GetTriggerMask(), AliPWG0Helper::kMB1);
207 //Bool_t eventTriggered = fESD->GetTriggerMask() & 32;
209 Bool_t eventVertex = AliPWG0Helper::IsVertexReconstructed(fESD->GetVertex());
211 // get the ESD vertex
212 const AliESDVertex* vtxESD = fESD->GetVertex();
216 // post the data already here
217 PostData(0, fOutput);
219 //const Float_t kPtCut = 0.3;
221 // create list of (label, eta) tuples
222 Int_t inputCount = 0;
225 if (fAnalysisMode == AliPWG0Helper::kSPD)
228 const AliMultiplicity* mult = fESD->GetMultiplicity();
231 AliDebug(AliLog::kError, "AliMultiplicity not available");
235 labelArr = new Int_t[mult->GetNumberOfTracklets()];
236 etaArr = new Float_t[mult->GetNumberOfTracklets()];
238 // get multiplicity from ITS tracklets
239 for (Int_t i=0; i<mult->GetNumberOfTracklets(); ++i)
241 //printf("%d %f %f %f\n", i, mult->GetTheta(i), mult->GetPhi(i), mult->GetDeltaPhi(i));
243 // This removes non-tracklets in PDC06 data. Very bad solution. New solution is implemented for newer data. Keeping this for compatibility.
244 if (mult->GetDeltaPhi(i) < -1000)
247 etaArr[inputCount] = mult->GetEta(i);
248 // TODO add second label array
249 labelArr[inputCount] = mult->GetLabel(i, 0);
253 else if (fAnalysisMode == AliPWG0Helper::kTPC || fAnalysisMode == AliPWG0Helper::kTPCITS)
257 AliDebug(AliLog::kError, "fESDTrackCuts not available");
261 // get multiplicity from ESD tracks
262 TObjArray* list = fEsdTrackCuts->GetAcceptedTracks(fESD);
263 Int_t nGoodTracks = list->GetEntries();
265 labelArr = new Int_t[nGoodTracks];
266 etaArr = new Float_t[nGoodTracks];
268 // loop over esd tracks
269 for (Int_t i=0; i<nGoodTracks; i++)
271 AliESDtrack* esdTrack = dynamic_cast<AliESDtrack*> (list->At(i));
274 AliDebug(AliLog::kError, Form("ERROR: Could not retrieve track %d.", i));
278 etaArr[inputCount] = esdTrack->Eta();
279 labelArr[inputCount] = TMath::Abs(esdTrack->GetLabel());
286 // eta range for nMCTracksSpecies, nESDTracksSpecies
287 Float_t etaRange = -1;
288 switch (fAnalysisMode) {
289 case AliPWG0Helper::kInvalid: break;
290 case AliPWG0Helper::kTPC:
291 case AliPWG0Helper::kTPCITS:
292 etaRange = 0.9; break;
293 case AliPWG0Helper::kSPD: etaRange = 2.0; break;
296 if (!fReadMC) // Processing of ESD information
298 if (eventTriggered && eventVertex)
300 Int_t nESDTracks05 = 0;
301 Int_t nESDTracks09 = 0;
302 Int_t nESDTracks15 = 0;
303 Int_t nESDTracks20 = 0;
305 for (Int_t i=0; i<inputCount; ++i)
307 Float_t eta = etaArr[i];
309 if (TMath::Abs(eta) < 0.5)
312 if (TMath::Abs(eta) < 0.9)
315 if (TMath::Abs(eta) < 1.5)
318 if (TMath::Abs(eta) < 2.0)
322 fMultiplicity->FillMeasured(vtx[2], nESDTracks05, nESDTracks09, nESDTracks15, nESDTracks20);
325 else if (fReadMC) // Processing of MC information
327 AliMCEventHandler* eventHandler = dynamic_cast<AliMCEventHandler*> (AliAnalysisManager::GetAnalysisManager()->GetMCtruthEventHandler());
329 Printf("ERROR: Could not retrieve MC event handler");
333 AliMCEvent* mcEvent = eventHandler->MCEvent();
335 Printf("ERROR: Could not retrieve MC event");
339 AliStack* stack = mcEvent->Stack();
342 AliDebug(AliLog::kError, "Stack not available");
346 AliHeader* header = mcEvent->Header();
349 AliDebug(AliLog::kError, "Header not available");
353 Bool_t processEvent = kTRUE;
354 if (fSelectProcessType > 0)
356 // getting process information; NB: this only works for Pythia
357 Int_t processtype = AliPWG0Helper::GetPythiaEventProcessType(header);
359 processEvent = kFALSE;
362 if (fSelectProcessType == 1 && processtype !=92 && processtype !=93 && processtype != 94)
363 processEvent = kTRUE;
365 // single diffractive
366 if (fSelectProcessType == 2 && (processtype == 92 || processtype == 93))
367 processEvent = kTRUE;
369 // double diffractive
370 if (fSelectProcessType == 3 && processtype == 94)
371 processEvent = kTRUE;
374 AliDebug(AliLog::kDebug, Form("Skipping this event, because it is not of the requested process type (%d)", processtype));
377 // systematic study: 10% lower efficiency
378 if (fSystSkipParticles && (gRandom->Uniform() < 0.1))
379 processEvent = kFALSE;
384 AliGenEventHeader* genHeader = header->GenEventHeader();
386 genHeader->PrimaryVertex(vtxMC);
388 // get number of tracks from MC
389 // loop over mc particles
390 Int_t nPrim = stack->GetNprimary();
391 Int_t nMCPart = stack->GetNtrack();
393 // tracks in different eta ranges
394 Int_t nMCTracks05 = 0;
395 Int_t nMCTracks09 = 0;
396 Int_t nMCTracks15 = 0;
397 Int_t nMCTracks20 = 0;
398 Int_t nMCTracksAll = 0;
400 // tracks per particle species, in |eta| < 2 (systematic study)
401 Int_t nMCTracksSpecies[4]; // (pi, K, p, other)
402 for (Int_t i = 0; i<4; ++i)
403 nMCTracksSpecies[i] = 0;
405 for (Int_t iMc = 0; iMc < nPrim; ++iMc)
407 AliDebug(AliLog::kDebug+1, Form("MC Loop: Processing particle %d.", iMc));
409 TParticle* particle = stack->Particle(iMc);
413 AliDebug(AliLog::kError, Form("UNEXPECTED: particle with label %d not found in stack (mc loop).", iMc));
417 Bool_t debug = kFALSE;
418 if (AliPWG0Helper::IsPrimaryCharged(particle, nPrim, debug) == kFALSE)
420 //printf("%d) DROPPED ", iMC);
425 //printf("%d) OK ", iMC);
428 //if (particle->Pt() < kPtCut)
431 Int_t particleWeight = 1;
433 Float_t pt = particle->Pt();
435 // in case of systematic study, weight according to the change of the pt spectrum
436 // it cannot be just multiplied because we cannot count "half of a particle"
437 // instead a random generator decides if the particle is counted twice (if value > 1)
438 // or not (if value < 0)
441 Int_t bin = fPtSpectrum->FindBin(pt);
442 if (bin > 0 && bin <= fPtSpectrum->GetNbinsX())
444 Float_t factor = fPtSpectrum->GetBinContent(bin);
447 Float_t random = gRandom->Uniform();
448 if (factor > 1 && random < factor - 1)
452 else if (factor < 1 && random < 1 - factor)
458 //Printf("MC weight is: %d", particleWeight);
460 if (TMath::Abs(particle->Eta()) < 0.5)
461 nMCTracks05 += particleWeight;
463 if (TMath::Abs(particle->Eta()) < 0.9)
464 nMCTracks09 += particleWeight;
466 if (TMath::Abs(particle->Eta()) < 1.5)
467 nMCTracks15 += particleWeight;
469 if (TMath::Abs(particle->Eta()) < 2.0)
470 nMCTracks20 += particleWeight;
472 nMCTracksAll += particleWeight;
474 if (fParticleCorrection[0] || fParticleSpecies)
477 switch (TMath::Abs(particle->GetPdgCode()))
479 case 211: id = 0; break;
480 case 321: id = 1; break;
481 case 2212: id = 2; break;
482 default: id = 3; break;
485 if (TMath::Abs(particle->Eta()) < etaRange)
486 nMCTracksSpecies[id]++;
488 if (fParticleCorrection[id])
489 fParticleCorrection[id]->GetTrackCorrection()->FillGene(vtxMC[2], particle->Eta(), particle->Pt());
491 } // end of mc particle
493 fMultiplicity->FillGenerated(vtxMC[2], eventTriggered, eventVertex, (Int_t) nMCTracks05, (Int_t) nMCTracks09, (Int_t) nMCTracks15, (Int_t) nMCTracks20, (Int_t) nMCTracksAll);
495 if (eventTriggered && eventVertex)
497 Int_t nESDTracks05 = 0;
498 Int_t nESDTracks09 = 0;
499 Int_t nESDTracks15 = 0;
500 Int_t nESDTracks20 = 0;
502 // tracks per particle species, in |eta| < 2 (systematic study)
503 Int_t nESDTracksSpecies[7]; // (pi, K, p, other, nolabel, doublecount_prim, doublecount_all)
504 for (Int_t i = 0; i<7; ++i)
505 nESDTracksSpecies[i] = 0;
507 Bool_t* foundPrimaries = new Bool_t[nPrim]; // to prevent double counting
508 for (Int_t i=0; i<nPrim; i++)
509 foundPrimaries[i] = kFALSE;
511 Bool_t* foundTracks = new Bool_t[nMCPart]; // to prevent double counting
512 for (Int_t i=0; i<nMCPart; i++)
513 foundTracks[i] = kFALSE;
515 for (Int_t i=0; i<inputCount; ++i)
517 Float_t eta = etaArr[i];
518 Int_t label = labelArr[i];
520 Int_t particleWeight = 1;
522 // in case of systematic study, weight according to the change of the pt spectrum
525 TParticle* mother = 0;
527 // preserve label for later
528 Int_t labelCopy = label;
530 labelCopy = AliPWG0Helper::FindPrimaryMotherLabel(stack, labelCopy);
532 mother = stack->Particle(labelCopy);
534 // in case of pt study we do not count particles w/o label, because they cannot be scaled
538 // it cannot be just multiplied because we cannot count "half of a particle"
539 // instead a random generator decides if the particle is counted twice (if value > 1)
540 // or not (if value < 0)
541 Int_t bin = fPtSpectrum->FindBin(mother->Pt());
542 if (bin > 0 && bin <= fPtSpectrum->GetNbinsX())
544 Float_t factor = fPtSpectrum->GetBinContent(bin);
547 Float_t random = gRandom->Uniform();
548 if (factor > 1 && random < factor - 1)
552 else if (factor < 1 && random < 1 - factor)
558 //Printf("ESD weight is: %d", particleWeight);
560 if (TMath::Abs(eta) < 0.5)
561 nESDTracks05 += particleWeight;
563 if (TMath::Abs(eta) < 0.9)
564 nESDTracks09 += particleWeight;
566 if (TMath::Abs(eta) < 1.5)
567 nESDTracks15 += particleWeight;
569 if (TMath::Abs(eta) < 2.0)
570 nESDTracks20 += particleWeight;
573 if (fParticleCorrection[0] || fParticleSpecies)
575 Int_t motherLabel = -1;
576 TParticle* mother = 0;
580 motherLabel = AliPWG0Helper::FindPrimaryMotherLabel(stack, label);
581 if (motherLabel >= 0)
582 mother = stack->Particle(motherLabel);
586 // count tracks that did not have a label
587 if (TMath::Abs(eta) < etaRange)
588 nESDTracksSpecies[4]++;
592 // get particle type (pion, proton, kaon, other)
594 switch (TMath::Abs(mother->GetPdgCode()))
596 case 211: id = 0; break;
597 case 321: id = 1; break;
598 case 2212: id = 2; break;
599 default: id = 3; break;
602 // double counting is ok for particle ratio study
603 if (TMath::Abs(eta) < etaRange)
604 nESDTracksSpecies[id]++;
606 // double counting is not ok for efficiency study
608 // check if we already counted this particle, this way distinguishes double counted particles (bug/artefact in tracking) or double counted primaries due to secondaries (physics)
609 if (foundTracks[label])
611 if (TMath::Abs(eta) < etaRange)
612 nESDTracksSpecies[6]++;
615 foundTracks[label] = kTRUE;
617 // particle (primary) already counted?
618 if (foundPrimaries[motherLabel])
620 if (TMath::Abs(eta) < etaRange)
621 nESDTracksSpecies[5]++;
624 foundPrimaries[motherLabel] = kTRUE;
626 if (fParticleCorrection[id])
627 fParticleCorrection[id]->GetTrackCorrection()->FillMeas(vtxMC[2], mother->Eta(), mother->Pt());
631 delete[] foundTracks;
632 delete[] foundPrimaries;
634 if ((Int_t) nMCTracks20 == 0 && nESDTracks20 > 3)
635 printf("WARNING: Event has %d generated and %d reconstructed...\n", nMCTracks20, nESDTracks20);
637 // fill response matrix using vtxMC (best guess)
638 fMultiplicity->FillCorrection(vtxMC[2], nMCTracks05, nMCTracks09, nMCTracks15, nMCTracks20, nMCTracksAll, nESDTracks05, nESDTracks09, nESDTracks15, nESDTracks20);
640 fMultiplicity->FillMeasured(vtx[2], nESDTracks05, nESDTracks09, nESDTracks15, nESDTracks20);
642 if (fParticleSpecies)
643 fParticleSpecies->Fill(vtxMC[2], nMCTracksSpecies[0], nMCTracksSpecies[1], nMCTracksSpecies[2], nMCTracksSpecies[3], nESDTracksSpecies[0], nESDTracksSpecies[1], nESDTracksSpecies[2], nESDTracksSpecies[3], nESDTracksSpecies[4], nESDTracksSpecies[5], nESDTracksSpecies[6]);
652 void AliMultiplicityTask::Terminate(Option_t *)
654 // The Terminate() function is the last function to be called during
655 // a query. It always runs on the client, it can be used to present
656 // the results graphically or save the results to file.
658 fOutput = dynamic_cast<TList*> (GetOutputData(0));
660 Printf("ERROR: fOutput not available");
664 fMultiplicity = dynamic_cast<AliMultiplicityCorrection*> (fOutput->FindObject("Multiplicity"));
665 for (Int_t i = 0; i < 4; ++i)
666 fParticleCorrection[i] = dynamic_cast<AliCorrection*> (fOutput->FindObject(Form("correction_%d", i)));
667 fParticleSpecies = dynamic_cast<TNtuple*> (fOutput->FindObject("fParticleSpecies"));
671 AliDebug(AliLog::kError, Form("ERROR: Histograms not available %p", (void*) fMultiplicity));
675 TFile* file = TFile::Open("multiplicityMC.root", "RECREATE");
677 fMultiplicity->SaveHistograms();
678 for (Int_t i = 0; i < 4; ++i)
679 if (fParticleCorrection[i])
680 fParticleCorrection[i]->SaveHistograms();
681 if (fParticleSpecies)
682 fParticleSpecies->Write();
684 TObjString option(fOption);
689 Printf("Writting result to multiplicityMC.root");