Added pointer (0 in default version) for revertexing cuts
[u/mrichter/AliRoot.git] / ANALYSIS / macros / AODtrain.C
1 // ### Settings that make sense when using the Alien plugin
2 //==============================================================================
3 Int_t       runOnData          = 1;       // Set to 1 if processing real data
4 Int_t       iCollision         = 0;       // 0=pp, 1=Pb-Pb
5 Int_t       run_flag           = 1100;    // year (2011 = 1100)
6 //==============================================================================
7 Bool_t      doCDBconnect        =1;
8 Bool_t      usePhysicsSelection = kTRUE; // use physics selection
9 Bool_t      useTender           = kFALSE; // use tender wagon
10 Bool_t      useCentrality       = kTRUE; // centrality
11 Bool_t      useV0tender         = kFALSE;  // use V0 correction in tender
12 Bool_t      useDBG              = kTRUE;  // activate debugging
13 Bool_t      useMC               = kFALSE;  // use MC info
14 Bool_t      useKFILTER          = kFALSE;  // use Kinematics filter
15 Bool_t      useTR               = kFALSE;  // use track references
16 Bool_t      useCORRFW           = kFALSE; // do not change
17 Bool_t      useAODTAGS          = kFALSE; // use AOD tags
18 Bool_t      useSysInfo          = kFALSE; // use sys info
19
20 // ### Analysis modules to be included. Some may not be yet fully implemented.
21 //==============================================================================
22 Int_t       iAODhandler        = 1;      // Analysis produces an AOD or dAOD's
23 Int_t       iESDfilter         = 1;      // ESD to AOD filter (barrel + muon tracks)
24 Int_t       iESDfilterReVtx    = -1;     // Request revertexing in ESD filtering
25 Int_t       iMUONcopyAOD       = 1;      // Task that copies only muon events in a separate AOD (PWG3)
26 Int_t       iJETAN             = 1;      // Jet analysis (PWG4)
27 Int_t       iJETANdelta        = 1;      // Jet delta AODs
28 Int_t       iPWGHFvertexing     = 1;      // Vertexing HF task (PWG3)
29 Int_t       iPWGDQJPSIfilter    = 0;      // JPSI filtering (PWG3)
30 Int_t       iPWGHFd2h           = 1;      // D0->2 hadrons (PWG3)
31 Int_t       iPWGPP               =1;      // high pt filter task
32 Int_t       iPWGLFForward       = 1;      // Forward mult task (PWGLF)
33 Bool_t doPIDResponse  = 1;
34 Bool_t doPIDqa        = 1; //new
35
36 // ### Configuration macros used for each module
37 //==============================================================================
38  TString configPWGHFd2h = (iCollision==0)?"$ALICE_ROOT/PWGHF/vertexingHF/ConfigVertexingHF.C"
39                           :"$ALICE_ROOT/PWGHF/vertexingHF/ConfigVertexingHF_highmult.C";
40
41
42 Double_t    *cutsESDfilterReVtx = 0;     // optional cuts for revertexing
43                                              
44 // Temporaries.
45 void AODmerge();
46 void AddAnalysisTasks();
47 Bool_t LoadCommonLibraries();
48 Bool_t LoadAnalysisLibraries();
49 Bool_t LoadLibrary(const char *);
50 TChain *CreateChain();
51 const char *cdbPath = "raw://";
52 Int_t run_number = 0;
53
54 //______________________________________________________________________________
55 void AODtrain(Int_t merge=0)
56 {
57 // Main analysis train macro.
58
59   if (merge || doCDBconnect) {
60     TGrid::Connect("alien://");
61     if (!gGrid || !gGrid->IsConnected()) {
62       ::Error("QAtrain", "No grid connection");
63       return;
64     }
65   }
66   // Set temporary merging directory to current one
67   gSystem->Setenv("TMPDIR", gSystem->pwd());
68   // Set temporary compilation directory to current one
69   gSystem->SetBuildDir(gSystem->pwd(), kTRUE);
70    printf("==================================================================\n");
71    printf("===========    RUNNING FILTERING TRAIN   ==========\n");
72    printf("==================================================================\n");
73    printf("=  Configuring analysis train for:                               =\n");
74    if (usePhysicsSelection)   printf("=  Physics selection                                                =\n");
75    if (useTender)    printf("=  TENDER                                                        =\n");
76    if (iESDfilter)   {
77      printf("=  ESD filter                                                    =\n");
78      if (iESDfilterReVtx>=0)  printf("=  ESD event revertexed before filterering, algo %2d              =\n",iESDfilterReVtx);
79    }
80    if (iMUONcopyAOD) printf("=  MUON copy AOD                                                 =\n");
81    if (iJETAN)       printf("=  Jet analysis                                                  =\n");
82    if (iJETANdelta)  printf("=     Jet delta AODs                                             =\n");
83    if (iPWGHFvertexing) printf("=  PWGHF vertexing                                                =\n");
84    if (iPWGDQJPSIfilter) printf("=  PWGDQ j/psi filter                                             =\n");
85    if (iPWGHFd2h) printf("=  PWGHF D0->2 hadrons QA                                     =\n");
86
87    // Load common libraries and set include path
88    if (!LoadCommonLibraries()) {
89       ::Error("AnalysisTrain", "Could not load common libraries");
90       return;
91    }
92     
93    // Make the analysis manager and connect event handlers
94    AliAnalysisManager *mgr  = new AliAnalysisManager("Analysis Train", "Production train");
95    if (useSysInfo) mgr->SetNSysInfo(100);
96    // Load analysis specific libraries
97    if (!LoadAnalysisLibraries()) {
98       ::Error("AnalysisTrain", "Could not load analysis libraries");
99       return;
100    }   
101
102    // Create input handler (input container created automatically)
103    // ESD input handler
104    AliESDInputHandler *esdHandler = new AliESDInputHandler();
105    mgr->SetInputEventHandler(esdHandler);       
106    // Monte Carlo handler
107    if (useMC) {
108       AliMCEventHandler* mcHandler = new AliMCEventHandler();
109       mgr->SetMCtruthEventHandler(mcHandler);
110       mcHandler->SetReadTR(useTR); 
111    }   
112    // AOD output container, created automatically when setting an AOD handler
113    if (iAODhandler) {
114       // AOD output handler
115       AliAODHandler* aodHandler   = new AliAODHandler();
116       aodHandler->SetOutputFileName("AliAOD.root");
117       mgr->SetOutputEventHandler(aodHandler);
118    }
119    // Debugging if needed
120    if (useDBG) mgr->SetDebugLevel(3);
121
122    AddAnalysisTasks(cdbPath);
123    if (merge) {
124       AODmerge();
125       mgr->InitAnalysis();
126       mgr->SetGridHandler(new AliAnalysisAlien);
127       mgr->StartAnalysis("gridterminate",0);
128       return;
129    }   
130    // Run the analysis                                                                                                                     
131    //
132    TChain *chain = CreateChain();
133    if (!chain) return;
134                                                                                                                                                    
135    TStopwatch timer;
136    timer.Start();
137    mgr->SetSkipTerminate(kTRUE);
138    if (mgr->InitAnalysis()) {
139       mgr->PrintStatus();
140       mgr->StartAnalysis("local", chain);
141    }
142    timer.Print();
143 }                                                                                                                                          
144                                                                                                                                             
145 //______________________________________________________________________________                                                           
146 void AddAnalysisTasks(const char *cdb_location){                                                                                                                                          
147   // Add all analysis task wagons to the train                                                                                               
148    AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();                                                                     
149
150   //
151   // Tender and supplies. Needs to be called for every event.
152   //
153    AliAnalysisManager::SetCommonFileName("AODQA.root");
154    if (useTender) {
155       gROOT->LoadMacro("$ALICE_ROOT/ANALYSIS/TenderSupplies/AddTaskTender.C");
156       // IF V0 tender needed, put kTRUE below
157       AliAnalysisTaskSE *tender = AddTaskTender(useV0tender);
158 //      tender->SetDebugLevel(2);
159    }
160    //
161   // PIDResponse(JENS)
162   //
163   if (doPIDResponse) {
164     gROOT->LoadMacro("$ALICE_ROOT/ANALYSIS/macros/AddTaskPIDResponse.C"); 
165     AliAnalysisTaskPIDResponse *PIDResponse = AddTaskPIDResponse();
166 //    PIDResponse->SelectCollisionCandidates(AliVEvent::kAny);
167   }  
168  
169   //
170   // PIDqa(JENS)
171   //
172   if (doPIDqa) {
173     gROOT->LoadMacro("$ALICE_ROOT/ANALYSIS/macros/AddTaskPIDqa.C");
174     AliAnalysisTaskPIDqa *PIDQA = AddTaskPIDqa();
175     PIDQA->SelectCollisionCandidates(AliVEvent::kAny);
176   }  
177   // CDB connection
178   //
179   if (doCDBconnect && !useTender) {
180     gROOT->LoadMacro("$ALICE_ROOT/PWGPP/PilotTrain/AddTaskCDBconnect.C");
181     AliTaskCDBconnect *taskCDB = AddTaskCDBconnect(cdb_location, run_number);
182     if (!taskCDB) return;
183     AliCDBManager *cdb = AliCDBManager::Instance();
184     cdb->SetDefaultStorage(cdb_location);
185 //    taskCDB->SetRunNumber(run_number);
186   }    
187  
188    if (usePhysicsSelection) {
189    // Physics selection task
190       gROOT->LoadMacro("$ALICE_ROOT/ANALYSIS/macros/AddTaskPhysicsSelection.C");
191       mgr->RegisterExtraFile("event_stat.root");
192       AliPhysicsSelectionTask *physSelTask = AddTaskPhysicsSelection(useMC);
193 //      AliOADBPhysicsSelection * oadbDefaultPbPb = CreateOADBphysicsSelection();      
194 //      physSelTask->GetPhysicsSelection()->SetCustomOADBObjects(oadbDefaultPbPb,0,0);
195       mgr->AddStatisticsTask(AliVEvent::kAny);
196    }
197    
198
199 //Jacek
200    if (iPWGPP) {
201       gROOT->LoadMacro("$ALICE_ROOT/PWGPP/macros/AddTaskFilteredTree.C");
202       AddTaskFilteredTree("FilterEvents_Trees.root");
203    }   
204    
205    // Centrality (only Pb-Pb)
206    if (useCentrality) {
207       gROOT->LoadMacro("$ALICE_ROOT/ANALYSIS/macros/AddTaskCentrality.C");
208       AliCentralitySelectionTask *taskCentrality = AddTaskCentrality();
209       //taskCentrality->SelectCollisionCandidates(AliVEvent::kAny);
210    }
211    
212 // --- PWGLF - Forward (cholm@nbi.dk) -----------------------------
213    if (iPWGLFForward && usePhysicsSelection) { 
214         gROOT->LoadMacro("$ALICE_ROOT/PWGLF/FORWARD/analysis2/AddTaskForwardMult.C");
215      UShort_t pwglfForwardSys = 0; // iCollision+1; // pp:1, PbPb:2, pPb:3
216      UShort_t pwglfSNN        = 0;            // GeV, 0==unknown
217      Short_t  pwglfField      = 0;
218      AddTaskForwardMult(useMC && useTR,        // Need track-refs 
219                         pwglfForwardSys,       // Collision system
220                         pwglfSNN, 
221                         pwglfField);
222         gROOT->LoadMacro("$ALICE_ROOT/PWGLF/FORWARD/analysis2/AddTaskCentralMult.C");
223         AddTaskCentralMult(useMC, pwglfForwardSys, pwglfSNN, pwglfField);
224    }
225  
226     
227
228    if (iESDfilter) {
229       //  ESD filter task configuration.
230       gROOT->LoadMacro("$ALICE_ROOT/ANALYSIS/ESDfilter/macros/AddTaskESDFilter.C");
231       AliAnalysisTaskESDfilter *taskesdfilter = 0;
232       if (iMUONcopyAOD) {
233          printf("Registering delta AOD file\n");
234          mgr->RegisterExtraFile("AliAOD.Muons.root");
235          mgr->RegisterExtraFile("AliAOD.Dimuons.root");
236          taskesdfilter = AddTaskESDFilter(useKFILTER, kTRUE, kFALSE, kFALSE /*usePhysicsSelection*/,kFALSE,kTRUE,kFALSE,kFALSE,run_flag);
237       } else {
238         taskesdfilter = AddTaskESDFilter(useKFILTER, kFALSE, kFALSE, kFALSE /*usePhysicsSelection*/,kFALSE,kTRUE,kFALSE,kFALSE,run_flag); // others
239       }   
240       if (iESDfilterReVtx>=0 && taskesdfilter) taskesdfilter->SetRefitVertexTracks(iESDfilterReVtx, cutsESDfilterReVtx);
241    }   
242
243 // ********** PWG3 wagons ******************************************************           
244    // PWGHF vertexing
245    if (iPWGHFvertexing) {
246       gROOT->LoadMacro("$ALICE_ROOT/PWGHF/vertexingHF/macros/AddTaskVertexingHF.C");
247       if (!iPWGHFd2h) TFile::Cp(gSystem->ExpandPathName(configPWGHFd2h.Data()), "file:ConfigVertexingHF.C");
248       AliAnalysisTaskSEVertexingHF *taskvertexingHF = AddTaskVertexingHF();
249       if (!taskvertexingHF) ::Warning("AnalysisTrainNew", "AliAnalysisTaskSEVertexingHF cannot run for this train conditions - EXCLUDED");
250       else mgr->RegisterExtraFile("AliAOD.VertexingHF.root");
251       taskvertexingHF->SelectCollisionCandidates(0);
252    }   
253       
254    // PWGDQ JPSI filtering (only pp)
255    if (iPWGDQJPSIfilter && (iCollision==0)) {
256       gROOT->LoadMacro("$ALICE_ROOT/PWGDQ/dielectron/macros/AddTaskJPSIFilter.C");
257       AliAnalysisTaskSE *taskJPSIfilter = AddTaskJPSIFilter();
258       if (!taskJPSIfilter) ::Warning("AnalysisTrainNew", "AliAnalysisTaskDielectronFilter cannot run for this train conditions - EXCLUDED");
259       else mgr->RegisterExtraFile("AliAOD.Dielectron.root");
260       taskJPSIfilter->SelectCollisionCandidates(0);
261    }   
262
263    // PWGHF D2h
264    if (iPWGHFd2h) {   
265      gROOT->LoadMacro("$ALICE_ROOT/PWGHF/vertexingHF/AddD2HTrain.C");
266      TFile::Cp(gSystem->ExpandPathName(configPWGHFd2h.Data()), "file:ConfigVertexingHF.C");
267      AddD2HTrain(kFALSE, 1,0,0,0,0,0,0,0,0,0,0);                                 
268    }
269    
270    // ********** PWG4 wagons ******************************************************
271    // Jet analysis
272
273    // Configurations flags, move up?
274    TString kDeltaAODJetName = "AliAOD.Jets.root"; //
275    Bool_t  kIsPbPb = (iCollision==0)?false:true; // can be more intlligent checking the name of the data set
276    TString kDefaultJetBackgroundBranch = "";
277    TString kJetSubtractBranches = "";
278    UInt_t kHighPtFilterMask = 272;// from esd filter
279    UInt_t iPhysicsSelectionFlag = 0;
280    if (iJETAN) {
281      gROOT->LoadMacro("$ALICE_ROOT/PWGJE/macros/AddTaskJets.C");
282      // Default jet reconstructor running on ESD's
283      AliAnalysisTaskJets *taskjets = AddTaskJets("AOD","UA1",0.4,kHighPtFilterMask,1.,0); // no background subtraction     
284      if (!taskjets) ::Fatal("AnalysisTrainNew", "AliAnalysisTaskJets cannot run for this train conditions - EXCLUDED");
285      if(kDeltaAODJetName.Length()>0) taskjets->SetNonStdOutputFile(kDeltaAODJetName.Data());
286      if (iJETANdelta) {
287         //            AddTaskJetsDelta("AliAOD.Jets.root"); // need to modify this accordingly in the add task jets
288         mgr->RegisterExtraFile(kDeltaAODJetName.Data());
289         TString cTmp("");
290         if(kIsPbPb){
291           // UA1 intrinsic background subtraction
292           taskjets = AddTaskJets("AOD","UA1",0.4,kHighPtFilterMask,1.,2); // background subtraction
293           if(kDeltaAODJetName.Length()>0)taskjets->SetNonStdOutputFile(kDeltaAODJetName.Data());
294        }
295        // SICONE 
296        taskjets = AddTaskJets("AOD","SISCONE",0.4,kHighPtFilterMask,0.15,0); //no background subtration to be done later....                                                                                  
297        if(kDeltaAODJetName.Length()>0)taskjets->SetNonStdOutputFile(kDeltaAODJetName.Data());
298        cTmp = taskjets->GetNonStdBranch();
299        if(cTmp.Length()>0)kJetSubtractBranches += Form("%s ",cTmp.Data());
300          
301        // Add the clusters..
302        gROOT->LoadMacro("$ALICE_ROOT/PWGJE/macros/AddTaskJetCluster.C");
303        AliAnalysisTaskJetCluster *taskCl = 0;
304        Float_t fCenUp = 0;
305        Float_t fCenLo = 0;
306        Float_t fTrackEtaWindow = 0.9;
307        taskCl = AddTaskJetCluster("AOD","",kHighPtFilterMask,iPhysicsSelectionFlag,"KT",0.4,0,1, kDeltaAODJetName.Data(),0.15,fTrackEtaWindow,0); // this one is for the background and random jets, random cones with no skip                                                                                 
308        taskCl->SetBackgroundCalc(kTRUE);
309        taskCl->SetNRandomCones(10);
310        taskCl->SetCentralityCut(fCenLo,fCenUp);
311        taskCl->SetGhostEtamax(fTrackEtaWindow);
312        kDefaultJetBackgroundBranch = Form("%s_%s",AliAODJetEventBackground::StdBranchName(),taskCl->GetJetOutputBranch());
313
314        taskCl = AddTaskJetCluster("AOD","",kHighPtFilterMask,iPhysicsSelectionFlag,"ANTIKT",0.4,2,1,kDeltaAODJetName.Data(),0.15);
315        taskCl->SetCentralityCut(fCenLo,fCenUp);
316        if(kIsPbPb)taskCl->SetBackgroundBranch(kDefaultJetBackgroundBranch.Data());
317        taskCl->SetNRandomCones(10);
318        kJetSubtractBranches += Form("%s ",taskCl->GetJetOutputBranch());
319
320        taskCl = AddTaskJetCluster("AOD","",kHighPtFilterMask,iPhysicsSelectionFlag,"ANTIKT",0.2,0,1,kDeltaAODJetName.Data(),0.15);
321        taskCl->SetCentralityCut(fCenLo,fCenUp);
322        if(kIsPbPb)taskCl->SetBackgroundBranch(kDefaultJetBackgroundBranch.Data());
323        kJetSubtractBranches += Form("%s ",taskCl->GetJetOutputBranch());
324          
325        // DO THE BACKGROUND SUBTRACTION
326        if(kIsPbPb&&kJetSubtractBranches.Length()){
327          gROOT->LoadMacro("$ALICE_ROOT/PWGJE/macros/AddTaskJetBackgroundSubtract.C");
328          AliAnalysisTaskJetBackgroundSubtract *taskSubtract = 0;
329          taskSubtract = AddTaskJetBackgroundSubtract(kJetSubtractBranches,1,"B0","B%d");
330          taskSubtract->SetBackgroundBranch(kDefaultJetBackgroundBranch.Data());
331          if(kDeltaAODJetName.Length()>0)taskSubtract->SetNonStdOutputFile(kDeltaAODJetName.Data());
332        }
333      } 
334    }
335 }
336 //______________________________________________________________________________
337 Bool_t LoadCommonLibraries()
338 {
339 // Load common analysis libraries.
340    if (!gSystem->Getenv("ALICE_ROOT")) {
341       ::Error("AnalysisTrainNew.C::LoadCommonLibraries", "Analysis train requires that analysis libraries are compiled with a local AliRoot"); 
342       return kFALSE;
343    }   
344    Bool_t success = kTRUE;
345    // Load framework classes. Par option ignored here.
346    success &= LoadLibrary("libSTEERBase.so");
347    success &= LoadLibrary("libESD.so");
348    success &= LoadLibrary("libAOD.so");
349    success &= LoadLibrary("libANALYSIS.so");
350    success &= LoadLibrary("libOADB.so");
351    success &= LoadLibrary("libANALYSISalice.so");
352    success &= LoadLibrary("libCORRFW.so");
353    gROOT->ProcessLine(".include $ALICE_ROOT/include");
354    if (success) {
355       ::Info("AnalysisTrainNew.C::LoadCommodLibraries", "Load common libraries:    SUCCESS");
356       ::Info("AnalysisTrainNew.C::LoadCommodLibraries", "Include path for Aclic compilation:\n%s",
357               gSystem->GetIncludePath());
358    } else {           
359       ::Info("AnalysisTrainNew.C::LoadCommodLibraries", "Load common libraries:    FAILED");
360    }   
361    return success;
362 }
363
364 //______________________________________________________________________________
365 Bool_t LoadAnalysisLibraries()
366 {
367 // Load common analysis libraries.
368    if (useTender || doCDBconnect) {
369       if (!LoadLibrary("TENDER") ||
370           !LoadLibrary("TENDERSupplies")) return kFALSE;
371    }       
372    // CDBconnect
373    if (doCDBconnect && !useTender) {
374       if (!LoadLibrary("PWGPP")) return kFALSE;
375    }
376           
377    if (iESDfilter || iPWGMuonTrain) {
378       if (!LoadLibrary("PWGmuon")) return kFALSE;
379    }   
380    // JETAN
381    if (iJETAN) {
382       if (!LoadLibrary("JETAN")) return kFALSE;
383    }
384    if (iJETANdelta) {
385       if (!LoadLibrary("JETAN") ||
386           !LoadLibrary("CGAL") ||
387           !LoadLibrary("fastjet") ||
388           !LoadLibrary("siscone") ||
389           !LoadLibrary("SISConePlugin") ||
390           !LoadLibrary("FASTJETAN")) return kFALSE;
391    }  
392    // PWG2 FORWARD
393    if (iPWGLFForward) {
394       //if (!LoadLibrary("PWGLFforward", mode, kTRUE)) return kFALSE;
395       if (!LoadLibrary("PWGLFforward2")) return kFALSE;
396    }   
397    
398    // PWG3 Vertexing HF
399    if (iPWGHFvertexing || iPWGHFd2h) {
400       if (!LoadLibrary("PWGflowBase") ||
401           !LoadLibrary("PWGflowTasks") ||
402           !LoadLibrary("PWGHFvertexingHF")) return kFALSE;
403    }    
404  //    if (iPWGHFvertexing || iPWG3d2h) {
405  //     if (!LoadLibrary("PWG3base") ||
406  //         !LoadLibrary("PWGHFvertexingHF")) return kFALSE;
407  //  }   
408    // PWG3 dielectron
409    if (iPWGDQJPSIfilter) {
410       if (!LoadLibrary("PWGDQdielectron")) return kFALSE;
411    }   
412    
413    ::Info("AnalysisTrainNew.C::LoadAnalysisLibraries", "Load other libraries:   SUCCESS");
414    return kTRUE;
415 }
416
417 //______________________________________________________________________________
418 Bool_t LoadLibrary(const char *module)
419 {
420 // Load a module library in a given mode. Reports success.
421    Int_t result;
422    TString mod(module);
423    if (!mod.Length()) {
424       ::Error("AnalysisTrainNew.C::LoadLibrary", "Empty module name");
425       return kFALSE;
426    }   
427    // If a library is specified, just load it
428    if (mod.EndsWith(".so")) {
429       mod.Remove(mod.Index(".so"));
430       result = gSystem->Load(mod);
431       if (result < 0) {
432          ::Error("AnalysisTrainNew.C::LoadLibrary", "Could not load library %s", module);
433          return kFALSE;
434       }
435       return kTRUE;
436    } 
437    // Check if the library is already loaded
438    if (strlen(gSystem->GetLibraries(Form("%s.so", module), "", kFALSE)) > 0) return kTRUE;    
439    result = gSystem->Load(Form("lib%s.so", module));
440    if (result < 0) {
441       ::Error("AnalysisTrainNew.C::LoadLibrary", "Could not load module %s", module);
442       return kFALSE;
443    }
444    return kTRUE;
445 }           
446
447
448 //______________________________________________________________________________
449 TChain *CreateChain()
450 {
451 // Create the input chain
452    chain = new TChain("esdTree");
453    if (gSystem->AccessPathName("AliESDs.root")) 
454       ::Error("AnalysisTrainNew.C::CreateChain", "File: AliESDs.root not in ./data dir");
455    else 
456        chain->Add("AliESDs.root");
457    if (chain->GetNtrees()) return chain;
458    return NULL;
459 }   
460
461 //______________________________________________________________________________
462 void AODmerge()
463 {
464 // Merging method. No staging and no terminate phase.
465   TStopwatch timer;
466   timer.Start();
467   TString outputDir = "wn.xml";
468   TString outputFiles = "EventStat_temp.root,AODQA.root,AliAOD.root,AliAOD.VertexingHF.root,FilterEvents_Trees.root,AliAOD.Muons.root,AliAOD.Jets.root";
469   TString mergeExcludes = "";
470   TObjArray *list = outputFiles.Tokenize(",");
471   TIter *iter = new TIter(list);
472   TObjString *str;
473   TString outputFile;
474   Bool_t merged = kTRUE;
475   while((str=(TObjString*)iter->Next())) {
476     outputFile = str->GetString();
477     // Skip already merged outputs
478     if (!gSystem->AccessPathName(outputFile)) {
479        printf("Output file <%s> found. Not merging again.",outputFile.Data());
480        continue;
481     }
482     if (mergeExcludes.Contains(outputFile.Data())) continue;
483     merged = AliAnalysisAlien::MergeOutput(outputFile, outputDir, 10, 0);
484     if (!merged) {
485        printf("ERROR: Cannot merge %s\n", outputFile.Data());
486        continue;
487     }
488   }
489   // all outputs merged, validate
490   ofstream out;
491   out.open("outputs_valid", ios::out);
492   out.close();
493   timer.Print();
494 }