3 #include "AliMultiplicityTask.h"
14 #include <TParticle.h>
17 #include <TObjString.h>
21 #include <AliESDVertex.h>
22 #include <AliESDEvent.h>
24 #include <AliHeader.h>
25 #include <AliGenEventHeader.h>
26 #include <AliMultiplicity.h>
27 #include <AliAnalysisManager.h>
28 #include <AliMCEventHandler.h>
29 #include <AliMCEvent.h>
30 #include <AliESDInputHandler.h>
32 #include "AliESDtrackCuts.h"
33 #include "AliPWG0Helper.h"
34 #include "AliMultiplicityCorrection.h"
35 #include "AliCorrection.h"
36 #include "AliCorrectionMatrix3D.h"
37 #include "AliPhysicsSelection.h"
38 #include "AliTriggerAnalysis.h"
39 #include "AliVEvent.h"
41 ClassImp(AliMultiplicityTask)
43 AliMultiplicityTask::AliMultiplicityTask(const char* opt) :
44 AliAnalysisTask("AliMultiplicityTask", ""),
47 fAnalysisMode((AliPWG0Helper::AnalysisMode) (AliPWG0Helper::kSPD | AliPWG0Helper::kFieldOn)),
48 fTrigger(AliTriggerAnalysis::kMB1),
50 fDiffTreatment(AliPWG0Helper::kMCFlags),
55 fSystSkipParticles(kFALSE),
56 fSelectProcessType(0),
67 // Constructor. Initialization of pointers
70 for (Int_t i = 0; i<8; i++)
71 fParticleCorrection[i] = 0;
73 for (Int_t i=0; i<3; i++)
76 // Define input and output slots here
77 DefineInput(0, TChain::Class());
78 DefineOutput(0, TList::Class());
80 if (fOption.Contains("only-process-type-nd"))
81 fSelectProcessType = 1;
83 if (fOption.Contains("only-process-type-sd"))
84 fSelectProcessType = 2;
86 if (fOption.Contains("only-process-type-dd"))
87 fSelectProcessType = 3;
89 if (fSelectProcessType != 0)
90 AliInfo(Form("WARNING: Systematic study enabled. Only considering process type %d", fSelectProcessType));
93 AliMultiplicityTask::~AliMultiplicityTask()
99 // histograms are in the output list and deleted when the output
100 // list is deleted by the TSelector dtor
102 if (fOutput&& !AliAnalysisManager::GetAnalysisManager()->IsProofMode()) {
108 //________________________________________________________________________
109 void AliMultiplicityTask::ConnectInputData(Option_t *)
114 Printf("AliMultiplicityTask::ConnectInputData called");
116 TTree* tree = dynamic_cast<TTree*> (GetInputData(0));
118 Printf("ERROR: Could not read tree from input slot 0");
120 // Disable all branches and enable only the needed ones
122 tree->SetBranchStatus("*", 0);
124 tree->SetBranchStatus("AliESDHeader*", 1);
125 tree->SetBranchStatus("*Vertex*", 1);
127 if (fAnalysisMode & AliPWG0Helper::kSPD) {
128 tree->SetBranchStatus("AliMultiplicity*", 1);
131 if (fAnalysisMode & AliPWG0Helper::kTPC || fAnalysisMode & AliPWG0Helper::kTPCITS) {
132 //AliESDtrackCuts::EnableNeededBranches(tree);
133 tree->SetBranchStatus("Tracks*", 1);
137 AliESDInputHandler *esdH = dynamic_cast<AliESDInputHandler*> (AliAnalysisManager::GetAnalysisManager()->GetInputEventHandler());
140 Printf("ERROR: Could not get ESDInputHandler");
142 fESD = esdH->GetEvent();
145 // disable info messages of AliMCEvent (per event)
146 AliLog::SetClassDebugLevel("AliMCEvent", AliLog::kWarning - AliLog::kDebug + 1);
149 void AliMultiplicityTask::CreateOutputObjects()
151 // create result objects and add to output list
156 fMultiplicity = new AliMultiplicityCorrection("Multiplicity", "Multiplicity");
157 fOutput->Add(fMultiplicity);
159 fdNdpT = new TH1F("fdNdpT", "fdNdpT", 1000, 0, 10);
161 fOutput->Add(fdNdpT);
163 if (fOption.Contains("particle-efficiency"))
164 for (Int_t i = 0; i<8; i++)
166 fParticleCorrection[i] = new AliCorrection(Form("correction_%d", i), Form("correction_%d", i));
167 fOutput->Add(fParticleCorrection[i]);
170 if (fOption.Contains("pt-spectrum-hist"))
172 TFile* file = TFile::Open("ptspectrum_fit.root");
175 TString subStr(fOption(fOption.Index("pt-spectrum")+17, 3));
176 TString histName(Form("ptspectrum_%s", subStr.Data()));
177 AliInfo(Form("Pt-Spectrum modification. Using %s.", histName.Data()));
178 fPtSpectrum = (TH1D*) file->Get(histName);
180 AliError("Histogram not found");
183 AliError("Could not open ptspectrum_fit.root. Pt Spectrum study could not be enabled.");
186 if (fOption.Contains("pt-spectrum-func"))
190 Printf("Using function for systematic p_t study");
194 Printf("ERROR: Could not find function for systematic p_t study");
195 fPtSpectrum = new TH1D("fPtSpectrum", "fPtSpectrum", 1, 0, 100);
196 fPtSpectrum->SetBinContent(1, 1);
201 Printf("WARNING: Systematic study enabled. Pt spectrum will be modified");
203 if (fOption.Contains("particle-species")) {
204 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");
205 fOutput->Add(fParticleSpecies);
208 fTemp1 = new TH2F("fTemp1", "fTemp1", 100, -0.5, 99.5, 100, -0.5, 99.5);
209 fOutput->Add(fTemp1);
211 for (Int_t i=0; i<3; i++)
213 fEta[i] = new TH1F(Form("fEta_%d", i), ";#eta", 100, -2, 2);
214 fOutput->Add(fEta[i]);
217 fVertex = new TH3F("vertex_check", "vertex_check;x;y;z", 100, -1, 1, 100, -1, 1, 100, -30, 30);
218 fOutput->Add(fVertex);
220 fEtaPhi = new TH2F("fEtaPhi", "fEtaPhi;#eta;#phi in rad.;count", 80, -4, 4, 18*20, 0, 2 * TMath::Pi());
221 fOutput->Add(fEtaPhi);
223 // TODO set seed for random generator
226 void AliMultiplicityTask::Exec(Option_t*)
230 // Check prerequisites
233 AliDebug(AliLog::kError, "ESD not available");
237 AliInputEventHandler* inputHandler = (AliInputEventHandler*) AliAnalysisManager::GetAnalysisManager()->GetInputEventHandler();
240 Printf("ERROR: Could not receive input handler");
244 Bool_t eventTriggered = inputHandler->IsEventSelected() & AliVEvent::kMB;
246 static AliTriggerAnalysis* triggerAnalysis = 0;
247 if (!triggerAnalysis)
249 AliPhysicsSelection* physicsSelection = static_cast<AliPhysicsSelection*> (inputHandler->GetEventSelection());
250 triggerAnalysis = physicsSelection->GetTriggerAnalysis();
253 eventTriggered = triggerAnalysis->IsTriggerFired(fESD, fTrigger);
255 const AliESDVertex* vtxESD = AliPWG0Helper::GetVertex(fESD, fAnalysisMode);
256 if (vtxESD && !AliPWG0Helper::TestVertex(vtxESD, fAnalysisMode))
259 // remove vertices outside +- 15 cm
260 if (vtxESD && TMath::Abs(vtxESD->GetZ()) > 15)
263 Bool_t eventVertex = (vtxESD != 0);
269 fVertex->Fill(vtxESD->GetX(), vtxESD->GetY(), vtxESD->GetZ());
272 // post the data already here
273 PostData(0, fOutput);
275 //const Float_t kPtCut = 0.3;
277 // create list of (label, eta) tuples
278 Int_t inputCount = 0;
281 Int_t nGoodTracks = 0; // number of total good tracks is needed both in SPD and TPC loops if the mode is kTPCSPD
282 Int_t nESDTracks = 0; // Total number of ESD tracks (including those not passing the cuts);
283 const int kRejBit = BIT(15); // set this bit in ESD tracks if it is rejected by a cut
285 if (fAnalysisMode & AliPWG0Helper::kTPC || fAnalysisMode & AliPWG0Helper::kTPCITS || fAnalysisMode & AliPWG0Helper::kTPCSPD)
289 AliDebug(AliLog::kError, "fESDTrackCuts not available");
295 // get multiplicity from ESD tracks
296 TObjArray* list = fEsdTrackCuts->GetAcceptedTracks(fESD, (fAnalysisMode & AliPWG0Helper::kTPC));
297 nGoodTracks = list->GetEntries();
299 Int_t arraySize = nGoodTracks; // if we're also using tracklets, we need to increase this
300 if (fAnalysisMode & AliPWG0Helper::kTPCSPD) {
301 // if I have to also count clusters later on, I have to make sure the arrays are big enough
302 // Moreover, we need to keep track of rejected tracks to avoid double-counting
303 Printf( "Processing tracks");
304 const AliMultiplicity* mult = fESD->GetMultiplicity();
307 AliDebug(AliLog::kError, "AliMultiplicity not available");
310 arraySize += mult->GetNumberOfTracklets();
311 // allocate and fill array for rejected tracks
312 nESDTracks = fESD->GetNumberOfTracks();
313 for(Int_t itracks = 0; itracks < nESDTracks; itracks++){
314 AliESDtrack* track = fESD->GetTrack(itracks);
315 if( itracks!=track->GetID() ){
316 AliFatal("Track ID not matching track index!");
318 if (!fEsdTrackCuts->AcceptTrack(track)) {
319 track->SetBit(kRejBit);
324 labelArr = new Int_t[arraySize];
325 etaArr = new Float_t[arraySize];
327 // loop over esd tracks
328 for (Int_t i=0; i<nGoodTracks; i++)
330 AliESDtrack* esdTrack = dynamic_cast<AliESDtrack*> (list->At(i));
333 AliDebug(AliLog::kError, Form("ERROR: Could not retrieve track %d.", i));
337 if (esdTrack->Pt() < 0.15){
338 esdTrack->SetBit(kRejBit);
342 if (fAnalysisMode & AliPWG0Helper::kTPCSPD) {
343 // Cuts by ruben to flag secondaries
344 if (esdTrack->IsOn(AliESDtrack::kMultSec) ) continue;
345 if (esdTrack->IsOn(AliESDtrack::kMultInV0)) continue;
348 Float_t d0z0[2],covd0z0[3];
349 esdTrack->GetImpactParameters(d0z0,covd0z0);
350 Float_t sigma= 0.0050+0.0060/TMath::Power(esdTrack->Pt(),0.9);
351 Float_t d0max = 7.*sigma;
352 if (TMath::Abs(d0z0[0]) > d0max) {
353 // rejLabelArr[irejCount++] = esdTrack->GetID(); // We
354 // don't count the tracklet if the track is a
355 // secondary, so this must be commented out
359 if (vtxESD && TMath::Abs(vtx[2]) < 10)
360 fEtaPhi->Fill(esdTrack->Eta(), esdTrack->Phi());
362 etaArr[inputCount] = esdTrack->Eta();
363 labelArr[inputCount] = TMath::Abs(esdTrack->GetLabel());
370 // SPD tracklets are used either in SPD standalone mode or in TPC+SPD mode (tracks + tracklets not using any cluster already used in tracks)
371 if (fAnalysisMode & AliPWG0Helper::kSPD || fAnalysisMode & AliPWG0Helper::kTPCSPD)
376 AliDebug(AliLog::kInfo, "Processing tracklets");
378 const AliMultiplicity* mult = fESD->GetMultiplicity();
381 AliDebug(AliLog::kError, "AliMultiplicity not available");
382 if (labelArr) delete[] labelArr;
383 if (etaArr) delete[] etaArr;
387 Bool_t foundInEta10 = kFALSE;
388 if ((fAnalysisMode & AliPWG0Helper::kSPD) && !(fAnalysisMode & AliPWG0Helper::kTPC || fAnalysisMode & AliPWG0Helper::kTPCITS || fAnalysisMode & AliPWG0Helper::kTPCSPD)) {
389 // if we are counting both tracks and tracklets, these arrays were already initialized above
390 AliDebug(AliLog::kInfo, "Booking arrays");
391 if (!labelArr) labelArr = new Int_t[mult->GetNumberOfTracklets()];
392 if (!etaArr) etaArr = new Float_t[mult->GetNumberOfTracklets()];
394 if (inputCount) foundInEta10 = kTRUE; // by definition, if we found a track.
396 // get multiplicity from ITS tracklets
397 for (Int_t i=0; i<mult->GetNumberOfTracklets(); ++i)
399 //printf("%d %f %f %f\n", i, mult->GetTheta(i), mult->GetPhi(i), mult->GetDeltaPhi(i));
401 Float_t deltaPhi = mult->GetDeltaPhi(i);
403 if (fDeltaPhiCut > 0 && TMath::Abs(deltaPhi) > fDeltaPhiCut)
406 if (fSystSkipParticles && gRandom->Uniform() < (0.0153))
408 Printf("Skipped tracklet!");
412 // if counting tracks+tracklets, check if clusters where already used in tracks
413 if (fAnalysisMode & AliPWG0Helper::kTPCSPD) {
415 mult->GetTrackletTrackIDs(i,0,id1,id2);
416 if ( (id1>=0&& !fESD->GetTrack(id1)->TestBit(kRejBit) ) ||
417 (id2>=0&& !fESD->GetTrack(id2)->TestBit(kRejBit) )
419 printf ("Skipping tracklet: already used in track");
422 // Ruben also had this, but we're not using pure ITSSA tracks here:
423 // if (fSPDMult->FreeClustersTracklet(itr,1)) trITSSApure++; // not used in ITS_SA_Pure track
427 etaArr[inputCount] = mult->GetEta(i);
428 if (mult->GetLabel(i, 0) == mult->GetLabel(i, 1))
430 labelArr[inputCount] = mult->GetLabel(i, 0);
433 labelArr[inputCount] = -1;
435 for (Int_t j=0; j<3; j++)
437 if (vtx[2] > fMultiplicity->GetVertexBegin(j) && vtx[2] < fMultiplicity->GetVertexEnd(j))
438 fEta[j]->Fill(etaArr[inputCount]);
441 if (vtxESD && TMath::Abs(vtx[2]) < 10)
442 fEtaPhi->Fill(etaArr[inputCount], mult->GetPhi(i));
444 // we have to repeat the trigger here, because the tracklet might have been kicked out fSystSkipParticles
445 if (TMath::Abs(etaArr[inputCount]) < 1)
446 foundInEta10 = kTRUE;
451 if (fSystSkipParticles && (fTrigger & AliTriggerAnalysis::kOneParticle) && !foundInEta10)
452 eventTriggered = kFALSE;
456 // eta range for nMCTracksSpecies, nESDTracksSpecies
457 Float_t etaRange = 1.0;
458 // switch (fAnalysisMode) {
459 // case AliPWG0Helper::kInvalid: break;
460 // case AliPWG0Helper::kTPC:
461 // case AliPWG0Helper::kTPCITS:
462 // etaRange = 1.0; break;
463 // case AliPWG0Helper::kSPD: etaRange = 1.0; break;
467 if (!fReadMC) // Processing of ESD information
469 Int_t nESDTracks05 = 0;
470 Int_t nESDTracks10 = 0;
471 Int_t nESDTracks14 = 0;
473 for (Int_t i=0; i<inputCount; ++i)
475 Float_t eta = etaArr[i];
477 if (TMath::Abs(eta) < 0.5)
480 if (TMath::Abs(eta) < 1.0)
483 if (TMath::Abs(eta) < 1.3)
487 //if (nESDTracks05 >= 20 || nESDTracks10 >= 30 || nESDTracks14 >= 32)
488 // Printf("File: %s, IEV: %d, TRG: ---, Orbit: 0x%x, Period: %d, BC: %d; Tracks: %d %d %d", ((TTree*) GetInputData(0))->GetCurrentFile()->GetName(), fESD->GetEventNumberInFile(), fESD->GetOrbitNumber(),fESD->GetPeriodNumber(),fESD->GetBunchCrossNumber(), nESDTracks05, nESDTracks10, nESDTracks14);
491 fMultiplicity->FillTriggeredEvent(nESDTracks05, nESDTracks10, nESDTracks14);
493 if (eventTriggered && eventVertex)
494 fMultiplicity->FillMeasured(vtx[2], nESDTracks05, nESDTracks10, nESDTracks14);
496 else if (fReadMC) // Processing of MC information
498 AliMCEventHandler* eventHandler = dynamic_cast<AliMCEventHandler*> (AliAnalysisManager::GetAnalysisManager()->GetMCtruthEventHandler());
500 Printf("ERROR: Could not retrieve MC event handler");
501 if (labelArr) delete[] labelArr;
502 if (etaArr) delete[] etaArr;
506 AliMCEvent* mcEvent = eventHandler->MCEvent();
508 Printf("ERROR: Could not retrieve MC event");
509 if (labelArr) delete[] labelArr;
510 if (etaArr) delete[] etaArr;
514 AliStack* stack = mcEvent->Stack();
517 AliDebug(AliLog::kError, "Stack not available");
518 if (labelArr) delete[] labelArr;
519 if (etaArr) delete[] etaArr;
523 AliHeader* header = mcEvent->Header();
526 AliDebug(AliLog::kError, "Header not available");
527 if (labelArr) delete[] labelArr;
528 if (etaArr) delete[] etaArr;
534 Printf("WARNING: Replacing vertex by MC vertex. This is for systematical checks only.");
536 AliGenEventHeader* genHeader = header->GenEventHeader();
538 genHeader->PrimaryVertex(vtxMC);
543 // get process information
544 AliPWG0Helper::MCProcessType processType = AliPWG0Helper::GetEventProcessType(fESD, header, stack, fDiffTreatment);
546 Bool_t processEvent = kTRUE;
547 if (fSelectProcessType > 0)
549 processEvent = kFALSE;
552 if (fSelectProcessType == 1 && processType == AliPWG0Helper::kND)
553 processEvent = kTRUE;
555 // single diffractive
556 if (fSelectProcessType == 2 && processType == AliPWG0Helper::kSD)
557 processEvent = kTRUE;
559 // double diffractive
560 if (fSelectProcessType == 3 && processType == AliPWG0Helper::kDD)
561 processEvent = kTRUE;
564 Printf("Skipping this event, because it is not of the requested process type (%d)", (Int_t) processType);
570 AliGenEventHeader* genHeader = header->GenEventHeader();
572 genHeader->PrimaryVertex(vtxMC);
574 // get number of tracks from MC
575 // loop over mc particles
576 Int_t nPrim = stack->GetNprimary();
577 Int_t nMCPart = stack->GetNtrack();
579 // tracks in different eta ranges
580 Int_t nMCTracks05 = 0;
581 Int_t nMCTracks10 = 0;
582 Int_t nMCTracks14 = 0;
583 Int_t nMCTracksAll = 0;
585 // tracks per particle species, in |eta| < 2 (systematic study)
586 Int_t nMCTracksSpecies[4]; // (pi, K, p, other)
587 for (Int_t i = 0; i<4; ++i)
588 nMCTracksSpecies[i] = 0;
590 for (Int_t iMc = 0; iMc < nPrim; ++iMc)
592 AliDebug(AliLog::kDebug+1, Form("MC Loop: Processing particle %d.", iMc));
594 TParticle* particle = stack->Particle(iMc);
598 AliDebug(AliLog::kError, Form("UNEXPECTED: particle with label %d not found in stack (mc loop).", iMc));
602 Bool_t debug = kFALSE;
603 if (AliPWG0Helper::IsPrimaryCharged(particle, nPrim, debug) == kFALSE)
605 //printf("%d) DROPPED ", iMC);
610 //printf("%d) OK ", iMC);
613 //if (particle->Pt() < kPtCut)
616 Int_t particleWeight = 1;
618 Float_t pt = particle->Pt();
620 // in case of systematic study, weight according to the change of the pt spectrum
621 // it cannot be just multiplied because we cannot count "half of a particle"
622 // instead a random generator decides if the particle is counted twice (if value > 1)
623 // or not (if value < 0)
626 Int_t bin = fPtSpectrum->FindBin(pt);
627 if (bin > 0 && bin <= fPtSpectrum->GetNbinsX())
629 Float_t factor = fPtSpectrum->GetBinContent(bin);
632 Float_t random = gRandom->Uniform();
633 if (factor > 1 && random < factor - 1)
637 else if (factor < 1 && random < 1 - factor)
643 //Printf("MC weight is: %d", particleWeight);
645 if (TMath::Abs(particle->Eta()) < 0.5)
646 nMCTracks05 += particleWeight;
648 if (TMath::Abs(particle->Eta()) < 1.0)
649 nMCTracks10 += particleWeight;
651 if (TMath::Abs(particle->Eta()) < 1.3)
652 nMCTracks14 += particleWeight;
654 nMCTracksAll += particleWeight;
656 if (particle->Pt() > 0 && TMath::Abs(particle->Eta()) < 1.0)
657 fdNdpT->Fill(particle->Pt(), 1.0 / particle->Pt());
659 if (fParticleCorrection[0] || fParticleSpecies)
662 switch (TMath::Abs(particle->GetPdgCode()))
664 case 211: id = 0; break;
665 case 321: id = 1; break;
666 case 2212: id = 2; break;
667 default: id = 3; break;
670 if (TMath::Abs(particle->Eta()) < etaRange)
671 nMCTracksSpecies[id]++;
673 if (fParticleCorrection[id])
674 fParticleCorrection[id]->GetTrackCorrection()->FillGene(vtxMC[2], particle->Eta(), particle->Pt());
676 } // end of mc particle
678 fMultiplicity->FillGenerated(vtxMC[2], eventTriggered, eventVertex, processType, (Int_t) nMCTracks05, (Int_t) nMCTracks10, (Int_t) nMCTracks14, (Int_t) nMCTracksAll);
681 Int_t nESDTracks05 = 0;
682 Int_t nESDTracks10 = 0;
683 Int_t nESDTracks14 = 0;
685 // tracks per particle species, in |eta| < 2 (systematic study)
686 Int_t nESDTracksSpecies[7]; // (pi, K, p, other, nolabel, doublecount_prim, doublecount_all)
687 for (Int_t i = 0; i<7; ++i)
688 nESDTracksSpecies[i] = 0;
690 Bool_t* foundPrimaries = new Bool_t[nMCPart]; // to prevent double counting
691 for (Int_t i=0; i<nPrim; i++)
692 foundPrimaries[i] = kFALSE;
694 Bool_t* foundPrimaries2 = new Bool_t[nMCPart]; // to prevent double counting
695 for (Int_t i=0; i<nPrim; i++)
696 foundPrimaries2[i] = kFALSE;
698 Bool_t* foundTracks = new Bool_t[nMCPart]; // to prevent double counting
699 for (Int_t i=0; i<nMCPart; i++)
700 foundTracks[i] = kFALSE;
702 for (Int_t i=0; i<inputCount; ++i)
704 Float_t eta = etaArr[i];
705 Int_t label = labelArr[i];
707 Int_t particleWeight = 1;
709 // in case of systematic study, weight according to the change of the pt spectrum
712 TParticle* mother = 0;
714 // preserve label for later
715 Int_t labelCopy = label;
717 labelCopy = AliPWG0Helper::FindPrimaryMotherLabel(stack, labelCopy);
719 mother = stack->Particle(labelCopy);
721 // in case of pt study we do not count particles w/o label, because they cannot be scaled
725 // it cannot be just multiplied because we cannot count "half of a particle"
726 // instead a random generator decides if the particle is counted twice (if value > 1)
727 // or not (if value < 0)
728 Int_t bin = fPtSpectrum->FindBin(mother->Pt());
729 if (bin > 0 && bin <= fPtSpectrum->GetNbinsX())
731 Float_t factor = fPtSpectrum->GetBinContent(bin);
734 Float_t random = gRandom->Uniform();
735 if (factor > 1 && random < factor - 1)
739 else if (factor < 1 && random < 1 - factor)
745 //Printf("ESD weight is: %d", particleWeight);
747 if (TMath::Abs(eta) < 0.5)
748 nESDTracks05 += particleWeight;
750 if (TMath::Abs(eta) < 1.0)
751 nESDTracks10 += particleWeight;
753 if (TMath::Abs(eta) < 1.3)
754 nESDTracks14 += particleWeight;
756 if (fParticleSpecies)
758 Int_t motherLabel = -1;
759 TParticle* mother = 0;
763 motherLabel = AliPWG0Helper::FindPrimaryMotherLabel(stack, label);
764 if (motherLabel >= 0)
765 mother = stack->Particle(motherLabel);
769 // count tracks that did not have a label
770 if (TMath::Abs(eta) < etaRange)
771 nESDTracksSpecies[4]++;
775 // get particle type (pion, proton, kaon, other) of mother
777 switch (TMath::Abs(mother->GetPdgCode()))
779 case 211: idMother = 0; break;
780 case 321: idMother = 1; break;
781 case 2212: idMother = 2; break;
782 default: idMother = 3; break;
785 // double counting is ok for particle ratio study
786 if (TMath::Abs(eta) < etaRange)
787 nESDTracksSpecies[idMother]++;
789 // double counting is not ok for efficiency study
791 // 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)
792 if (foundTracks[label])
794 if (TMath::Abs(eta) < etaRange)
795 nESDTracksSpecies[6]++;
799 foundTracks[label] = kTRUE;
801 // particle (primary) already counted?
802 if (foundPrimaries[motherLabel])
804 if (TMath::Abs(eta) < etaRange)
805 nESDTracksSpecies[5]++;
808 foundPrimaries[motherLabel] = kTRUE;
813 if (fParticleCorrection[0])
815 if (label >= 0 && stack->IsPhysicalPrimary(label))
817 TParticle* particle = stack->Particle(label);
819 // get particle type (pion, proton, kaon, other)
821 switch (TMath::Abs(particle->GetPdgCode()))
823 case 211: id = 0; break;
824 case 321: id = 1; break;
825 case 2212: id = 2; break;
826 default: id = 3; break;
829 // todo check if values are not completely off??
831 // particle (primary) already counted?
832 if (!foundPrimaries2[label])
834 foundPrimaries2[label] = kTRUE;
835 fParticleCorrection[id]->GetTrackCorrection()->FillMeas(vtxMC[2], particle->Eta(), particle->Pt());
841 if (fParticleCorrection[0])
843 // if the particle decays/stops before this radius we do not see it
844 // 8cm larger than SPD layer 2
845 // 123cm TPC radius where a track has about 50 clusters (cut limit)
846 const Float_t endRadius = (fAnalysisMode & AliPWG0Helper::kSPD) ? 8. : 123;
848 // loop over all primaries that have not been found
849 for (Int_t i=0; i<nPrim; i++)
852 if (foundPrimaries2[i])
855 TParticle* particle = 0;
856 TClonesArray* trackrefs = 0;
857 mcEvent->GetParticleAndTR(i, particle, trackrefs);
859 // true primary and charged
860 if (!AliPWG0Helper::IsPrimaryCharged(particle, nPrim))
863 //skip particles with larger |eta| than 3, to keep the log clean, is anyway not included in correction map
864 if (TMath::Abs(particle->Eta()) > 3)
867 // skipping checking of process type of daughter: Neither kPBrem, kPDeltaRay nor kPCerenkov should appear in the event generation
869 // get particle type (pion, proton, kaon, other)
871 switch (TMath::Abs(particle->GetPdgCode()))
873 case 211: id = 4; break;
874 case 321: id = 5; break;
875 case 2212: id = 6; break;
876 default: id = 7; break;
879 if (!fParticleCorrection[id])
882 // get last track reference
883 AliTrackReference* trackref = dynamic_cast<AliTrackReference*> (trackrefs->Last());
887 Printf("ERROR: Could not get trackref of %d (count %d)", i, trackrefs->GetEntries());
892 // particle in tracking volume long enough...
893 if (trackref->R() > endRadius)
896 if (particle->GetLastDaughter() >= 0)
898 Int_t uID = stack->Particle(particle->GetLastDaughter())->GetUniqueID();
899 //if (uID != kPBrem && uID != kPDeltaRay && uID < kPCerenkov)
904 Printf("Particle %d (%s) decayed at %f, daugher uniqueID: %d:", i, particle->GetName(), trackref->R(), uID);
906 Printf("Daugthers:");
907 for (Int_t d = particle->GetFirstDaughter(); d <= particle->GetLastDaughter(); d++)
908 stack->Particle(d)->Print();
911 fParticleCorrection[id]->GetTrackCorrection()->FillGene(vtxMC[2], particle->Eta(), particle->Pt());
916 if (trackref->DetectorId() == -1)
919 Printf("Particle %d stopped at %f:", i, trackref->R());
923 fParticleCorrection[id]->GetTrackCorrection()->FillMeas(vtxMC[2], particle->Eta(), particle->Pt());
927 Printf("Particle %d simply not tracked", i);
933 delete[] foundTracks;
934 delete[] foundPrimaries;
935 delete[] foundPrimaries2;
937 // if ((Int_t) nMCTracks14 > 10 && nESDTracks14 <= 3)
939 // TTree* tree = dynamic_cast<TTree*> (GetInputData(0));
940 // printf("WARNING: Event %lld %s (vtx-z = %f, recon: %f, contrib: %d, res: %f) has %d generated and %d reconstructed...\n", tree->GetReadEntry(), tree->GetCurrentFile()->GetName(), vtxMC[2], vtx[2], vtxESD->GetNContributors(), vtxESD->GetZRes(), nMCTracks14, nESDTracks14);
945 fMultiplicity->FillTriggeredEvent(nESDTracks05, nESDTracks10, nESDTracks14);
946 fMultiplicity->FillNoVertexEvent(vtxMC[2], eventVertex, nMCTracks05, nMCTracks10, nMCTracks14, nESDTracks05, nESDTracks10, nESDTracks14);
949 // if (nESDTracks05 == 0)
950 // fTemp1->Fill(nMCTracks05, nESDTracks05);
954 if (eventTriggered && eventVertex)
956 // fill response matrix using vtxMC (best guess)
957 fMultiplicity->FillCorrection(vtxMC[2], nMCTracks05, nMCTracks10, nMCTracks14, nMCTracksAll, nESDTracks05, nESDTracks10, nESDTracks14);
959 fMultiplicity->FillMeasured(vtx[2], nESDTracks05, nESDTracks10, nESDTracks14);
961 if (fParticleSpecies)
962 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]);
974 void AliMultiplicityTask::Terminate(Option_t *)
976 // The Terminate() function is the last function to be called during
977 // a query. It always runs on the client, it can be used to present
978 // the results graphically or save the results to file.
980 fOutput = dynamic_cast<TList*> (GetOutputData(0));
982 Printf("ERROR: fOutput not available");
986 fMultiplicity = dynamic_cast<AliMultiplicityCorrection*> (fOutput->FindObject("Multiplicity"));
987 for (Int_t i = 0; i < 8; ++i)
988 fParticleCorrection[i] = dynamic_cast<AliCorrection*> (fOutput->FindObject(Form("correction_%d", i)));
989 fParticleSpecies = dynamic_cast<TNtuple*> (fOutput->FindObject("fParticleSpecies"));
991 fdNdpT = dynamic_cast<TH1*> (fOutput->FindObject("fdNdpT"));
995 AliDebug(AliLog::kError, Form("ERROR: Histograms not available %p", (void*) fMultiplicity));
999 TString fileName("multiplicity");
1000 if (fSelectProcessType == 1)
1002 if (fSelectProcessType == 2)
1004 if (fSelectProcessType == 3)
1006 fileName += ".root";
1007 TFile* file = TFile::Open(fileName, "RECREATE");
1009 fMultiplicity->SaveHistograms();
1010 for (Int_t i = 0; i < 8; ++i)
1011 if (fParticleCorrection[i])
1012 fParticleCorrection[i]->SaveHistograms();
1013 if (fParticleSpecies)
1014 fParticleSpecies->Write();
1018 fTemp1 = dynamic_cast<TH1*> (fOutput->FindObject("fTemp1"));
1022 fEtaPhi = dynamic_cast<TH2F*> (fOutput->FindObject("fEtaPhi"));
1026 fVertex = dynamic_cast<TH3F*> (fOutput->FindObject("vertex_check"));
1030 for (Int_t i=0; i<3; i++)
1032 fEta[i] = dynamic_cast<TH1*> (fOutput->FindObject(Form("fEta_%d", i)));
1036 Float_t events = fMultiplicity->GetMultiplicityESD(i)->Integral(1, fMultiplicity->GetMultiplicityESD(i)->GetNbinsX());
1038 fEta[i]->Scale(1.0 / events);
1039 fEta[i]->Scale(1.0 / fEta[i]->GetXaxis()->GetBinWidth(1));
1044 TObjString option(fOption);
1049 Printf("Written result to %s", fileName.Data());