1 //====================================================================
2 #include "AliBasedNdetaTask.h"
8 #include <AliAnalysisManager.h>
9 #include <AliAODEvent.h>
10 #include <AliAODHandler.h>
11 #include <AliAODInputHandler.h>
12 #include "AliForwardUtil.h"
13 #include "AliAODForwardMult.h"
15 //____________________________________________________________________
16 AliBasedNdetaTask::AliBasedNdetaTask()
17 : AliAnalysisTaskSE(),
18 fSum(0), // Sum of histograms
19 fSumMC(0), // Sum of MC histograms (if any)
20 fSums(0), // Container of sums
21 fOutput(0), // Container of outputs
22 fTriggers(0), // Histogram of triggers
23 fVtxMin(0), // Minimum v_z
24 fVtxMax(0), // Maximum v_z
25 fTriggerMask(0), // Trigger mask
26 fRebin(0), // Rebinning factor
32 //____________________________________________________________________
33 AliBasedNdetaTask::AliBasedNdetaTask(const char* name)
34 : AliAnalysisTaskSE(name),
35 fSum(0), // Sum of histograms
36 fSumMC(0), // Sum of MC histograms (if any)
37 fSums(0), // Container of sums
38 fOutput(0), // Container of outputs
39 fTriggers(0), // Histogram of triggers
40 fVtxMin(-10), // Minimum v_z
41 fVtxMax(10), // Maximum v_z
42 fTriggerMask(AliAODForwardMult::kInel),
43 fRebin(5), // Rebinning factor
48 // Output slot #1 writes into a TH1 container
49 DefineOutput(1, TList::Class());
50 DefineOutput(2, TList::Class());
53 //____________________________________________________________________
54 AliBasedNdetaTask::AliBasedNdetaTask(const AliBasedNdetaTask& o)
55 : AliAnalysisTaskSE(o),
56 fSum(o.fSum), // TH2D* - Sum of histograms
57 fSumMC(o.fSumMC),// TH2D* - Sum of MC histograms (if any)
58 fSums(o.fSums), // TList* - Container of sums
59 fOutput(o.fOutput), // TList* - Container of outputs
60 fTriggers(o.fTriggers), // TH1D* - Histogram of triggers
61 fVtxMin(o.fVtxMin), // Double_t - Minimum v_z
62 fVtxMax(o.fVtxMax), // Double_t - Maximum v_z
63 fTriggerMask(o.fTriggerMask),// Int_t - Trigger mask
64 fRebin(o.fRebin), // Int_t - Rebinning factor
65 fCutEdges(o.fCutEdges), // Bool_t - Whether to cut edges when rebinning
70 //____________________________________________________________________
71 AliBasedNdetaTask::~AliBasedNdetaTask()
85 //________________________________________________________________________
87 AliBasedNdetaTask::SetTriggerMask(const char* mask)
93 TIter next(trgs.Tokenize(" ,|"));
94 while ((trg = static_cast<TObjString*>(next()))) {
95 TString s(trg->GetString());
96 if (s.IsNull()) continue;
97 if (s.CompareTo("INEL") == 0) trgMask = AliAODForwardMult::kInel;
98 else if (s.CompareTo("INEL>0")== 0) trgMask = AliAODForwardMult::kInelGt0;
99 else if (s.CompareTo("NSD") == 0) trgMask = AliAODForwardMult::kNSD;
101 Warning("SetTriggerMask", "Unknown trigger %s", s.Data());
103 if (trgMask == 0) trgMask = 1;
104 SetTriggerMask(trgMask);
107 //________________________________________________________________________
109 AliBasedNdetaTask::UserCreateOutputObjects()
112 // Called once (on the worker node)
115 fOutput->SetName(Form("%s_result", GetName()));
119 fSums->SetName(Form("%s_sums", GetName()));
123 fTriggers = new TH1D("triggers", "Number of triggers",
124 kAccepted, 1, kAccepted);
125 fTriggers->SetYTitle("# of events");
126 fTriggers->GetXaxis()->SetBinLabel(kAll, "All events");
127 fTriggers->GetXaxis()->SetBinLabel(kB, "w/B trigger");
128 fTriggers->GetXaxis()->SetBinLabel(kA, "w/A trigger");
129 fTriggers->GetXaxis()->SetBinLabel(kC, "w/C trigger");
130 fTriggers->GetXaxis()->SetBinLabel(kE, "w/E trigger");
131 fTriggers->GetXaxis()->SetBinLabel(kMB, "w/Collision trigger");
132 fTriggers->GetXaxis()->SetBinLabel(kWithVertex, "w/Vertex");
133 fTriggers->GetXaxis()->SetBinLabel(kWithTrigger, "w/Selected trigger");
134 fTriggers->GetXaxis()->SetBinLabel(kAccepted, "Accepted by cut");
135 fTriggers->GetXaxis()->SetNdivisions(kAccepted, false);
136 fTriggers->SetFillColor(kRed+1);
137 fTriggers->SetFillStyle(3001);
138 fTriggers->SetStats(0);
139 fSums->Add(fTriggers);
141 // Check that we have an AOD input handler
142 AliAnalysisManager* am = AliAnalysisManager::GetAnalysisManager();
143 AliAODInputHandler* ah =
144 dynamic_cast<AliAODInputHandler*>(am->GetInputEventHandler());
145 if (!ah) AliFatal("No AOD input handler set in analysis manager");
147 // Post data for ALL output slots >0 here, to get at least an empty histogram
151 //____________________________________________________________________
153 AliBasedNdetaTask::CloneHist(TH2D* in, const char* name)
156 TH2D* ret = static_cast<TH2D*>(in->Clone(name));
157 ret->SetDirectory(0);
164 //____________________________________________________________________
166 AliBasedNdetaTask::CheckEvent(AliAODEvent* aod)
168 TObject* oForward = aod->FindListObject("Forward");
170 AliWarning("No forward object found");
173 AliAODForwardMult* forward = static_cast<AliAODForwardMult*>(oForward);
176 fTriggers->AddBinContent(kAll);
177 if (forward->IsTriggerBits(AliAODForwardMult::kB))
178 fTriggers->AddBinContent(kB);
179 if (forward->IsTriggerBits(AliAODForwardMult::kA))
180 fTriggers->AddBinContent(kA);
181 if (forward->IsTriggerBits(AliAODForwardMult::kC))
182 fTriggers->AddBinContent(kC);
183 if (forward->IsTriggerBits(AliAODForwardMult::kE))
184 fTriggers->AddBinContent(kE);
185 if (forward->IsTriggerBits(AliAODForwardMult::kInel))
186 fTriggers->AddBinContent(kMB);
188 // Check if we have an event of interest.
189 if (!forward->IsTriggerBits(fTriggerMask)) return false;
190 fTriggers->AddBinContent(kWithTrigger);
192 // Check that we have a valid vertex
193 if (!forward->HasIpZ()) return false;
194 fTriggers->AddBinContent(kWithVertex);
196 // Check that vertex is within cuts
197 if (!forward->InRange(fVtxMin, fVtxMax)) return false;
198 fTriggers->AddBinContent(kAccepted);
202 //____________________________________________________________________
204 AliBasedNdetaTask::UserExec(Option_t *)
207 AliAODEvent* aod = dynamic_cast<AliAODEvent*>(InputEvent());
209 AliError("Cannot get the AOD event");
213 // Get the histogram(s)
214 TH2D* data = GetHistogram(aod);
215 TH2D* dataMC = GetHistogram(aod, true);
217 // We should have a base object at least
219 AliWarning("No data object found in AOD");
223 // Create our sum histograms
224 if (!fSum) fSum = CloneHist(data, GetName());
225 if (!fSumMC && dataMC) fSumMC = CloneHist(dataMC,Form("%sMC", GetName()));
228 if (!CheckEvent(aod)) return;
232 if (fSumMC) fSumMC->Add((dataMC));
237 //________________________________________________________________________
239 AliBasedNdetaTask::SetHistogramAttributes(TH1D* h, Int_t colour, Int_t marker,
240 const char* title, const char* ytitle)
243 h->SetMarkerColor(colour);
244 h->SetMarkerStyle(marker);
247 h->SetYTitle(ytitle);
248 h->GetXaxis()->SetTitleFont(132);
249 h->GetXaxis()->SetLabelFont(132);
250 h->GetXaxis()->SetNdivisions(10);
251 h->GetYaxis()->SetTitleFont(132);
252 h->GetYaxis()->SetLabelFont(132);
253 h->GetYaxis()->SetNdivisions(10);
254 h->GetYaxis()->SetDecimals();
258 //________________________________________________________________________
260 AliBasedNdetaTask::ProjectX(const TH2D* h,
269 return h->ProjectionX(name, firstbin, lastbin, (error ? "e" : ""));
272 TAxis* xaxis = h->GetXaxis();
273 TAxis* yaxis = h->GetYaxis();
274 TH1D* ret = new TH1D(name, h->GetTitle(), xaxis->GetNbins(),
275 xaxis->GetXmin(), xaxis->GetXmax());
276 static_cast<const TAttLine*>(h)->Copy(*ret);
277 static_cast<const TAttFill*>(h)->Copy(*ret);
278 static_cast<const TAttMarker*>(h)->Copy(*ret);
279 ret->GetXaxis()->ImportAttributes(xaxis);
281 Int_t first = firstbin;
282 Int_t last = lastbin;
283 if (first < 0) first = 0;
284 else if (first >= yaxis->GetNbins()+1) first = yaxis->GetNbins();
285 if (last < 0) last = yaxis->GetNbins();
286 else if (last > yaxis->GetNbins()+1) last = yaxis->GetNbins();
287 if (last-first < 0) {
288 AliWarning(Form("Nothing to project [%d,%d]", first, last));
294 // AliInfo(Form("Projecting bins [%d,%d] of %s", first, last, h->GetName()));
295 Int_t ybins = (last-first+1);
296 for (Int_t xbin = 0; xbin <= xaxis->GetNbins()+1; xbin++) {
297 Double_t content = 0;
302 for (Int_t ybin = first; ybin <= last; ybin++) {
303 Double_t c1 = h->GetCellContent(xbin, ybin);
304 Double_t e1 = h->GetCellError(xbin, ybin);
307 if (c1 < 1e-12) continue;
317 if(content > 0 && nbins > 0) {
318 Double_t factor = (corr ? Double_t(ybins) / nbins : 1);
320 // Calculate weighted average
321 ret->SetBinContent(xbin, content * factor);
322 ret->SetBinError(xbin, factor * TMath::Sqrt(error2));
325 ret->SetBinContent(xbin, factor * content);
332 //________________________________________________________________________
334 AliBasedNdetaTask::Terminate(Option_t *)
336 // Draw result to screen, or perform fitting, normalizations Called
337 // once at the end of the query
339 fSums = dynamic_cast<TList*> (GetOutputData(1));
341 AliError("Could not retrieve TList fSums");
347 fOutput->SetName(Form("%s_result", GetName()));
351 fSum = static_cast<TH2D*>(fSums->FindObject(GetName()));
352 fSumMC = static_cast<TH2D*>(fSums->FindObject(Form("%sMC", GetName())));
353 fTriggers = static_cast<TH1D*>(fSums->FindObject("triggers"));
356 AliError("Couldn't find histogram 'triggers' in list");
360 AliError("Couldn't find histogram 'base' in list");
364 Int_t nAll = Int_t(fTriggers->GetBinContent(kAll));
365 Int_t nB = Int_t(fTriggers->GetBinContent(kB));
366 Int_t nA = Int_t(fTriggers->GetBinContent(kA));
367 Int_t nC = Int_t(fTriggers->GetBinContent(kC));
368 Int_t nE = Int_t(fTriggers->GetBinContent(kE));
369 Int_t nMB = Int_t(fTriggers->GetBinContent(kMB));
370 Int_t nTriggered = Int_t(fTriggers->GetBinContent(kWithTrigger));
371 Int_t nWithVertex = Int_t(fTriggers->GetBinContent(kWithVertex));
372 Int_t nAccepted = Int_t(fTriggers->GetBinContent(kAccepted));
373 Int_t nGood = nB - nA - nC + 2 * nE;
374 if (nTriggered <= 0) {
375 AliError("Number of triggered events <= 0");
379 AliWarning(Form("Number of good events=%d=%d-%d-%d+2*%d<=0",
380 nGood, nB, nA, nC, nE));
383 Double_t vtxEff = Double_t(nMB) / nTriggered * Double_t(nAccepted) / nGood;
384 Double_t vNorm = Double_t(nAccepted) / nGood;
385 AliInfo(Form("Total of %9d events\n"
386 " of these %9d are minimum bias\n"
387 " of these %9d has a %s trigger\n"
388 " of these %9d has a vertex\n"
389 " of these %9d were in [%+4.1f,%+4.1f]cm\n"
390 " Triggers by type:\n"
392 " A|C = %9d (%9d+%-9d)\n"
394 " Implies %9d good triggers\n"
395 " Vertex efficiency: %f (%f)",
396 nAll, nMB, nTriggered,
397 AliAODForwardMult::GetTriggerString(fTriggerMask),
398 nWithVertex, nAccepted,
400 nB, nA+nC, nA, nC, nE, nGood, vtxEff, vNorm));
402 const char* name = GetName();
404 // Get acceptance normalisation from underflow bins
405 TH1D* norm = ProjectX(fSum, Form("norm%s",name), 0, 1, fCorrEmpty, false);
406 // Project onto eta axis - _ignoring_underflow_bins_!
407 TH1D* dndeta = ProjectX(fSum, Form("dndeta%s",name), 1, fSum->GetNbinsY(),
409 // Normalize to the acceptance
410 dndeta->Divide(norm);
411 // Scale by the vertex efficiency
412 dndeta->Scale(vNorm, "width");
413 norm->Scale(1. / nAccepted);
415 SetHistogramAttributes(dndeta, kRed+1, 20, Form("ALICE %s", name));
416 SetHistogramAttributes(norm, kRed+1,20,Form("ALICE %s normalisation", name));
418 fOutput->Add(fTriggers->Clone());
419 if (fSymmetrice) fOutput->Add(Symmetrice(dndeta));
420 fOutput->Add(dndeta);
422 fOutput->Add(Rebin(dndeta));
423 if (fSymmetrice) fOutput->Add(Symmetrice(Rebin(dndeta)));
426 // Get acceptance normalisation from underflow bins
427 TH1D* normMC = ProjectX(fSumMC,Form("norm%sMC", name), 0, 1,
429 // Project onto eta axis - _ignoring_underflow_bins_!
430 TH1D* dndetaMC = ProjectX(fSumMC,Form("dndeta%sMC", name),1,
431 fSum->GetNbinsY(), fCorrEmpty);
432 // Normalize to the acceptance
433 dndetaMC->Divide(normMC);
434 // Scale by the vertex efficiency
435 dndetaMC->Scale(vNorm, "width");
436 normMC->Scale(1. / nAccepted);
438 SetHistogramAttributes(dndetaMC, kRed+3, 21, Form("ALICE %s (MC)",name));
439 SetHistogramAttributes(normMC, kRed+3, 21, Form("ALICE %s (MC) "
440 "normalisation",name));
442 fOutput->Add(dndetaMC);
443 if (fSymmetrice) fOutput->Add(Symmetrice(dndetaMC));
444 fOutput->Add(normMC);
445 fOutput->Add(Rebin(dndetaMC));
446 if (fSymmetrice) fOutput->Add(Symmetrice(Rebin(dndetaMC)));
450 new TNamed("trigString", AliAODForwardMult::GetTriggerString(fTriggerMask));
451 trigString->SetUniqueID(fTriggerMask);
452 fOutput->Add(trigString);
454 TAxis* vtxAxis = new TAxis(1,fVtxMin,fVtxMax);
455 vtxAxis->SetName("vtxAxis");
456 vtxAxis->SetTitle(Form("v_{z}#in[%+5.1f,%+5.1f]cm", fVtxMin,fVtxMax));
457 fOutput->Add(vtxAxis);
459 PostData(2, fOutput);
462 //________________________________________________________________________
464 AliBasedNdetaTask::Rebin(const TH1D* h) const
466 if (fRebin <= 1) return 0;
468 Int_t nBins = h->GetNbinsX();
469 if(nBins % fRebin != 0) {
470 Warning("Rebin", "Rebin factor %d is not a devisor of current number "
471 "of bins %d in the histogram %s", fRebin, nBins, h->GetName());
476 TH1D* tmp = static_cast<TH1D*>(h->Clone(Form("%s_rebin%02d",
477 h->GetName(), fRebin)));
479 tmp->SetDirectory(0);
481 // The new number of bins
482 Int_t nBinsNew = nBins / fRebin;
483 for(Int_t i = 1;i<= nBinsNew; i++) {
484 Double_t content = 0;
488 for(Int_t j = 1; j<=fRebin;j++) {
489 Int_t bin = (i-1)*fRebin + j;
490 Double_t c = h->GetBinContent(bin);
492 if (c <= 0) continue;
495 if (h->GetBinContent(bin+1)<=0 ||
496 h->GetBinContent(bin-1)) {
497 Warning("Rebin", "removing bin %d=%f of %s (%d=%f,%d=%f)",
498 bin, c, h->GetName(),
499 bin+1, h->GetBinContent(bin+1),
500 bin-1, h->GetBinContent(bin-1));
504 Double_t e = h->GetBinError(bin);
505 Double_t w = 1 / (e*e); // 1/c/c
512 if(content > 0 && nbins > 0) {
513 tmp->SetBinContent(i, wsum / sumw);
514 tmp->SetBinError(i,1./TMath::Sqrt(sumw));
521 //__________________________________________________________________
523 * Make an extension of @a h to make it symmetric about 0
525 * @param h Histogram to symmertrice
527 * @return Symmetric extension of @a h
530 AliBasedNdetaTask::Symmetrice(const TH1* h) const
532 Int_t nBins = h->GetNbinsX();
533 TH1* s = static_cast<TH1*>(h->Clone(Form("%s_mirror", h->GetName())));
534 s->SetTitle(Form("%s (mirrored)", h->GetTitle()));
536 s->SetBins(nBins, -h->GetXaxis()->GetXmax(), -h->GetXaxis()->GetXmin());
537 s->SetMarkerColor(h->GetMarkerColor());
538 s->SetMarkerSize(h->GetMarkerSize());
539 s->SetMarkerStyle(h->GetMarkerStyle()+4);
540 s->SetFillColor(h->GetFillColor());
541 s->SetFillStyle(h->GetFillStyle());
544 // Find the first and last bin with data
545 Int_t first = nBins+1;
547 for (Int_t i = 1; i <= nBins; i++) {
548 if (h->GetBinContent(i) <= 0) continue;
549 first = TMath::Min(first, i);
550 last = TMath::Max(last, i);
553 Double_t xfirst = h->GetBinCenter(first-1);
554 Int_t f1 = h->GetXaxis()->FindBin(-xfirst);
555 Int_t l2 = s->GetXaxis()->FindBin(xfirst);
556 for (Int_t i = f1, j=l2; i <= last; i++,j--) {
557 s->SetBinContent(j, h->GetBinContent(i));
558 s->SetBinError(j, h->GetBinError(i));
560 // Fill in overlap bin
561 s->SetBinContent(l2+1, h->GetBinContent(first));
562 s->SetBinError(l2+1, h->GetBinError(first));