2 * @mainpage Forward/Backward Correlations
4 * A script containing a class ForwardBackwardTask and a
5 * function to run the analysis.
7 * The class ForwardBackwardTask is an AliAnalysisTaskSE. That means
8 * that it have facilities for analysing ESD, AOD, and MC input. The
9 * process of running the code is handled by an AliAnalysisManager
10 * (created in the function). It uses a TSelector to loop over a
13 * The flow of the code is
15 * +-----------------------+
16 * | Create Analysis Train |-> ForwardBackwardTask constructor
17 * +-----------------------+
20 * +-----------------------+
21 * | Intialise all tasks |-> ForwardBackwardTask::Init (not implemented)
22 * +-----------------------+
25 * +-----------------------+
26 * | Split job on workers |
27 * +-----------------------+
30 * +-----------------------+
31 * | Create output objects |-> ForwardBackwardTask::CreateOutputObjects
33 * +-----------------------+
36 * +-----------------------+
37 * | More events on this |<-----+
38 * | worker node? |--+ |
39 * +-----------------------+ | |
42 * | +-------------------+
43 * | | Process one event |->ForwardBackwardTask::UserExec
44 * | +-------------------+
47 * +-----------------------+
48 * | Merge output of each |
50 * +-----------------------+
53 * +-----------------------+
54 * | End of job processing |-> ForwardBackwardTask::Terminate
55 * +-----------------------+
58 * Since the class ForwardBackwardTask derives from a compiled class
59 * (AliAnalysisTaskSE) we need to compile that code. The script will,
60 * when executed in the AliROOT prompt load it self again and byte
61 * compile it with the preprocessor flag BUILD defined. \
63 * The preprocessor define BUILD is not defined at first, when the
64 * script is loaded using
67 * Root> .x ForwardBackward.C
70 * which means that CINT will only see the function ForwardBackward.
71 * In that function, we define the BUILD preprocessor symbol
74 * gSystem->AddIncludePath("-DBUILD=1 ...");
77 * and then ACLic compile ourselves
80 * gROOT->LoadMacro("./SPDComparison.C++");
83 * But since BUILD is now defined, it means that ACLic will only see
84 * the class and not the function SPDComparison.
86 * This trick hinges on that when you initially load the script and
87 * when it is done inside the script it is done using two distinct
88 * paths - otherwise ROOT will try to unload the script first, and
94 #include <AliAnalysisTaskSE.h>
95 #include <AliESDEvent.h>
97 #include <AliMultiplicity.h>
98 #include "AliFMDEventInspector.h"
99 #include "AliAODForwardMult.h"
102 #include <TGraphErrors.h>
104 #include <TObjArray.h>
109 * @class SPDComparisonTask
111 * Task to do forward/backward correlations using FMD and SPD
114 * The class contains the sub-structure Bin that represents an
115 * @f$\eta@f$ range. One can add (possibly overlapping) @f$\eta@f$
116 * ranges by calling the member function AddBin
119 class SPDComparisonTask : public AliAnalysisTaskSE
123 * A single vertex bin - contains summed histogram of clusters and
127 struct VtxBin : public TNamed
130 * Static function to get a bin name
132 * @param low Low limit
133 * @param high High limit
135 * @return Pointer to static array
137 static const char* BinName(Double_t low, Double_t high)
140 n = (Form("vtx%+05.1f_%+05.1f", low, high));
141 n.ReplaceAll("+", "p");
142 n.ReplaceAll("-", "m");
143 n.ReplaceAll(".", "d");
149 * @param low Low limit
150 * @param high High limit
152 VtxBin(Double_t low, Double_t high)
153 : TNamed(BinName(low,high), ""),
161 VtxBin() : TNamed(), fClusters(0), fTracklets(0) {}
165 * @param o Object to copy from
167 VtxBin(const VtxBin& o) :
168 TNamed(o), fClusters(o.fClusters), fTracklets(o.fTracklets)
171 * Assignment operator
173 * @param o Object to assign from
175 * @return Reference to this.
177 VtxBin& operator=(const VtxBin& o)
179 TNamed::operator=(o);
180 fClusters = o.fClusters;
181 fTracklets = o.fTracklets;
187 * @param l Output list
188 * @param eta Eta axis to use
190 void DefineOutput(TList* l, const TAxis& eta)
192 TList* ll = new TList;
193 ll->SetName(GetName());
197 fClusters = new TH1D("clusters", "Clusters",
201 fClusters->SetXTitle("#eta");
202 fClusters->SetYTitle("dN/d#eta");
203 fClusters->SetDirectory(0);
207 fTracklets = static_cast<TH1D*>(fClusters->Clone("tracklets"));
208 fTracklets->SetTitle("Tracklets");
209 fTracklets->SetDirectory(0);
215 * @param spdmult Input
217 void Process(const AliMultiplicity* spdmult)
219 //Filling clusters in layer 1 used for tracklets...
220 for(Int_t j = 0; j< spdmult->GetNumberOfTracklets();j++) {
221 Double_t eta = spdmult->GetEta(j);
222 fClusters->Fill(eta);
223 fTracklets->Fill(eta);
226 //...and then the unused ones in layer 1
227 for(Int_t j = 0; j< spdmult->GetNumberOfSingleClusters();j++) {
228 Double_t eta = -TMath::Log(TMath::Tan(spdmult->GetThetaSingle(j)/2.));
229 fClusters->Fill(eta);
233 * End of job processing
235 * @param l Output list
236 * @param nEvents Number of events to normalise to
238 void Finish(TList* l, Int_t nEvents)
240 TList* ll = static_cast<TList*>(l->FindObject(GetName()));
241 fClusters = static_cast<TH1D*>(ll->FindObject("clusters"));
242 fTracklets = static_cast<TH1D*>(ll->FindObject("tracklets"));
243 fClusters->Scale(1. / nEvents, "width");
244 fTracklets->Scale(1. / nEvents, "width");
245 TH1* ratio = static_cast<TH1D*>(fClusters->Clone("ratio"));
246 ratio->SetDirectory(0);
247 ratio->SetTitle("Clusters/Tracklets");
248 ratio->Divide(fTracklets);
251 TH1D* fClusters; // Cluster histogram
252 TH1D* fTracklets; // Tracklet histogram
255 //__________________________________________________________________
257 * Default constructor - do not use
260 : AliAnalysisTaskSE(),
266 fVertexAxis(20, -20, 20)
269 * Constructor with a single argument.
271 SPDComparisonTask(const char*)
272 : AliAnalysisTaskSE("spdComparision"),
273 fInspector("eventInspector"),
278 fVertexAxis(20, -20, 20)
280 // Declare our output container
281 DefineOutput(1,TList::Class());
286 * @param o Object to copy from
288 SPDComparisonTask(const SPDComparisonTask& o)
289 : AliAnalysisTaskSE(o),
290 fInspector(o.fInspector),
294 fFirstEvent(o.fFirstEvent),
295 fVertexAxis(20, -20, 20)
297 SetVertexAxis(o.fVertexAxis);
302 * @param o Object to assign from
304 * @return Reference to this
306 SPDComparisonTask& operator=(const SPDComparisonTask& o)
308 AliAnalysisTaskSE::operator=(o);
309 fInspector = o.fInspector;
312 fFirstEvent = o.fFirstEvent;
313 SetVertexAxis(o.fVertexAxis);
319 ~SPDComparisonTask() {}
321 * Set the vertex axis to use
323 * @param a Axis to set from
325 void SetVertexAxis(const TAxis& a)
327 SetVertexAxis(a.GetNbins(),
332 * Set the vertex axis to use
334 * @param n Number of bins
335 * @param xmin Least @f$v_z@f$
336 * @param xmax Most @f$v_z@f$
338 void SetVertexAxis(Int_t n, Double_t xmin, Double_t xmax)
340 fVertexAxis.Set(n, xmin, xmax);
343 * Create output objects
346 void UserCreateOutputObjects()
349 fList->SetName(GetName());
353 fEvents = new TH1D("events", "Events",
354 fVertexAxis.GetNbins(),
355 fVertexAxis.GetXmin(),
356 fVertexAxis.GetXmax());
357 fEvents->SetDirectory(0);
358 fEvents->SetXTitle("v_{z} [cm]");
361 TAxis& vtxAxis = fVertexAxis;
362 fBins = new TObjArray(vtxAxis.GetNbins(),1);
364 TAxis etaAxis(120, -3, 3);
365 for (Int_t i = 1; i <= vtxAxis.GetNbins(); i++) {
366 VtxBin* bin = new VtxBin(vtxAxis.GetBinLowEdge(i),
367 vtxAxis.GetBinUpEdge(i));
368 bin->DefineOutput(fList, etaAxis);
373 fInspector.DefineOutput(fList);
374 fInspector.Init(*(fEvents->GetXaxis()));
381 * @param option Not used
383 void UserExec(Option_t* option="")
385 // Get the input data - ESD event
386 AliESDEvent* esd = dynamic_cast<AliESDEvent*>(InputEvent());
388 AliWarning("No ESD event found for input event");
392 //--- Read run information -----------------------------------------
393 if (fFirstEvent && esd->GetESDRun()) {
394 fInspector.ReadRunDetails(esd);
396 AliInfo(Form("Initializing with parameters from the ESD:\n"
397 " AliESDEvent::GetBeamEnergy() ->%f\n"
398 " AliESDEvent::GetBeamType() ->%s\n"
399 " AliESDEvent::GetCurrentL3() ->%f\n"
400 " AliESDEvent::GetMagneticField()->%f\n"
401 " AliESDEvent::GetRunNumber() ->%d\n",
402 esd->GetBeamEnergy(),
405 esd->GetMagneticField(),
406 esd->GetRunNumber()));
413 UInt_t triggers; // Trigger bits
414 Bool_t lowFlux; // Low flux flag
415 UShort_t iVz; // Vertex bin from ESD
416 Double_t vZ; // Z coordinate from ESD
417 Double_t cent; // Centrality
418 UShort_t nClusters;// Number of SPD clusters
420 UInt_t retESD = fInspector.Process(esd, triggers, lowFlux, iVz, vZ,
422 Bool_t isInel = triggers & AliAODForwardMult::kB;
423 Bool_t hasVtx = retESD == AliFMDEventInspector::kOk;
425 if (!isInel || !hasVtx) return;
428 const AliMultiplicity* spdmult = esd->GetMultiplicity();
430 VtxBin* bin = static_cast<VtxBin*>(fBins->At(iVz));
432 AliError(Form("No bin @ %d (%fcm)", iVz, vZ));
435 bin->Process(spdmult);
437 // Post data to output container
441 * Called at the end of the processing
445 void Terminate(Option_t* option="")
447 fList = dynamic_cast<TList*>(GetOutputData(1));
449 AliError("No output list defined");
453 fEvents = static_cast<TH1D*>(fList->FindObject("events"));
455 Int_t nEvents = fEvents->GetEntries();
456 AliInfo(Form("Got a total of %d events", nEvents));
463 while ((bin = static_cast<VtxBin*>(next()))) {
464 bin->Finish(fList, fEvents->GetBinContent(i++));
465 if (!clusters) clusters = static_cast<TH1D*>(bin->fClusters->Clone());
466 else clusters->Add(bin->fClusters);
467 if (!tracklets) tracklets = static_cast<TH1D*>(bin->fTracklets->Clone());
468 else tracklets->Add(bin->fTracklets);
470 clusters->SetDirectory(0);
471 tracklets->SetDirectory(0);
472 clusters->Scale(1. / i);
473 tracklets->Scale(1. / i);
476 TH1D* ratio = static_cast<TH1D*>(clusters->Clone("ratio"));
477 ratio->SetDirectory(0);
478 ratio->SetTitle("Clusters/Tracklets");
479 ratio->Divide(tracklets);
481 fList->Add(clusters);
482 fList->Add(tracklets);
486 AliFMDEventInspector fInspector; // Inspector
487 TObjArray* fBins; // Vertex bins
488 TH1D* fEvents; // Events
489 TList* fList; // Output list
490 Bool_t fFirstEvent;// First event flag
493 ClassDef(SPDComparisonTask,1); // BF analysis
497 //====================================================================
501 * @param aoddir Input directory
502 * @param nEvents Number of events, negative means all
505 SPDComparison(const char* esddir, Int_t nEvents=-1)
507 // --- Libraries to load -------------------------------------------
508 gROOT->Macro("$ALICE_ROOT/PWG2/FORWARD/analysis2/scripts/LoadLibs.C");
510 // --- Our data chain ----------------------------------------------
511 gROOT->LoadMacro("$ALICE_ROOT/PWG2/FORWARD/analysis2/scripts/MakeChain.C");
512 TChain* chain = MakeChain("ESD", esddir, true);
513 // If 0 or less events is select, choose all
514 if (nEvents <= 0) nEvents = chain->GetEntries();
516 // --- Manager -----------------------------------------------------
517 AliAnalysisManager* mgr = new AliAnalysisManager("FB", "FB train");
518 AliAnalysisManager::SetCommonFileName("spd_comps.root");
520 // --- AOD input handler -------------------------------------------
521 AliESDInputHandler *inputHandler = new AliESDInputHandler();
522 mgr->SetInputEventHandler(inputHandler);
524 // --- compile our code --------------------------------------------
525 gSystem->AddIncludePath("-I${ALICE_ROOT}/PWG2/FORWARD/analysis2 "
526 "-I${ALICE_ROOT}/ANALYSIS "
527 "-I${ALICE_ROOT}/include -DBUILD=1");
528 gROOT->LoadMacro("./SPDComparison.C++g");
530 // --- Make our object ---------------------------------------------
531 SPDComparisonTask* task = new SPDComparisonTask("SPD_COMP");
532 task->SetVertexAxis(10, -10, 10);
535 // --- create containers for input/output --------------------------
536 AliAnalysisDataContainer *sums =
537 mgr->CreateContainer("spdComp", TList::Class(),
538 AliAnalysisManager::kOutputContainer,
539 AliAnalysisManager::GetCommonFileName());
540 // --- connect input/output ----------------------------------------
541 mgr->ConnectInput(task, 0, mgr->GetCommonInputContainer());
542 mgr->ConnectOutput(task, 1, sums);
544 // --- Run the analysis --------------------------------------------
546 if (!mgr->InitAnalysis()) {
547 Error("SPDComparison", "Failed to initialize analysis train!");
550 // Some informative output
552 // mgr->SetDebugLevel(3);
553 if (mgr->GetDebugLevel() < 1) mgr->SetUseProgressBar(kTRUE,100);
557 Printf("=== RUNNING ANALYSIS on %9d events ==================", nEvents);
558 mgr->StartAnalysis("local", chain, nEvents);
565 //====================================================================
572 DrawSPDComparison(const char* filename="spd_comps.root")
574 // --- Open the file -----------------------------------------------
575 TFile* file = TFile::Open(filename, "READ");
577 Error("DrawSPDComparison", "Failed to open file %s", filename);
581 // --- Get our list ------------------------------------------------
582 TList* spd = static_cast<TList*>(file->Get("spdComp"));
584 Error("DrawSPDComparison", "Failed to get list SPD_COMP from file %s",
589 // --- Loop over list and get correlation plots --------------------
590 TH1* clusters = static_cast<TH1*>(spd->FindObject("clusters"));
591 TH1* tracklets = static_cast<TH1*>(spd->FindObject("tracklets"));
592 TH1* ratio = static_cast<TH1*>(spd->FindObject("ratio"));
593 TH1* events = static_cast<TH1*>(spd->FindObject("events"));
595 // --- Set style parameters ----------------------------------------
596 gStyle->SetPalette(1);
597 gStyle->SetTitleFillColor(0);
598 gStyle->SetTitleStyle(0);
599 gStyle->SetTitleBorderSize(0);
600 gStyle->SetOptStat(0);
601 gStyle->SetTitleX(0.69);
602 gStyle->SetTitleY(0.99);
603 gStyle->SetTitleW(0.30);
604 gStyle->SetTitleH(0.10);
606 // --- Make canvas for correlation plots and plot them -------------
607 TCanvas* c1 = new TCanvas("c1", "c1", 900, 600);
608 c1->SetTopMargin(0.05);
609 c1->SetRightMargin(0.05);
612 c1->SetBorderSize(0);
613 c1->SetBorderMode(0);
616 TPad* p1 = new TPad("p1","p1", 0.0, 0.3, 1.0, 1.0, 0, 0, 0);
619 p1->SetBorderSize(0);
620 p1->SetBorderMode(0);
621 p1->SetTopMargin(0.05);
622 p1->SetBottomMargin(0.001);
623 p1->SetRightMargin(0.05);
626 clusters->SetMarkerStyle(20);
627 clusters->SetMarkerColor(kRed+1);
630 tracklets->SetMarkerStyle(20);
631 tracklets->SetMarkerColor(kBlue+1);
632 tracklets->Draw("same");
634 TString v(Form("%+5.1f<|v_{z}|<%+5.1f",
635 events->GetXaxis()->GetXmin(),
636 events->GetXaxis()->GetXmax()));
637 TLatex* ltx = new TLatex(.2,.80, v.Data());
640 TLegend* l = p1->BuildLegend(.6,.6,.94,.94);
646 TPad* p2 = new TPad("p2","p2", 0.0, 0.0, 1.0, 0.3, 0, 0, 0);
649 p2->SetBorderSize(0);
650 p2->SetBorderMode(0);
651 p2->SetTopMargin(0.001);
652 p2->SetBottomMargin(0.2);
653 p2->SetRightMargin(0.05);
656 ratio->SetMarkerStyle(20);
657 ratio->SetMarkerColor(kGray+1);
659 ratio->GetYaxis()->SetRangeUser(0,2);
661 c1->SaveAs("SPDComparison.png");
662 c1->SaveAs("SPDComparison.root");