]> git.uio.no Git - u/mrichter/AliRoot.git/blame - PWG0/multiplicity/AliMultiplicityTask.cxx
factoring out AliTriggerAnalysis class
[u/mrichter/AliRoot.git] / PWG0 / multiplicity / AliMultiplicityTask.cxx
CommitLineData
a9017e49 1/* $Id$ */
2
3#include "AliMultiplicityTask.h"
4
5#include <TStyle.h>
6#include <TSystem.h>
7#include <TCanvas.h>
8#include <TVector3.h>
9#include <TChain.h>
10#include <TFile.h>
69b09e3b 11#include <TH1D.h>
a9017e49 12#include <TH2F.h>
13#include <TH3F.h>
14#include <TParticle.h>
15#include <TRandom.h>
16#include <TNtuple.h>
17#include <TObjString.h>
18#include <TF1.h>
19
20#include <AliLog.h>
21#include <AliESDVertex.h>
22#include <AliESDEvent.h>
23#include <AliStack.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>
31
745d6088 32#include "AliESDtrackCuts.h"
a9017e49 33#include "AliPWG0Helper.h"
0a0f4adb 34#include "multiplicity/AliMultiplicityCorrection.h"
a9017e49 35#include "AliCorrection.h"
36#include "AliCorrectionMatrix3D.h"
70fdd197 37#include "AliTriggerAnalysis.h"
a9017e49 38
a9017e49 39ClassImp(AliMultiplicityTask)
40
41AliMultiplicityTask::AliMultiplicityTask(const char* opt) :
42 AliAnalysisTask("AliMultiplicityTask", ""),
43 fESD(0),
44 fOption(opt),
70fdd197 45 fAnalysisMode((AliPWG0Helper::AnalysisMode) (AliPWG0Helper::kSPD | AliPWG0Helper::kFieldOn)),
46 fTrigger(AliTriggerAnalysis::kMB1),
69b09e3b 47 fDeltaPhiCut(-1),
2fa65f52 48 fReadMC(kFALSE),
f3eb27f6 49 fUseMCVertex(kFALSE),
a9017e49 50 fMultiplicity(0),
51 fEsdTrackCuts(0),
52 fSystSkipParticles(kFALSE),
53 fSelectProcessType(0),
54 fParticleSpecies(0),
69b09e3b 55 fdNdpT(0),
a9017e49 56 fPtSpectrum(0),
57 fOutput(0)
58{
59 //
60 // Constructor. Initialization of pointers
61 //
62
69b09e3b 63 for (Int_t i = 0; i<8; i++)
a9017e49 64 fParticleCorrection[i] = 0;
65
66 // Define input and output slots here
67 DefineInput(0, TChain::Class());
68 DefineOutput(0, TList::Class());
69}
70
71AliMultiplicityTask::~AliMultiplicityTask()
72{
73 //
74 // Destructor
75 //
76
77 // histograms are in the output list and deleted when the output
78 // list is deleted by the TSelector dtor
79
80 if (fOutput) {
81 delete fOutput;
82 fOutput = 0;
83 }
84}
85
86//________________________________________________________________________
87void AliMultiplicityTask::ConnectInputData(Option_t *)
88{
89 // Connect ESD
90 // Called once
91
2fa65f52 92 Printf("AliMultiplicityTask::ConnectInputData called");
93
a9017e49 94 TTree* tree = dynamic_cast<TTree*> (GetInputData(0));
95 if (!tree) {
96 Printf("ERROR: Could not read tree from input slot 0");
97 } else {
98 // Disable all branches and enable only the needed ones
69b09e3b 99 /*
f3eb27f6 100 tree->SetBranchStatus("*", 0);
2fa65f52 101
f3eb27f6 102 tree->SetBranchStatus("AliESDHeader*", 1);
103 tree->SetBranchStatus("*Vertex*", 1);
a9017e49 104
70fdd197 105 if (fAnalysisMode & AliPWG0Helper::kSPD) {
f3eb27f6 106 tree->SetBranchStatus("AliMultiplicity*", 1);
107 }
a9017e49 108
70fdd197 109 if (fAnalysisMode & AliPWG0Helper::kTPC || fAnalysisMode & AliPWG0Helper::kTPCITS) {
f3eb27f6 110 //AliESDtrackCuts::EnableNeededBranches(tree);
111 tree->SetBranchStatus("Tracks*", 1);
2fa65f52 112 }
69b09e3b 113 */
a9017e49 114
a9017e49 115 AliESDInputHandler *esdH = dynamic_cast<AliESDInputHandler*> (AliAnalysisManager::GetAnalysisManager()->GetInputEventHandler());
116
117 if (!esdH) {
118 Printf("ERROR: Could not get ESDInputHandler");
119 } else
120 fESD = esdH->GetEvent();
121 }
f3eb27f6 122
123 // disable info messages of AliMCEvent (per event)
124 AliLog::SetClassDebugLevel("AliMCEvent", AliLog::kWarning - AliLog::kDebug + 1);
a9017e49 125}
126
127void AliMultiplicityTask::CreateOutputObjects()
128{
129 // create result objects and add to output list
130
131 fOutput = new TList;
132 fOutput->SetOwner();
133
134 fMultiplicity = new AliMultiplicityCorrection("Multiplicity", "Multiplicity");
135 fOutput->Add(fMultiplicity);
69b09e3b 136
137 fdNdpT = new TH1F("fdNdpT", "fdNdpT", 1000, 0, 10);
138 fdNdpT->Sumw2();
139 fOutput->Add(fdNdpT);
a9017e49 140
141 if (fOption.Contains("skip-particles"))
142 {
143 fSystSkipParticles = kTRUE;
144 AliInfo("WARNING: Systematic study enabled. Particles will be skipped.");
145 }
146
147 if (fOption.Contains("particle-efficiency"))
69b09e3b 148 for (Int_t i = 0; i<8; i++)
a9017e49 149 {
150 fParticleCorrection[i] = new AliCorrection(Form("correction_%d", i), Form("correction_%d", i));
151 fOutput->Add(fParticleCorrection[i]);
152 }
153
154 if (fOption.Contains("only-process-type-nd"))
155 fSelectProcessType = 1;
156
157 if (fOption.Contains("only-process-type-sd"))
158 fSelectProcessType = 2;
159
160 if (fOption.Contains("only-process-type-dd"))
161 fSelectProcessType = 3;
162
163 if (fSelectProcessType != 0)
164 AliInfo(Form("WARNING: Systematic study enabled. Only considering process type %d", fSelectProcessType));
165
166 if (fOption.Contains("pt-spectrum-hist"))
167 {
168 TFile* file = TFile::Open("ptspectrum_fit.root");
169 if (file)
170 {
171 TString subStr(fOption(fOption.Index("pt-spectrum")+17, 3));
172 TString histName(Form("ptspectrum_%s", subStr.Data()));
173 AliInfo(Form("Pt-Spectrum modification. Using %s.", histName.Data()));
69b09e3b 174 fPtSpectrum = (TH1D*) file->Get(histName);
175 if (!fPtSpectrum)
176 AliError("Histogram not found");
a9017e49 177 }
178 else
179 AliError("Could not open ptspectrum_fit.root. Pt Spectrum study could not be enabled.");
a9017e49 180 }
181
182 if (fOption.Contains("pt-spectrum-func"))
183 {
184 if (fPtSpectrum)
185 {
69b09e3b 186 Printf("Using function for systematic p_t study");
a9017e49 187 }
188 else
189 {
69b09e3b 190 Printf("ERROR: Could not find function for systematic p_t study");
191 fPtSpectrum = new TH1D("fPtSpectrum", "fPtSpectrum", 1, 0, 100);
a9017e49 192 fPtSpectrum->SetBinContent(1, 1);
193 }
a9017e49 194 }
195
69b09e3b 196 if (fPtSpectrum)
197 Printf("WARNING: Systematic study enabled. Pt spectrum will be modified");
198
a9017e49 199 if (fOption.Contains("particle-species")) {
200 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");
201 fOutput->Add(fParticleSpecies);
202 }
203
204 // TODO set seed for random generator
205}
206
207void AliMultiplicityTask::Exec(Option_t*)
208{
209 // process the event
210
211 // Check prerequisites
212 if (!fESD)
213 {
745d6088 214 AliDebug(AliLog::kError, "ESD not available");
a9017e49 215 return;
216 }
217
70fdd197 218 static AliTriggerAnalysis* triggerAnalysis = new AliTriggerAnalysis;
219 Bool_t eventTriggered = triggerAnalysis->IsTriggerFired(fESD, fTrigger);
7dcf959e 220 //Printf("%lld", fESD->GetTriggerMask());
a9017e49 221
f3eb27f6 222 const AliESDVertex* vtxESD = AliPWG0Helper::GetVertex(fESD, fAnalysisMode);
223 Bool_t eventVertex = (vtxESD != 0);
a9017e49 224
a9017e49 225 Double_t vtx[3];
f3eb27f6 226 if (vtxESD)
227 vtxESD->GetXYZ(vtx);
a9017e49 228
2fa65f52 229 // post the data already here
230 PostData(0, fOutput);
69b09e3b 231
a9017e49 232 //const Float_t kPtCut = 0.3;
233
2fa65f52 234 // create list of (label, eta) tuples
235 Int_t inputCount = 0;
236 Int_t* labelArr = 0;
237 Float_t* etaArr = 0;
70fdd197 238 if (fAnalysisMode & AliPWG0Helper::kSPD)
a9017e49 239 {
2fa65f52 240 // get tracklets
241 const AliMultiplicity* mult = fESD->GetMultiplicity();
242 if (!mult)
a9017e49 243 {
2fa65f52 244 AliDebug(AliLog::kError, "AliMultiplicity not available");
245 return;
a9017e49 246 }
247
2fa65f52 248 labelArr = new Int_t[mult->GetNumberOfTracklets()];
249 etaArr = new Float_t[mult->GetNumberOfTracklets()];
250
251 // get multiplicity from ITS tracklets
252 for (Int_t i=0; i<mult->GetNumberOfTracklets(); ++i)
a9017e49 253 {
2fa65f52 254 //printf("%d %f %f %f\n", i, mult->GetTheta(i), mult->GetPhi(i), mult->GetDeltaPhi(i));
a9017e49 255
69b09e3b 256 Float_t deltaPhi = mult->GetDeltaPhi(i);
257
258 if (fDeltaPhiCut > 0 && TMath::Abs(deltaPhi) > fDeltaPhiCut)
2fa65f52 259 continue;
a9017e49 260
2fa65f52 261 etaArr[inputCount] = mult->GetEta(i);
69b09e3b 262 if (mult->GetLabel(i, 0) == mult->GetLabel(i, 1))
263 {
264 labelArr[inputCount] = mult->GetLabel(i, 0);
265 }
266 else
267 labelArr[inputCount] = -1;
268
2fa65f52 269 ++inputCount;
270 }
271 }
70fdd197 272 else if (fAnalysisMode & AliPWG0Helper::kTPC || fAnalysisMode & AliPWG0Helper::kTPCITS)
2fa65f52 273 {
274 if (!fEsdTrackCuts)
275 {
276 AliDebug(AliLog::kError, "fESDTrackCuts not available");
277 return;
278 }
a9017e49 279
69b09e3b 280 if (vtxESD)
a9017e49 281 {
69b09e3b 282 // get multiplicity from ESD tracks
70fdd197 283 TObjArray* list = fEsdTrackCuts->GetAcceptedTracks(fESD, (fAnalysisMode & AliPWG0Helper::kTPC));
69b09e3b 284 Int_t nGoodTracks = list->GetEntries();
285
286 labelArr = new Int_t[nGoodTracks];
287 etaArr = new Float_t[nGoodTracks];
288
289 // loop over esd tracks
290 for (Int_t i=0; i<nGoodTracks; i++)
a9017e49 291 {
69b09e3b 292 AliESDtrack* esdTrack = dynamic_cast<AliESDtrack*> (list->At(i));
293 if (!esdTrack)
294 {
295 AliDebug(AliLog::kError, Form("ERROR: Could not retrieve track %d.", i));
296 continue;
297 }
298
299 etaArr[inputCount] = esdTrack->Eta();
300 labelArr[inputCount] = TMath::Abs(esdTrack->GetLabel());
301 ++inputCount;
a9017e49 302 }
69b09e3b 303
304 delete list;
a9017e49 305 }
2fa65f52 306 }
a9017e49 307
2fa65f52 308 // eta range for nMCTracksSpecies, nESDTracksSpecies
70fdd197 309 Float_t etaRange = 1.0;
310// switch (fAnalysisMode) {
311// case AliPWG0Helper::kInvalid: break;
312// case AliPWG0Helper::kTPC:
313// case AliPWG0Helper::kTPCITS:
314// etaRange = 1.0; break;
315// case AliPWG0Helper::kSPD: etaRange = 1.0; break;
316// default: break;
317// }
a9017e49 318
2fa65f52 319 if (!fReadMC) // Processing of ESD information
320 {
321 if (eventTriggered && eventVertex)
322 {
323 Int_t nESDTracks05 = 0;
69b09e3b 324 Int_t nESDTracks10 = 0;
b3b260d1 325 Int_t nESDTracks14 = 0;
a9017e49 326
2fa65f52 327 for (Int_t i=0; i<inputCount; ++i)
328 {
329 Float_t eta = etaArr[i];
a9017e49 330
2fa65f52 331 if (TMath::Abs(eta) < 0.5)
332 nESDTracks05++;
a9017e49 333
69b09e3b 334 if (TMath::Abs(eta) < 1.0)
335 nESDTracks10++;
a9017e49 336
b3b260d1 337 if (TMath::Abs(eta) < 1.4)
338 nESDTracks14++;
a9017e49 339 }
2fa65f52 340
b3b260d1 341 fMultiplicity->FillMeasured(vtx[2], nESDTracks05, nESDTracks10, nESDTracks14);
2fa65f52 342 }
343 }
344 else if (fReadMC) // Processing of MC information
345 {
346 AliMCEventHandler* eventHandler = dynamic_cast<AliMCEventHandler*> (AliAnalysisManager::GetAnalysisManager()->GetMCtruthEventHandler());
347 if (!eventHandler) {
348 Printf("ERROR: Could not retrieve MC event handler");
349 return;
a9017e49 350 }
a9017e49 351
2fa65f52 352 AliMCEvent* mcEvent = eventHandler->MCEvent();
353 if (!mcEvent) {
354 Printf("ERROR: Could not retrieve MC event");
355 return;
356 }
a9017e49 357
2fa65f52 358 AliStack* stack = mcEvent->Stack();
359 if (!stack)
360 {
361 AliDebug(AliLog::kError, "Stack not available");
362 return;
363 }
69b09e3b 364
2fa65f52 365 AliHeader* header = mcEvent->Header();
366 if (!header)
367 {
368 AliDebug(AliLog::kError, "Header not available");
369 return;
370 }
a9017e49 371
f3eb27f6 372 if (fUseMCVertex)
373 {
374 Printf("WARNING: Replacing vertex by MC vertex. This is for systematical checks only.");
375 // get the MC vertex
376 AliGenEventHeader* genHeader = header->GenEventHeader();
377 TArrayF vtxMC(3);
378 genHeader->PrimaryVertex(vtxMC);
379
380 vtx[2] = vtxMC[2];
381 }
69b09e3b 382
383 // get process information
384 AliPWG0Helper::MCProcessType processType = AliPWG0Helper::GetEventProcessType(header);
f3eb27f6 385
2fa65f52 386 Bool_t processEvent = kTRUE;
387 if (fSelectProcessType > 0)
388 {
2fa65f52 389 processEvent = kFALSE;
a9017e49 390
2fa65f52 391 // non diffractive
69b09e3b 392 if (fSelectProcessType == 1 && processType == AliPWG0Helper::kND)
2fa65f52 393 processEvent = kTRUE;
a9017e49 394
2fa65f52 395 // single diffractive
69b09e3b 396 if (fSelectProcessType == 2 && processType == AliPWG0Helper::kSD)
2fa65f52 397 processEvent = kTRUE;
a9017e49 398
2fa65f52 399 // double diffractive
69b09e3b 400 if (fSelectProcessType == 3 && processType == AliPWG0Helper::kDD)
2fa65f52 401 processEvent = kTRUE;
a9017e49 402
2fa65f52 403 if (!processEvent)
69b09e3b 404 Printf("Skipping this event, because it is not of the requested process type (%d)", (Int_t) processType);
2fa65f52 405 }
a9017e49 406
2fa65f52 407 if (processEvent)
408 {
409 // get the MC vertex
410 AliGenEventHeader* genHeader = header->GenEventHeader();
411 TArrayF vtxMC(3);
412 genHeader->PrimaryVertex(vtxMC);
413
414 // get number of tracks from MC
415 // loop over mc particles
416 Int_t nPrim = stack->GetNprimary();
417 Int_t nMCPart = stack->GetNtrack();
418
419 // tracks in different eta ranges
420 Int_t nMCTracks05 = 0;
69b09e3b 421 Int_t nMCTracks10 = 0;
b3b260d1 422 Int_t nMCTracks14 = 0;
2fa65f52 423 Int_t nMCTracksAll = 0;
424
425 // tracks per particle species, in |eta| < 2 (systematic study)
426 Int_t nMCTracksSpecies[4]; // (pi, K, p, other)
427 for (Int_t i = 0; i<4; ++i)
428 nMCTracksSpecies[i] = 0;
429
430 for (Int_t iMc = 0; iMc < nPrim; ++iMc)
431 {
432 AliDebug(AliLog::kDebug+1, Form("MC Loop: Processing particle %d.", iMc));
a9017e49 433
2fa65f52 434 TParticle* particle = stack->Particle(iMc);
a9017e49 435
2fa65f52 436 if (!particle)
437 {
438 AliDebug(AliLog::kError, Form("UNEXPECTED: particle with label %d not found in stack (mc loop).", iMc));
439 continue;
440 }
a9017e49 441
2fa65f52 442 Bool_t debug = kFALSE;
443 if (AliPWG0Helper::IsPrimaryCharged(particle, nPrim, debug) == kFALSE)
444 {
445 //printf("%d) DROPPED ", iMC);
446 //particle->Print();
447 continue;
448 }
a9017e49 449
2fa65f52 450 //printf("%d) OK ", iMC);
451 //particle->Print();
a9017e49 452
2fa65f52 453 //if (particle->Pt() < kPtCut)
454 // continue;
a9017e49 455
2fa65f52 456 Int_t particleWeight = 1;
a9017e49 457
2fa65f52 458 Float_t pt = particle->Pt();
a9017e49 459
2fa65f52 460 // in case of systematic study, weight according to the change of the pt spectrum
461 // it cannot be just multiplied because we cannot count "half of a particle"
462 // instead a random generator decides if the particle is counted twice (if value > 1)
463 // or not (if value < 0)
464 if (fPtSpectrum)
a9017e49 465 {
2fa65f52 466 Int_t bin = fPtSpectrum->FindBin(pt);
467 if (bin > 0 && bin <= fPtSpectrum->GetNbinsX())
a9017e49 468 {
2fa65f52 469 Float_t factor = fPtSpectrum->GetBinContent(bin);
470 if (factor > 0)
471 {
472 Float_t random = gRandom->Uniform();
473 if (factor > 1 && random < factor - 1)
474 {
475 particleWeight = 2;
476 }
477 else if (factor < 1 && random < 1 - factor)
478 particleWeight = 0;
479 }
a9017e49 480 }
a9017e49 481 }
a9017e49 482
2fa65f52 483 //Printf("MC weight is: %d", particleWeight);
a9017e49 484
2fa65f52 485 if (TMath::Abs(particle->Eta()) < 0.5)
486 nMCTracks05 += particleWeight;
a9017e49 487
69b09e3b 488 if (TMath::Abs(particle->Eta()) < 1.0)
489 nMCTracks10 += particleWeight;
a9017e49 490
b3b260d1 491 if (TMath::Abs(particle->Eta()) < 1.4)
492 nMCTracks14 += particleWeight;
a9017e49 493
2fa65f52 494 nMCTracksAll += particleWeight;
69b09e3b 495
496 if (particle->Pt() > 0 && TMath::Abs(particle->Eta()) < 1.0)
497 fdNdpT->Fill(particle->Pt(), 1.0 / particle->Pt());
a9017e49 498
2fa65f52 499 if (fParticleCorrection[0] || fParticleSpecies)
500 {
501 Int_t id = -1;
502 switch (TMath::Abs(particle->GetPdgCode()))
503 {
504 case 211: id = 0; break;
505 case 321: id = 1; break;
506 case 2212: id = 2; break;
507 default: id = 3; break;
508 }
a9017e49 509
2fa65f52 510 if (TMath::Abs(particle->Eta()) < etaRange)
511 nMCTracksSpecies[id]++;
512
513 if (fParticleCorrection[id])
514 fParticleCorrection[id]->GetTrackCorrection()->FillGene(vtxMC[2], particle->Eta(), particle->Pt());
515 }
516 } // end of mc particle
a9017e49 517
b3b260d1 518 fMultiplicity->FillGenerated(vtxMC[2], eventTriggered, eventVertex, processType, (Int_t) nMCTracks05, (Int_t) nMCTracks10, (Int_t) nMCTracks14, (Int_t) nMCTracksAll);
a9017e49 519
2fa65f52 520 if (eventTriggered && eventVertex)
a9017e49 521 {
2fa65f52 522 Int_t nESDTracks05 = 0;
69b09e3b 523 Int_t nESDTracks10 = 0;
b3b260d1 524 Int_t nESDTracks14 = 0;
a9017e49 525
2fa65f52 526 // tracks per particle species, in |eta| < 2 (systematic study)
527 Int_t nESDTracksSpecies[7]; // (pi, K, p, other, nolabel, doublecount_prim, doublecount_all)
528 for (Int_t i = 0; i<7; ++i)
529 nESDTracksSpecies[i] = 0;
a9017e49 530
2fa65f52 531 Bool_t* foundPrimaries = new Bool_t[nPrim]; // to prevent double counting
532 for (Int_t i=0; i<nPrim; i++)
533 foundPrimaries[i] = kFALSE;
a9017e49 534
69b09e3b 535 Bool_t* foundPrimaries2 = new Bool_t[nPrim]; // to prevent double counting
536 for (Int_t i=0; i<nPrim; i++)
537 foundPrimaries2[i] = kFALSE;
538
2fa65f52 539 Bool_t* foundTracks = new Bool_t[nMCPart]; // to prevent double counting
540 for (Int_t i=0; i<nMCPart; i++)
541 foundTracks[i] = kFALSE;
a9017e49 542
2fa65f52 543 for (Int_t i=0; i<inputCount; ++i)
544 {
545 Float_t eta = etaArr[i];
546 Int_t label = labelArr[i];
a9017e49 547
2fa65f52 548 Int_t particleWeight = 1;
549
69b09e3b 550 // systematic study: 5% lower efficiency
551 if (fSystSkipParticles && (gRandom->Uniform() < 0.05))
552 continue;
553
2fa65f52 554 // in case of systematic study, weight according to the change of the pt spectrum
555 if (fPtSpectrum)
556 {
557 TParticle* mother = 0;
558
559 // preserve label for later
560 Int_t labelCopy = label;
561 if (labelCopy >= 0)
562 labelCopy = AliPWG0Helper::FindPrimaryMotherLabel(stack, labelCopy);
563 if (labelCopy >= 0)
564 mother = stack->Particle(labelCopy);
565
566 // in case of pt study we do not count particles w/o label, because they cannot be scaled
567 if (!mother)
568 continue;
569
570 // it cannot be just multiplied because we cannot count "half of a particle"
571 // instead a random generator decides if the particle is counted twice (if value > 1)
572 // or not (if value < 0)
573 Int_t bin = fPtSpectrum->FindBin(mother->Pt());
574 if (bin > 0 && bin <= fPtSpectrum->GetNbinsX())
575 {
576 Float_t factor = fPtSpectrum->GetBinContent(bin);
577 if (factor > 0)
578 {
579 Float_t random = gRandom->Uniform();
580 if (factor > 1 && random < factor - 1)
581 {
582 particleWeight = 2;
583 }
584 else if (factor < 1 && random < 1 - factor)
585 particleWeight = 0;
586 }
587 }
588 }
589
590 //Printf("ESD weight is: %d", particleWeight);
591
592 if (TMath::Abs(eta) < 0.5)
593 nESDTracks05 += particleWeight;
a9017e49 594
69b09e3b 595 if (TMath::Abs(eta) < 1.0)
596 nESDTracks10 += particleWeight;
a9017e49 597
b3b260d1 598 if (TMath::Abs(eta) < 1.4)
599 nESDTracks14 += particleWeight;
a9017e49 600
69b09e3b 601 if (fParticleSpecies)
2fa65f52 602 {
603 Int_t motherLabel = -1;
604 TParticle* mother = 0;
605
606 // find mother
607 if (label >= 0)
608 motherLabel = AliPWG0Helper::FindPrimaryMotherLabel(stack, label);
609 if (motherLabel >= 0)
610 mother = stack->Particle(motherLabel);
611
612 if (!mother)
613 {
614 // count tracks that did not have a label
615 if (TMath::Abs(eta) < etaRange)
616 nESDTracksSpecies[4]++;
2fa65f52 617 }
69b09e3b 618 else
2fa65f52 619 {
69b09e3b 620 // get particle type (pion, proton, kaon, other) of mother
621 Int_t idMother = -1;
622 switch (TMath::Abs(mother->GetPdgCode()))
623 {
624 case 211: idMother = 0; break;
625 case 321: idMother = 1; break;
626 case 2212: idMother = 2; break;
627 default: idMother = 3; break;
628 }
629
630 // double counting is ok for particle ratio study
631 if (TMath::Abs(eta) < etaRange)
632 nESDTracksSpecies[idMother]++;
633
634 // double counting is not ok for efficiency study
635
636 // 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)
637 if (foundTracks[label])
638 {
639 if (TMath::Abs(eta) < etaRange)
640 nESDTracksSpecies[6]++;
641 }
642 else
643 {
644 foundTracks[label] = kTRUE;
645
646 // particle (primary) already counted?
647 if (foundPrimaries[motherLabel])
648 {
649 if (TMath::Abs(eta) < etaRange)
650 nESDTracksSpecies[5]++;
651 }
652 else
653 foundPrimaries[motherLabel] = kTRUE;
654 }
2fa65f52 655 }
69b09e3b 656 }
657
658 if (fParticleCorrection[0])
659 {
660 if (label >= 0 && stack->IsPhysicalPrimary(label))
661 {
662 TParticle* particle = stack->Particle(label);
2fa65f52 663
69b09e3b 664 // get particle type (pion, proton, kaon, other)
665 Int_t id = -1;
666 switch (TMath::Abs(particle->GetPdgCode()))
667 {
668 case 211: id = 0; break;
669 case 321: id = 1; break;
670 case 2212: id = 2; break;
671 default: id = 3; break;
672 }
2fa65f52 673
69b09e3b 674 // todo check if values are not completely off??
2fa65f52 675
69b09e3b 676 // particle (primary) already counted?
677 if (!foundPrimaries2[label])
678 {
679 foundPrimaries2[label] = kTRUE;
680 fParticleCorrection[id]->GetTrackCorrection()->FillMeas(vtxMC[2], particle->Eta(), particle->Pt());
681 }
682 }
683 }
684 }
685
686 if (fParticleCorrection[0])
687 {
688 // if the particle decays/stops before this radius we do not see it
689 // 8cm larger than SPD layer 2
690 // 123cm TPC radius where a track has about 50 clusters (cut limit)
70fdd197 691 const Float_t endRadius = (fAnalysisMode & AliPWG0Helper::kSPD) ? 8. : 123;
69b09e3b 692
693 // loop over all primaries that have not been found
694 for (Int_t i=0; i<nPrim; i++)
695 {
696 // already found
697 if (foundPrimaries2[i])
698 continue;
699
700 TParticle* particle = 0;
701 TClonesArray* trackrefs = 0;
702 mcEvent->GetParticleAndTR(i, particle, trackrefs);
703
704 // true primary and charged
705 if (!AliPWG0Helper::IsPrimaryCharged(particle, nPrim))
706 continue;
707
708 //skip particles with larger |eta| than 3, to keep the log clean, is anyway not included in correction map
709 if (TMath::Abs(particle->Eta()) > 3)
710 continue;
711
712 // skipping checking of process type of daughter: Neither kPBrem, kPDeltaRay nor kPCerenkov should appear in the event generation
713
714 // get particle type (pion, proton, kaon, other)
715 Int_t id = -1;
716 switch (TMath::Abs(particle->GetPdgCode()))
2fa65f52 717 {
69b09e3b 718 case 211: id = 4; break;
719 case 321: id = 5; break;
720 case 2212: id = 6; break;
721 default: id = 7; break;
722 }
723
724 if (!fParticleCorrection[id])
725 continue;
726
727 // get last track reference
728 AliTrackReference* trackref = dynamic_cast<AliTrackReference*> (trackrefs->Last());
729
730 if (!trackref)
731 {
732 Printf("ERROR: Could not get trackref of %d (count %d)", i, trackrefs->GetEntries());
733 particle->Print();
2fa65f52 734 continue;
735 }
69b09e3b 736
737 // particle in tracking volume long enough...
738 if (trackref->R() > endRadius)
739 continue;
740
741 if (particle->GetLastDaughter() >= 0)
2fa65f52 742 {
69b09e3b 743 Int_t uID = stack->Particle(particle->GetLastDaughter())->GetUniqueID();
744 //if (uID != kPBrem && uID != kPDeltaRay && uID < kPCerenkov)
745 if (uID == kPDecay)
746 {
747 // decayed
748
749 Printf("Particle %d (%s) decayed at %f, daugher uniqueID: %d:", i, particle->GetName(), trackref->R(), uID);
750 particle->Print();
751 Printf("Daughers:");
752 for (Int_t d = particle->GetFirstDaughter(); d <= particle->GetLastDaughter(); d++)
753 stack->Particle(d)->Print();
754 Printf("");
755
756 fParticleCorrection[id]->GetTrackCorrection()->FillGene(vtxMC[2], particle->Eta(), particle->Pt());
757 continue;
758 }
759 }
760
761 if (trackref->DetectorId() == -1)
762 {
763 // stopped
764 Printf("Particle %d stopped at %f:", i, trackref->R());
765 particle->Print();
766 Printf("");
767
768 fParticleCorrection[id]->GetTrackCorrection()->FillMeas(vtxMC[2], particle->Eta(), particle->Pt());
2fa65f52 769 continue;
770 }
69b09e3b 771
772 Printf("Particle %d simply not tracked", i);
773 particle->Print();
774 Printf("");
2fa65f52 775 }
776 }
69b09e3b 777
2fa65f52 778 delete[] foundTracks;
779 delete[] foundPrimaries;
69b09e3b 780 delete[] foundPrimaries2;
a9017e49 781
b3b260d1 782 if ((Int_t) nMCTracks14 > 10 && nESDTracks14 <= 3)
f3eb27f6 783 {
784 TTree* tree = dynamic_cast<TTree*> (GetInputData(0));
b3b260d1 785 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);
f3eb27f6 786 }
a9017e49 787
2fa65f52 788 // fill response matrix using vtxMC (best guess)
b3b260d1 789 fMultiplicity->FillCorrection(vtxMC[2], nMCTracks05, nMCTracks10, nMCTracks14, nMCTracksAll, nESDTracks05, nESDTracks10, nESDTracks14);
a9017e49 790
b3b260d1 791 fMultiplicity->FillMeasured(vtx[2], nESDTracks05, nESDTracks10, nESDTracks14);
2fa65f52 792
793 if (fParticleSpecies)
794 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]);
795 }
796 }
797 }
a9017e49 798
69b09e3b 799 if (etaArr)
800 delete[] etaArr;
801 if (labelArr)
802 delete[] labelArr;
a9017e49 803}
804
805void AliMultiplicityTask::Terminate(Option_t *)
806{
807 // The Terminate() function is the last function to be called during
808 // a query. It always runs on the client, it can be used to present
809 // the results graphically or save the results to file.
810
811 fOutput = dynamic_cast<TList*> (GetOutputData(0));
812 if (!fOutput) {
813 Printf("ERROR: fOutput not available");
814 return;
815 }
816
817 fMultiplicity = dynamic_cast<AliMultiplicityCorrection*> (fOutput->FindObject("Multiplicity"));
69b09e3b 818 for (Int_t i = 0; i < 8; ++i)
a9017e49 819 fParticleCorrection[i] = dynamic_cast<AliCorrection*> (fOutput->FindObject(Form("correction_%d", i)));
820 fParticleSpecies = dynamic_cast<TNtuple*> (fOutput->FindObject("fParticleSpecies"));
69b09e3b 821
822 fdNdpT = dynamic_cast<TH1*> (fOutput->FindObject("fdNdpT"));
a9017e49 823
824 if (!fMultiplicity)
825 {
826 AliDebug(AliLog::kError, Form("ERROR: Histograms not available %p", (void*) fMultiplicity));
827 return;
828 }
829
dca331bb 830 TFile* file = TFile::Open("multiplicity.root", "RECREATE");
a9017e49 831
832 fMultiplicity->SaveHistograms();
69b09e3b 833 for (Int_t i = 0; i < 8; ++i)
a9017e49 834 if (fParticleCorrection[i])
835 fParticleCorrection[i]->SaveHistograms();
836 if (fParticleSpecies)
837 fParticleSpecies->Write();
69b09e3b 838 if (fdNdpT)
839 fdNdpT->Write();
a9017e49 840
841 TObjString option(fOption);
842 option.Write();
843
844 file->Close();
845
7dcf959e 846 Printf("Written result to multiplicity.root");
a9017e49 847}