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 "multiplicity/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),
44 fTrigger(AliPWG0Helper::kMB1),
49 fSystSkipParticles(kFALSE),
50 fSelectProcessType(0),
56 // Constructor. Initialization of pointers
59 for (Int_t i = 0; i<4; i++)
60 fParticleCorrection[i] = 0;
62 // Define input and output slots here
63 DefineInput(0, TChain::Class());
64 DefineOutput(0, TList::Class());
67 AliMultiplicityTask::~AliMultiplicityTask()
73 // histograms are in the output list and deleted when the output
74 // list is deleted by the TSelector dtor
82 //________________________________________________________________________
83 void AliMultiplicityTask::ConnectInputData(Option_t *)
88 Printf("AliMultiplicityTask::ConnectInputData called");
90 TTree* tree = dynamic_cast<TTree*> (GetInputData(0));
92 Printf("ERROR: Could not read tree from input slot 0");
94 // Disable all branches and enable only the needed ones
95 tree->SetBranchStatus("*", 0);
97 tree->SetBranchStatus("AliESDHeader*", 1);
98 tree->SetBranchStatus("*Vertex*", 1);
100 if (fAnalysisMode == AliPWG0Helper::kSPD) {
101 tree->SetBranchStatus("AliMultiplicity*", 1);
104 if (fAnalysisMode == AliPWG0Helper::kTPC || fAnalysisMode == AliPWG0Helper::kTPCITS) {
105 //AliESDtrackCuts::EnableNeededBranches(tree);
106 tree->SetBranchStatus("Tracks*", 1);
109 AliESDInputHandler *esdH = dynamic_cast<AliESDInputHandler*> (AliAnalysisManager::GetAnalysisManager()->GetInputEventHandler());
112 Printf("ERROR: Could not get ESDInputHandler");
114 fESD = esdH->GetEvent();
117 // disable info messages of AliMCEvent (per event)
118 AliLog::SetClassDebugLevel("AliMCEvent", AliLog::kWarning - AliLog::kDebug + 1);
121 void AliMultiplicityTask::CreateOutputObjects()
123 // create result objects and add to output list
128 fMultiplicity = new AliMultiplicityCorrection("Multiplicity", "Multiplicity");
129 fOutput->Add(fMultiplicity);
131 if (fOption.Contains("skip-particles"))
133 fSystSkipParticles = kTRUE;
134 AliInfo("WARNING: Systematic study enabled. Particles will be skipped.");
137 if (fOption.Contains("particle-efficiency"))
138 for (Int_t i = 0; i<4; i++)
140 fParticleCorrection[i] = new AliCorrection(Form("correction_%d", i), Form("correction_%d", i));
141 fOutput->Add(fParticleCorrection[i]);
144 if (fOption.Contains("only-process-type-nd"))
145 fSelectProcessType = 1;
147 if (fOption.Contains("only-process-type-sd"))
148 fSelectProcessType = 2;
150 if (fOption.Contains("only-process-type-dd"))
151 fSelectProcessType = 3;
153 if (fSelectProcessType != 0)
154 AliInfo(Form("WARNING: Systematic study enabled. Only considering process type %d", fSelectProcessType));
156 if (fOption.Contains("pt-spectrum-hist"))
158 TFile* file = TFile::Open("ptspectrum_fit.root");
161 TString subStr(fOption(fOption.Index("pt-spectrum")+17, 3));
162 TString histName(Form("ptspectrum_%s", subStr.Data()));
163 AliInfo(Form("Pt-Spectrum modification. Using %s.", histName.Data()));
164 fPtSpectrum = (TH1*) file->Get(histName);
166 AliError("Histogram not found");
169 AliError("Could not open ptspectrum_fit.root. Pt Spectrum study could not be enabled.");
172 AliInfo("WARNING: Systematic study enabled. Pt spectrum will be modified");
175 if (fOption.Contains("pt-spectrum-func"))
179 Printf("Using function from input list for systematic p_t study");
183 fPtSpectrum = new TH1F("fPtSpectrum", "fPtSpectrum", 1, 0, 100);
184 fPtSpectrum->SetBinContent(1, 1);
188 AliInfo("WARNING: Systematic study enabled. Pt spectrum will be modified");
191 if (fOption.Contains("particle-species")) {
192 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");
193 fOutput->Add(fParticleSpecies);
196 // TODO set seed for random generator
199 void AliMultiplicityTask::Exec(Option_t*)
203 // Check prerequisites
206 AliDebug(AliLog::kError, "ESD not available");
210 Bool_t eventTriggered = AliPWG0Helper::IsEventTriggered(fESD->GetTriggerMask(), fTrigger);
212 const AliESDVertex* vtxESD = AliPWG0Helper::GetVertex(fESD, fAnalysisMode);
213 Bool_t eventVertex = (vtxESD != 0);
219 // post the data already here
220 PostData(0, fOutput);
222 //const Float_t kPtCut = 0.3;
224 // create list of (label, eta) tuples
225 Int_t inputCount = 0;
228 if (fAnalysisMode == AliPWG0Helper::kSPD)
231 const AliMultiplicity* mult = fESD->GetMultiplicity();
234 AliDebug(AliLog::kError, "AliMultiplicity not available");
238 labelArr = new Int_t[mult->GetNumberOfTracklets()];
239 etaArr = new Float_t[mult->GetNumberOfTracklets()];
241 // get multiplicity from ITS tracklets
242 for (Int_t i=0; i<mult->GetNumberOfTracklets(); ++i)
244 //printf("%d %f %f %f\n", i, mult->GetTheta(i), mult->GetPhi(i), mult->GetDeltaPhi(i));
246 // This removes non-tracklets in PDC06 data. Very bad solution. New solution is implemented for newer data. Keeping this for compatibility.
247 if (mult->GetDeltaPhi(i) < -1000)
250 etaArr[inputCount] = mult->GetEta(i);
251 // TODO add second label array
252 labelArr[inputCount] = mult->GetLabel(i, 0);
256 else if (fAnalysisMode == AliPWG0Helper::kTPC || fAnalysisMode == AliPWG0Helper::kTPCITS)
260 AliDebug(AliLog::kError, "fESDTrackCuts not available");
264 // get multiplicity from ESD tracks
265 TObjArray* list = fEsdTrackCuts->GetAcceptedTracks(fESD, (fAnalysisMode == AliPWG0Helper::kTPC));
266 Int_t nGoodTracks = list->GetEntries();
268 labelArr = new Int_t[nGoodTracks];
269 etaArr = new Float_t[nGoodTracks];
271 // loop over esd tracks
272 for (Int_t i=0; i<nGoodTracks; i++)
274 AliESDtrack* esdTrack = dynamic_cast<AliESDtrack*> (list->At(i));
277 AliDebug(AliLog::kError, Form("ERROR: Could not retrieve track %d.", i));
281 etaArr[inputCount] = esdTrack->Eta();
282 labelArr[inputCount] = TMath::Abs(esdTrack->GetLabel());
289 // eta range for nMCTracksSpecies, nESDTracksSpecies
290 Float_t etaRange = -1;
291 switch (fAnalysisMode) {
292 case AliPWG0Helper::kInvalid: break;
293 case AliPWG0Helper::kTPC:
294 case AliPWG0Helper::kTPCITS:
295 etaRange = 0.9; break;
296 case AliPWG0Helper::kSPD: etaRange = 2.0; break;
299 if (!fReadMC) // Processing of ESD information
301 if (eventTriggered && eventVertex)
303 Int_t nESDTracks05 = 0;
304 Int_t nESDTracks09 = 0;
305 Int_t nESDTracks15 = 0;
306 Int_t nESDTracks20 = 0;
308 for (Int_t i=0; i<inputCount; ++i)
310 Float_t eta = etaArr[i];
312 if (TMath::Abs(eta) < 0.5)
315 if (TMath::Abs(eta) < 0.9)
318 if (TMath::Abs(eta) < 1.5)
321 if (TMath::Abs(eta) < 2.0)
325 fMultiplicity->FillMeasured(vtx[2], nESDTracks05, nESDTracks09, nESDTracks15, nESDTracks20);
328 else if (fReadMC) // Processing of MC information
330 AliMCEventHandler* eventHandler = dynamic_cast<AliMCEventHandler*> (AliAnalysisManager::GetAnalysisManager()->GetMCtruthEventHandler());
332 Printf("ERROR: Could not retrieve MC event handler");
336 AliMCEvent* mcEvent = eventHandler->MCEvent();
338 Printf("ERROR: Could not retrieve MC event");
342 AliStack* stack = mcEvent->Stack();
345 AliDebug(AliLog::kError, "Stack not available");
349 AliHeader* header = mcEvent->Header();
352 AliDebug(AliLog::kError, "Header not available");
358 Printf("WARNING: Replacing vertex by MC vertex. This is for systematical checks only.");
360 AliGenEventHeader* genHeader = header->GenEventHeader();
362 genHeader->PrimaryVertex(vtxMC);
367 Bool_t processEvent = kTRUE;
368 if (fSelectProcessType > 0)
370 // getting process information; NB: this only works for Pythia
371 Int_t processtype = AliPWG0Helper::GetEventProcessType(header);
373 processEvent = kFALSE;
376 if (fSelectProcessType == 1 && processtype == AliPWG0Helper::kND )
377 processEvent = kTRUE;
379 // single diffractive
380 if (fSelectProcessType == 2 && processtype == AliPWG0Helper::kSD )
381 processEvent = kTRUE;
383 // double diffractive
384 if (fSelectProcessType == 3 && processtype == AliPWG0Helper::kDD )
385 processEvent = kTRUE;
388 AliDebug(AliLog::kDebug, Form("Skipping this event, because it is not of the requested process type (%d)", processtype));
391 // systematic study: 10% lower efficiency
392 if (fSystSkipParticles && (gRandom->Uniform() < 0.1))
393 processEvent = kFALSE;
398 AliGenEventHeader* genHeader = header->GenEventHeader();
400 genHeader->PrimaryVertex(vtxMC);
402 // get number of tracks from MC
403 // loop over mc particles
404 Int_t nPrim = stack->GetNprimary();
405 Int_t nMCPart = stack->GetNtrack();
407 // tracks in different eta ranges
408 Int_t nMCTracks05 = 0;
409 Int_t nMCTracks09 = 0;
410 Int_t nMCTracks15 = 0;
411 Int_t nMCTracks20 = 0;
412 Int_t nMCTracksAll = 0;
414 // tracks per particle species, in |eta| < 2 (systematic study)
415 Int_t nMCTracksSpecies[4]; // (pi, K, p, other)
416 for (Int_t i = 0; i<4; ++i)
417 nMCTracksSpecies[i] = 0;
419 for (Int_t iMc = 0; iMc < nPrim; ++iMc)
421 AliDebug(AliLog::kDebug+1, Form("MC Loop: Processing particle %d.", iMc));
423 TParticle* particle = stack->Particle(iMc);
427 AliDebug(AliLog::kError, Form("UNEXPECTED: particle with label %d not found in stack (mc loop).", iMc));
431 Bool_t debug = kFALSE;
432 if (AliPWG0Helper::IsPrimaryCharged(particle, nPrim, debug) == kFALSE)
434 //printf("%d) DROPPED ", iMC);
439 //printf("%d) OK ", iMC);
442 //if (particle->Pt() < kPtCut)
445 Int_t particleWeight = 1;
447 Float_t pt = particle->Pt();
449 // in case of systematic study, weight according to the change of the pt spectrum
450 // it cannot be just multiplied because we cannot count "half of a particle"
451 // instead a random generator decides if the particle is counted twice (if value > 1)
452 // or not (if value < 0)
455 Int_t bin = fPtSpectrum->FindBin(pt);
456 if (bin > 0 && bin <= fPtSpectrum->GetNbinsX())
458 Float_t factor = fPtSpectrum->GetBinContent(bin);
461 Float_t random = gRandom->Uniform();
462 if (factor > 1 && random < factor - 1)
466 else if (factor < 1 && random < 1 - factor)
472 //Printf("MC weight is: %d", particleWeight);
474 if (TMath::Abs(particle->Eta()) < 0.5)
475 nMCTracks05 += particleWeight;
477 if (TMath::Abs(particle->Eta()) < 0.9)
478 nMCTracks09 += particleWeight;
480 if (TMath::Abs(particle->Eta()) < 1.5)
481 nMCTracks15 += particleWeight;
483 if (TMath::Abs(particle->Eta()) < 2.0)
484 nMCTracks20 += particleWeight;
486 nMCTracksAll += particleWeight;
488 if (fParticleCorrection[0] || fParticleSpecies)
491 switch (TMath::Abs(particle->GetPdgCode()))
493 case 211: id = 0; break;
494 case 321: id = 1; break;
495 case 2212: id = 2; break;
496 default: id = 3; break;
499 if (TMath::Abs(particle->Eta()) < etaRange)
500 nMCTracksSpecies[id]++;
502 if (fParticleCorrection[id])
503 fParticleCorrection[id]->GetTrackCorrection()->FillGene(vtxMC[2], particle->Eta(), particle->Pt());
505 } // end of mc particle
507 fMultiplicity->FillGenerated(vtxMC[2], eventTriggered, eventVertex, (Int_t) nMCTracks05, (Int_t) nMCTracks09, (Int_t) nMCTracks15, (Int_t) nMCTracks20, (Int_t) nMCTracksAll);
509 if (eventTriggered && eventVertex)
511 Int_t nESDTracks05 = 0;
512 Int_t nESDTracks09 = 0;
513 Int_t nESDTracks15 = 0;
514 Int_t nESDTracks20 = 0;
516 // tracks per particle species, in |eta| < 2 (systematic study)
517 Int_t nESDTracksSpecies[7]; // (pi, K, p, other, nolabel, doublecount_prim, doublecount_all)
518 for (Int_t i = 0; i<7; ++i)
519 nESDTracksSpecies[i] = 0;
521 Bool_t* foundPrimaries = new Bool_t[nPrim]; // to prevent double counting
522 for (Int_t i=0; i<nPrim; i++)
523 foundPrimaries[i] = kFALSE;
525 Bool_t* foundTracks = new Bool_t[nMCPart]; // to prevent double counting
526 for (Int_t i=0; i<nMCPart; i++)
527 foundTracks[i] = kFALSE;
529 for (Int_t i=0; i<inputCount; ++i)
531 Float_t eta = etaArr[i];
532 Int_t label = labelArr[i];
534 Int_t particleWeight = 1;
536 // in case of systematic study, weight according to the change of the pt spectrum
539 TParticle* mother = 0;
541 // preserve label for later
542 Int_t labelCopy = label;
544 labelCopy = AliPWG0Helper::FindPrimaryMotherLabel(stack, labelCopy);
546 mother = stack->Particle(labelCopy);
548 // in case of pt study we do not count particles w/o label, because they cannot be scaled
552 // it cannot be just multiplied because we cannot count "half of a particle"
553 // instead a random generator decides if the particle is counted twice (if value > 1)
554 // or not (if value < 0)
555 Int_t bin = fPtSpectrum->FindBin(mother->Pt());
556 if (bin > 0 && bin <= fPtSpectrum->GetNbinsX())
558 Float_t factor = fPtSpectrum->GetBinContent(bin);
561 Float_t random = gRandom->Uniform();
562 if (factor > 1 && random < factor - 1)
566 else if (factor < 1 && random < 1 - factor)
572 //Printf("ESD weight is: %d", particleWeight);
574 if (TMath::Abs(eta) < 0.5)
575 nESDTracks05 += particleWeight;
577 if (TMath::Abs(eta) < 0.9)
578 nESDTracks09 += particleWeight;
580 if (TMath::Abs(eta) < 1.5)
581 nESDTracks15 += particleWeight;
583 if (TMath::Abs(eta) < 2.0)
584 nESDTracks20 += particleWeight;
587 if (fParticleCorrection[0] || fParticleSpecies)
589 Int_t motherLabel = -1;
590 TParticle* mother = 0;
594 motherLabel = AliPWG0Helper::FindPrimaryMotherLabel(stack, label);
595 if (motherLabel >= 0)
596 mother = stack->Particle(motherLabel);
600 // count tracks that did not have a label
601 if (TMath::Abs(eta) < etaRange)
602 nESDTracksSpecies[4]++;
606 // get particle type (pion, proton, kaon, other)
608 switch (TMath::Abs(mother->GetPdgCode()))
610 case 211: id = 0; break;
611 case 321: id = 1; break;
612 case 2212: id = 2; break;
613 default: id = 3; break;
616 // double counting is ok for particle ratio study
617 if (TMath::Abs(eta) < etaRange)
618 nESDTracksSpecies[id]++;
620 // double counting is not ok for efficiency study
622 // 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)
623 if (foundTracks[label])
625 if (TMath::Abs(eta) < etaRange)
626 nESDTracksSpecies[6]++;
629 foundTracks[label] = kTRUE;
631 // particle (primary) already counted?
632 if (foundPrimaries[motherLabel])
634 if (TMath::Abs(eta) < etaRange)
635 nESDTracksSpecies[5]++;
638 foundPrimaries[motherLabel] = kTRUE;
640 if (fParticleCorrection[id])
641 fParticleCorrection[id]->GetTrackCorrection()->FillMeas(vtxMC[2], mother->Eta(), mother->Pt());
645 delete[] foundTracks;
646 delete[] foundPrimaries;
648 if ((Int_t) nMCTracks15 > 15 && nESDTracks15 <= 3)
650 TTree* tree = dynamic_cast<TTree*> (GetInputData(0));
651 printf("WARNING: Event %lld %s (vtx-z = %f) has %d generated and %d reconstructed...\n", tree->GetReadEntry(), tree->GetCurrentFile()->GetName(), vtxMC[2], nMCTracks15, nESDTracks15);
654 // fill response matrix using vtxMC (best guess)
655 fMultiplicity->FillCorrection(vtxMC[2], nMCTracks05, nMCTracks09, nMCTracks15, nMCTracks20, nMCTracksAll, nESDTracks05, nESDTracks09, nESDTracks15, nESDTracks20);
657 fMultiplicity->FillMeasured(vtx[2], nESDTracks05, nESDTracks09, nESDTracks15, nESDTracks20);
659 if (fParticleSpecies)
660 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]);
669 void AliMultiplicityTask::Terminate(Option_t *)
671 // The Terminate() function is the last function to be called during
672 // a query. It always runs on the client, it can be used to present
673 // the results graphically or save the results to file.
675 fOutput = dynamic_cast<TList*> (GetOutputData(0));
677 Printf("ERROR: fOutput not available");
681 fMultiplicity = dynamic_cast<AliMultiplicityCorrection*> (fOutput->FindObject("Multiplicity"));
682 for (Int_t i = 0; i < 4; ++i)
683 fParticleCorrection[i] = dynamic_cast<AliCorrection*> (fOutput->FindObject(Form("correction_%d", i)));
684 fParticleSpecies = dynamic_cast<TNtuple*> (fOutput->FindObject("fParticleSpecies"));
688 AliDebug(AliLog::kError, Form("ERROR: Histograms not available %p", (void*) fMultiplicity));
692 TFile* file = TFile::Open("multiplicity.root", "RECREATE");
694 fMultiplicity->SaveHistograms();
695 for (Int_t i = 0; i < 4; ++i)
696 if (fParticleCorrection[i])
697 fParticleCorrection[i]->SaveHistograms();
698 if (fParticleSpecies)
699 fParticleSpecies->Write();
701 TObjString option(fOption);
706 Printf("Writting result to multiplicity.root");