ROOT logo
/**
 * @file   AOD.C
 * @author Christian Holm Christensen <cholm@nbi.dk>
 * @date   Wed Sep 24 15:02:00 2014
 * 
 * @brief  Master script for AOD production.
 * 
 * @note Do not modify this script. 
 *
 * This script reads in 4 other scripts 
 *
 * - GRP.C to load the global run parameters for the selected run,
 *   such as collision system, energy, etc.
 * 
 * - AODConfig.C which defines a number of functions that return
 *   either true or false.  The tasks added depends on these functions
 *
 * - BaseConfig.C which defines some base classes 
 * 
 * - DetConfig.C which defines which detectors are active and on. 
 *
 * Users can customize QAConfig.C and DetConfig.C according to their
 * needs
 */
/** Path to CDB */
const char *cdbPath = "raw://";
Bool_t cholm = false;
/**
 * Interface (pure virtual) that all configuration classes must
 * implement.
 */
struct VirtualAODCfg
{
  /** 
   * @{ 
   * @name Plug-in settings 
   * Settings that make sense when using the Alien plugin
   */
  /** @return Connect to CDB */
  virtual Bool_t UseCDBconnect() const = 0;
  /** @return use physics selection */
  virtual Bool_t UsePhysicsSelection() const = 0;
  /** @return use tender wagon */
  virtual Bool_t UseTender() const = 0;
  /** @return centrality */
  virtual Bool_t UseCentrality() const = 0;
  /** @return use V0 correction in tender */
  virtual Bool_t UseV0tender() const = 0;
  /** @return activate debugging */
  virtual Bool_t UseDBG() const = 0;
  /** @return use MC info */
  virtual Bool_t UseMC() const = 0;
  /** @return use Kinematics filter */
  virtual Bool_t UseKFILTER() const = 0;
  /** @return use track references */
  virtual Bool_t UseTR() const = 0;
  /** @return do not change */
  virtual Bool_t UseCORRFW() const = 0;
  /** @return use AOD tags */
  virtual Bool_t UseAODTAGS() const = 0;
  /** @return use sys info */
  virtual Bool_t UseSysInfo() const = 0;
  /* @} */
  
  /** 
   * @{ 
   * @name Modules 
   *  Analysis modules to be included. Some may not be yet fully implemented.
   */
  /** @return Analysis produces an AOD or dAOD's */
  virtual Bool_t UseAODhandler() const = 0;
  /** @return ESD to AOD filter (barrel + muon tracks) */
  virtual Bool_t UseESDfilter() const = 0;
  /** @return Use Muon train  */
  virtual Bool_t UsePWGMuonTrain() const = 0;
  /** @return Task that copies only muon events */
  virtual Bool_t UseMUONcopyAOD() const = 0;
  /** @return Jet analysis (PWG4) */
  virtual Bool_t UseJETAN() const = 0;
  /** @return Jet delta AODs */
  virtual Bool_t UseJETANdelta() const = 0;
  /** @return Vertexing HF task (PWG3) */
  virtual Bool_t UsePWGHFvertexing() const = 0;
  /** @return JPSI filtering (PWG3) */
  virtual Bool_t UsePWGDQJPSIfilter() const = 0;
  /** @return D0->2 hadrons (PWG3) */
  virtual Bool_t UsePWGHFd2h() const = 0;
  /** @return PID response */
  virtual Bool_t UsePIDResponse() const = 0;
  /** @return Forward mult task (PWGLF) */
  virtual Bool_t UsePWGLFForward() const = 0;
  /* @} */
  /** 
   * Print one flag
   * 
   * @param title Title
   * @param use   Use or not 
   */
  virtual void PrintOne(const char* title, Bool_t use) const
  {
    Printf("%-30s : %3s", title, use ? "yes" : "no");
  }
  /** 
   * Print settings
   * 
   */
  virtual void Print() const { 
    PrintOne("Connect to CDB",			UseCDBconnect());
    PrintOne("Use physics selection",		UsePhysicsSelection());
    PrintOne("Use tender wagon",		UseTender());
    PrintOne("Use centrality",			UseCentrality());
    PrintOne("Use V0 correction in tender",	UseV0tender());
    PrintOne("Activate debugging",		UseDBG());
    PrintOne("Use MC info",			UseMC());
    PrintOne("Use Kinematics filter",		UseKFILTER());
    PrintOne("Use track references",		UseTR());
    PrintOne("Use correction framework",	UseCORRFW());
    PrintOne("Use AOD tags",			UseAODTAGS());
    PrintOne("Use sys info",			UseSysInfo());
    PrintOne("Produces an AOD or dAOD's",	UseAODhandler());
    PrintOne("ESD to AOD filter",		UseESDfilter());
    PrintOne("Use Muon train ",			UsePWGMuonTrain());
    PrintOne("Copy muon events",		UseMUONcopyAOD());
    PrintOne("Jet analysis (PWG4)",		UseJETAN());
    PrintOne("Jet delta AODs",			UseJETANdelta());
    PrintOne("Vertexing HF task (PWG3)",	UsePWGHFvertexing());
    PrintOne("JPSI filtering (PWG3)",		UsePWGDQJPSIfilter());
    PrintOne("D0->2 hadrons (PWG3)",		UsePWGHFd2h());
    PrintOne("PID response",			UsePIDResponse());
    PrintOne("Forward mult task (PWGLF)",	UsePWGLFForward());
  }
};

VirtualAODCfg* aodCfg = 0;

//====================================================================
/** 
 * Load a library/module 
 * 
 * @param module Library/module name 
 * 
 * @return true on success
 */
Bool_t LoadLibrary(const char *module)
{
  // Load a module library in a given mode. Reports success.
  Int_t result = 0;
  TString mod(module);
  ::Info("LoadLibrary", "Loading %s", module);
  gROOT->IncreaseDirLevel();

  if (mod.IsNull()) {
    ::Error("AnalysisTrainNew.C::LoadLibrary", "Empty module name");
    gROOT->DecreaseDirLevel();
    return kFALSE;
  }

  // If a library is specified, just load it
  if (mod.EndsWith(".so")) {
    mod.Remove(mod.Index(".so"));
    ::Info("LoadLibrary", "Loading .so: %s", mod.Data()); 
    result = gSystem->Load(mod);
    if (result < 0) {
      ::Error("AnalysisTrainNew.C::LoadLibrary", 
	      "Could not load library %s", module);
    }
    gROOT->DecreaseDirLevel();      
    return (result >= 0);
  }
  // Check if the library is already loaded
  if (strlen(gSystem->GetLibraries(Form("%s.so", module), "", kFALSE)) > 0) {
    ::Info("LoadLibrary", "Module %s.so already loaded", module);
    gROOT->DecreaseDirLevel();      
    return kTRUE;
  }

  ::Info("LoadLibrary", "Trying to load lib%s.so", module);
  result = gSystem->Load(Form("lib%s.so", module));
  if (result < 0)
    ::Error("AnalysisTrainNew.C::LoadLibrary", 
	    "Could not load module %s", module);
  ::Info("LoadLibrary", "Module %s, successfully loaded", module);
  gROOT->DecreaseDirLevel();      
  return (result >= 0);
}

//====================================================================
/** 
 * Load common libraries 
 * 
 * @return true on sucess 
 */
Bool_t LoadCommonLibraries()
{
  // Load common analysis libraries.
  if (!gSystem->Getenv("ALICE_ROOT")) {
    ::Error("AnalysisTrainNew.C::LoadCommonLibraries", 
	    "Analysis train requires that analysis libraries are "
	    "compiled with a local AliRoot");
    return kFALSE;
  }

  Bool_t success = kTRUE;
  // Load framework classes. Par option ignored here.
  success &= LoadLibrary("libSTEERBase.so");
  success &= LoadLibrary("libESD.so");
  success &= LoadLibrary("libAOD.so");
  success &= LoadLibrary("libANALYSIS.so");
  success &= LoadLibrary("libOADB.so");
  success &= LoadLibrary("libANALYSISalice.so");
  success &= LoadLibrary("libESDfilter.so");
  success &= LoadLibrary("libCORRFW.so");
  gROOT->ProcessLine(".include $ALICE_ROOT/include");
  if (success) {
    ::Info("AnalysisTrainNew.C::LoadCommodLibraries", 
	   "Load common libraries:    SUCCESS");
    ::Info("AnalysisTrainNew.C::LoadCommodLibraries", 
	   "Include path for Aclic compilation:\n%s",
	   gSystem->GetIncludePath());
  } else {
    ::Info("AnalysisTrainNew.C::LoadCommodLibraries", 
	   "Load common libraries:    FAILED");
  }
  return success;
}

//====================================================================
/** 
 * Load libraries needed by the train 
 * 
 * @param useTender 
 * @param doCDBconnect 
 * @param iESDfilter 
 * @param iPWGMuonTrain 
 * @param iJETAN 
 * @param iJETANdelta 
 * @param iPWGHFvertexing 
 * @param iPWGHFd2h 
 * @param iPWGDQJPSIfilter 
 * 
 * @return true on success 
 */
Bool_t LoadAnalysisLibraries()
{
  // Load common analysis libraries.
  if (aodCfg->UseTender() || aodCfg->UseCDBconnect()) {
    if (!LoadLibrary("TENDER") ||!LoadLibrary("TENDERSupplies")) return kFALSE;
  }
  // CDBconnect
  if ((aodCfg->UseCDBconnect() && !aodCfg->UseTender()) 
      && !LoadLibrary("PWGPP")) return false;
  if ((aodCfg->UseESDfilter() || 
       (aodCfg->UsePWGMuonTrain() && detCfg->UseMUON())))
    if (!LoadLibrary("PWGmuon")) return kFALSE;
  // JETAN
  if ((aodCfg->UseJETAN() || aodCfg->UseJETANdelta()))
    if (!LoadLibrary("JETAN")) return kFALSE;
  if (aodCfg->UseJETANdelta()) { // CINT doesn't like long '||' chains
    if (!LoadLibrary("CGAL"))           return false;
    if (!LoadLibrary("fastjet"))        return false;
    if (!LoadLibrary("siscone")) 	return false;
    if (!LoadLibrary("SISConePlugin"))  return false;
    if (!LoadLibrary("FASTJETAN"))      return false;
  }

  // PWG3 Vertexing HF
  if (aodCfg->UsePWGHFvertexing() || aodCfg->UsePWGHFd2h())) { 
    // CINT doesn't like long '||' chains
    if (!LoadLibrary("PWGflowBase"))      return false;
    if (!LoadLibrary("PWGflowTasks"))     return false;
    if (cholm) if (!LoadLibrary("PWGTRD"))           return false;
    if (!LoadLibrary("PWGHFvertexingHF")) return false;
  }

  // PWG3 dielectron
  if (aodCfg->UsePWGDQJPSIfilter() && 
      !LoadLibrary("PWGDQdielectron")) return kFALSE;
  
  ::Info("AnalysisTrainNew.C::LoadAnalysisLibraries", 
	 "Load other libraries:   SUCCESS");
  return kTRUE;
}

//====================================================================
/** 
 * Add tasks to the train 
 * 
 * @param cdb_location 
 */
void AddAnalysisTasks(const char *cdb_location)
{
  // === Add all analysis task wagons to the train ===================
  // 
  // --- Some constants ----------------------------------------------
  TString ali   = "$(ALICE_ROOT)";
  TString ana   = ali + "/ANALYSIS";
  TString pwghf = ali + "/PWGHF";
  TString pwglf = ali + "/PWGLF";
  TString pwgje = ali + "/PWGJE";
  TString pwgdq = ali + "/PWGDQ";
  TString pwgpp = ali + "/PWGPP";

  // --- Get the analysis manager ------------------------------------
  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  AliAnalysisManager::SetCommonFileName("AODQA.root");

  // --- PIDResponse(JENS) -------------------------------------------
  if (aodCfg->UsePIDResponse()) {
    gROOT->LoadMacro(ana+"/macros/AddTaskPIDResponse.C");
    AliAnalysisTaskPIDResponse *PIDResponse = AddTaskPIDResponse(kTRUE);
  }

  // --- CDB connection ----------------------------------------------
  if (aodCfg->UseCDBconnect() && !aodCfg->UseTender()) {
    gROOT->LoadMacro(pwgpp+"/PilotTrain/AddTaskCDBconnect.C");
    AliTaskCDBconnect *taskCDB = AddTaskCDBconnect(cdb_location, grp->run);
    if (!taskCDB) return;

    AliCDBManager *cdb = AliCDBManager::Instance();
    // cdb->SetDefaultStorage(cdb_location);
    cdb->SetDefaultStorageFromRun(grp->run);
  }
  if (aodCfg->UseTender()) {
    gROOT->LoadMacro(ana+"/TenderSupplies/AddTaskTender.C");
    AliAnalysisTaskSE *tender = AddTaskTender(aodCfg->UseV0tender());
  }

  // --- Physics selection -------------------------------------------
  if (aodCfg->UsePhysicsSelection()) {
    // Physics selection task
    gROOT->LoadMacro(ana+"/macros/AddTaskPhysicsSelection.C");
    mgr->RegisterExtraFile("event_stat.root");
    AliPhysicsSelectionTask *physSelTask = 
      AddTaskPhysicsSelection(aodCfg->UseMC());
  }

  // --- Centrality (only Pb-Pb) -------------------------------------
  if (aodCfg->UseCentrality()) {
    gROOT->LoadMacro(ana+"/macros/AddTaskCentrality.C");
    AliCentralitySelectionTask *taskCentrality = AddTaskCentrality();
    taskCentrality->SetMCInput();
  }

  // --- PWGLF - Forward (cholm@nbi.dk) -----------------------------
  if (aodCfg->UsePWGLFForward() && 
      aodCfg->UsePhysicsSelection() &&
      detCfg->UseFMD()) {
    gROOT->LoadMacro(pwglf+"/FORWARD/analysis2/AddTaskForwardMult.C");
    // Arguments are 
    //   mc         Assume MC input
    //   runNo      Run number to do local initialization - not used
    //   sys        Collision system (1:pp,2:PbPb,3:pPb/Pbp) - not used
    //   sNN        Collision energy in GeV - not used
    //   field      L3 magnetic field strength  - not used
    //   config     Configuration script 
    //   corrdir    Possible directory containing custom OADB corrections
    // HACK load custom corrections 
    Info("", "Adding forward AOD task with mc=%d",
	 aodCfg->UseMC() && aodCfg->UseTR());
    AddTaskForwardMult(aodCfg->UseMC() && aodCfg->UseTR(),0,0,0,0,
		       "ForwardAODConfig.C",".");
    gROOT->LoadMacro(pwglf+"/FORWARD/analysis2/AddTaskCentralMult.C");
    AddTaskCentralMult(aodCfg->UseMC() && aodCfg->UseTR(),0,0,0,0,
		       "CentralAODConfig.C");
    const char* hack2="AliForwardCorrectionManager::Instance().Print(\"R\")";
    gROOT->ProcessLine(hack2);
  }


  // --- ESD filter --------------------------------------------------
  if (aodCfg->UseESDfilter()) {
    //  ESD filter task configuration.
    gROOT->LoadMacro(ana+"/ESDfilter/macros/AddTaskESDFilter.C");
    if (aodCfg->UseMUONcopyAOD() && detCfg->UseMUON()) {
      printf("Registering delta AOD file\n");
      mgr->RegisterExtraFile("AliAOD.Muons.root");
      mgr->RegisterExtraFile("AliAOD.Dimuons.root");
    }
    UInt_t runFlag = (grp->Year()%100)*100;
    AliAnalysisTaskESDfilter *taskesdfilter =
      AddTaskESDFilter(aodCfg->UseKFILTER(),
		       aodCfg->UseMUONcopyAOD(),         // write Muon AOD
		       kFALSE,               // write dimuon AOD
		       kFALSE,               // usePhysicsSelection
		       kFALSE,               // centrality OBSOLETE
		       kTRUE,                // enable TPS only tracks
		       kFALSE,               // disable cascades
		       kFALSE,               // disable kinks
		       runFlag);             // run flag (YY00)
  }

  TString configPWGHFd2h = 
    (grp->IsPP() ?
     pwghf+"/vertexingHF/ConfigVertexingHF.C" :
     pwghf+"/vertexingHF/ConfigVertexingHF_Pb_AllCent.C");

  // --- PWG3 vertexing ----------------------------------------------
  if (aodCfg->UsePWGHFvertexing()) {
    gROOT->LoadMacro(pwghf+"/vertexingHF/macros/AddTaskVertexingHF.C");

    if (!aodCfg->UsePWGHFd2h()) 
      TFile::Cp(gSystem->ExpandPathName(configPWG3d2h.Data()), 
		"file:ConfigVertexingHF.C");

    AliAnalysisTaskSEVertexingHF *taskvertexingHF = AddTaskVertexingHF();
    if (!taskvertexingHF) 
      ::Warning("AnalysisTrainNew", 
		"AliAnalysisTaskSEVertexingHF cannot run for this train "
		"conditions - EXCLUDED");
    else 
      mgr->RegisterExtraFile("AliAOD.VertexingHF.root");

    taskvertexingHF->SelectCollisionCandidates(0);
  }

  // ---- PWG3 JPSI filtering (only pp) ------------------------------
  if (aodCfg->UsePWGDQJPSIfilter()) {
    gROOT->LoadMacro(pwgdq+"/dielectron/macros/AddTaskJPSIFilter.C");
    AliAnalysisTaskSE *taskJPSIfilter = AddTaskJPSIFilter();

    if (!taskJPSIfilter) 
      ::Warning("AnalysisTrainNew", 
		"AliAnalysisTaskDielectronFilter cannot run for this train "
		"conditions - EXCLUDED");
    else 
      mgr->RegisterExtraFile("AliAOD.Dielectron.root");

    taskJPSIfilter->SelectCollisionCandidates(0);
  }

  // --- PWG3 D2h ----------------------------------------------------
  if (aodCfg->UsePWGHFd2h() && aodCfg->UsePWGHFvertexing()) {
    gROOT->LoadMacro(pwghf+"/vertexingHF/AddD2HTrain.C");
    TFile::Cp(gSystem->ExpandPathName(configPWGHFd2h.Data()), 
	      "file:ConfigVertexingHF.C");
    AddD2HTrain(kFALSE, 1,0,0,0,0,0,0,0,0,0,0);
  }

  // --- Jet analysis ------------------------------------------------

  // Configurations flags, move up?
  if (aodCfg->UseJETAN()) {
#if 0
    Warning("", "JET analysis disabled - major restructuring ofg JETAN");
#else
    TString jetAOD             = "AliAOD.Jets.root";
    UInt_t  highPtMask         = 768;// from esd filter
    TString subtractBranches   = "";
    UInt_t  psFlag             = 0;

    Info("", "Loading macro %s/macros/AddTaskJets.C", pwgje.Data());
    gROOT->LoadMacro(pwgje+"/macros/AddTaskJets.C");
    // Default jet reconstructor running on ESD's
    // no background subtraction
    AliAnalysisTask* task = AddTaskJets("AOD","UA1",0.4F,highPtMask,1.F,0); 
    if (!task) 
      ::Fatal("AnalysisTrainNew", 
	      "AliAnalysisTaskJets cannot run for this train "
	      "conditions - EXCLUDED");
    
    AliAnalysisTaskJets* taskjets = static_cast<AliAnalysisTaskJets*>(task);
    if(!jetAOD.IsNull()) taskjets->SetNonStdOutputFile(jetAOD);

    if (aodCfg->UseJETANdelta()) {
      // need to modify this accordingly in the add task jets
      // AddTaskJetsDelta("AliAOD.Jets.root"); 
      mgr->RegisterExtraFile(jetAOD);
      TString cTmp("");

      if(grp->IsAA()){
	// UA1 intrinsic background subtraction
	// background subtraction
	taskjets = AddTaskJets("AOD","UA1",0.4,highPtMask,1.,2); 
	if(!jetAOD.IsNull()) taskjets->SetNonStdOutputFile(jetAOD);
      }
      // SICONE
      //no background subtration to be done later....
      taskjets = AddTaskJets("AOD","SISCONE",0.4,highPtMask,0.15,0); 
      if(!jetAOD.IsNull()) taskjets->SetNonStdOutputFile(jetAOD.Data());
      cTmp = taskjets->GetNonStdBranch();
      if(!cTmp.IsNull()) subtractBranches += Form("%s ",cTmp.Data());

      // Add the clusters..
      gROOT->LoadMacro(pwgje+"/macros/AddTaskJetCluster.C");
      AliAnalysisTaskJetCluster *taskCl = 0;
      Float_t fCenUp = 0;
      Float_t fCenLo = 0;
      Float_t fTrackEtaWindow = 0.9;
      // this one is for the background and random jets, random cones
      // with no skip
      taskCl = AddTaskJetCluster("AOD","",highPtMask,
				 psFlag,"KT",0.4,0,1, 
				 jetAOD,0.15,
				 fTrackEtaWindow,0); 
      taskCl->SetBackgroundCalc(kTRUE);
      taskCl->SetNRandomCones(10);
      taskCl->SetCentralityCut(fCenLo,fCenUp);
      taskCl->SetGhostEtamax(fTrackEtaWindow);
      TString bkgBranch = Form("%s_%s",
			       AliAODJetEventBackground::StdBranchName(),
			       taskCl->GetJetOutputBranch());

      taskCl = AddTaskJetCluster("AOD", "", highPtMask, psFlag, "ANTIKT",
				 0.4, 2, 1, jetAOD, 0.15);
      taskCl->SetCentralityCut(fCenLo,fCenUp);
      if(grp->IsAA()) taskCl->SetBackgroundBranch(bkgBranch.Data());

      taskCl->SetNRandomCones(10);
      subtractBranches += Form("%s ",taskCl->GetJetOutputBranch());

      taskCl = AddTaskJetCluster("AOD", "", highPtMask, psFlag, "ANTIKT",
				 0.2, 0 , 1, jetAOD, 0.15);
      taskCl->SetCentralityCut(fCenLo,fCenUp);
      if(grp->IsAA())taskCl->SetBackgroundBranch(bkgBranch);
      
      subtractBranches += Form("%s ",taskCl->GetJetOutputBranch());

      // DO THE BACKGROUND SUBTRACTION
      if(grp->IsAA() && !subtractBranches.IsNull()) {
	gROOT->LoadMacro(pwgje+"/macros/AddTaskJetBackgroundSubtract.C");
	AliAnalysisTaskJetBackgroundSubtract *taskSubtract = 0;
	taskSubtract = AddTaskJetBackgroundSubtract(subtractBranches,1,
						    "B0","B%d");
	taskSubtract->SetBackgroundBranch(bkgBranch);
	if(!jetAOD.IsNull()) taskSubtract->SetNonStdOutputFile(jetAOD.Data());
      }
    }
#endif
  }
}



//====================================================================
/** 
 * Create the input chain
 * 
 * 
 * @return Pointer to newly allocated train 
 */
TChain *CreateChain()
{
  // Create the input chain
  chain = new TChain("esdTree");
  if (gSystem->AccessPathName("AliESDs.root"))
    ::Error("AnalysisTrainNew.C::CreateChain", 
	    "File: AliESDs.root not in ./data dir");
  else
    chain->Add("AliESDs.root");
  if (chain->GetNtrees()) return chain;
  return NULL;
}

/** 
 * Helper function to make @c outputs_valid file 
 * 
 */
void ValidateOutput()
{
  std::ofstream out;
  out.open("outputs_valid", ios::out);
  out.close();    
}  
//====================================================================
/** 
 * Merge AOD output 
 * 
 * @param dir   Directory 
 * @param stage The merging stage 
 */
void AODMerge(const char* dir, Int_t stage)
{
  // Merging method. No staging and no terminate phase.
  TStopwatch  timer; timer.Start();
  TString     outputDir     = dir;
  TObjArray   outputFiles;
  // outputFiles.Add(new TObjString("EventStat_temp.root"));
  outputFiles.Add(new TObjString("AODQA.root"));
  outputFiles.Add(new TObjString("pyxsec_hists.root"));

  Bool_t mergeTrees = stage <= 1;
  if (mergeTrees) {
    outputFiles.Add(new TObjString("AliAOD.root"));
    if (aodCfg->UsePWGHFvertexing()) 
      outputFiles.Add(new TObjString("AliAOD.VertexingHF.root"));
    if (aodCfg->UseESDfilter() && 
	aodCfg->UseMUONcopyAOD() && 
	detCfg->UseMUON())
      outputFiles.Add(new TObjString("AliAOD.Muons.root"));
    if (aodCfg->UseJETAN()) 
      outputFiles.Add(new TObjString("AliAOD.Jets.root"));
    if (aodCfg->UsePWGDQJPSIfilter()) 
      outputFiles.Add(new TObjString("AliAOD.Dielectron.root"));
  }

  TString     mergeExcludes = "";
  TIter       iter(&outputFiles);
  TObjString* str           = 0;
  Bool_t      merged        = kTRUE;
  while ((str = static_cast<TObjString*>(iter()))) {
    TString& outputFile = str->GetString();
    // Skip already merged outputs
    if (!gSystem->AccessPathName(outputFile)) {
      ::Warning("Merge","Output file <%s> found. Not merging again.",
		outputFile.Data());
      continue;
    }
    if (mergeExcludes.Contains(outputFile.Data())) continue;
    merged = AliAnalysisAlien::MergeOutput(outputFile, 
					   outputDir, 
					   10, 
					   stage);
    if (!merged) {
      ::Error("Merge", "Cannot merge %s\n", outputFile.Data());
      continue;
    }
  }

  // all outputs merged, validate
  if (!outputDir.Contains("stage")) {
    ValidateOutput();
    timer.Print();
    return;
  }

  // --- set up to run terminate -------------------------------------
  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  mgr->SetSkipTerminate(kFALSE);
  if (!mgr->InitAnalysis()) return;

  mgr->PrintStatus();
  mgr->SetGridHandler(new AliAnalysisAlien);
  mgr->StartAnalysis("gridterminate",0);
  ValidateOutput();
  timer.Print();

}

//====================================================================
/** 
 * Set-up and run AOD train 
 * 
 * @param run      Run number 
 * @param xmlfile  Collection 
 * @param stage    Stage 
 */
void AOD(UInt_t run, const char* xmlfile=0, Int_t stage=0)
{
  TString host(gSystem->HostName());
  cholm = host.BeginsWith("hehi");
  if (cholm) TGrid::Connect("alien:");

  // -----------------------------------------------------------------
  // 
  // Get GRP parameters.  Defines global "grp" as a pointer to GRPData
  //
  gROOT->Macro(Form("GRP.C(%d)", run));
  gROOT->Macro("AODConfig.C");
  gROOT->Macro("BaseConfig.C");
  gROOT->Macro("DetConfig.C");

  // --- Some settings -----------------------------------------------
  // Set temporary merging directory to current one
  gSystem->Setenv("TMPDIR", gSystem->pwd());
  // Set temporary compilation directory to current one
  gSystem->SetBuildDir(gSystem->pwd(), kTRUE);

  // --- Friendly message --------------------------------------------
  printf("===================================================\n");
  printf("===========    RUNNING FILTERING TRAIN   ==========\n");
  printf("===================================================\n");
  printf("=  Configuring analysis train for:\n");
  aodCfg->Print();

  // Load common libraries and set include path
  if (!LoadCommonLibraries()) {
    ::Error("AnalysisTrain", "Could not load common libraries");
    return;
  }

  // === Make the analysis manager and connect event handlers ========
  // 
  // --- Analysis manager and load libraries -------------------------
  AliAnalysisManager *mgr = new AliAnalysisManager("Filter","Production train");
  mgr->SetRunFromPath(grp->run);
  if (aodCfg->UseSysInfo()) mgr->SetNSysInfo(100);
  if (!LoadAnalysisLibraries()) {
    ::Error("AnalysisTrain", "Could not load analysis libraries");
    return;
  }

  // --- Create ESD input handler ------------------------------------
  AliESDInputHandler *esdHandler = new AliESDInputHandler();
  mgr->SetInputEventHandler(esdHandler);

  // --- Monte Carlo handler -----------------------------------------
  if (aodCfg->UseMC()) {
    AliMCEventHandler* mcHandler = new AliMCEventHandler();
    mgr->SetMCtruthEventHandler(mcHandler);
    mcHandler->SetPreReadMode(1);
    mcHandler->SetReadTR(aodCfg->UseTR());
  }

  // --- AOD output handler ------------------------------------------
  if (aodCfg->UseAODhandler()) {
    AliAODHandler* aodHandler   = new AliAODHandler();
    aodHandler->SetOutputFileName("AliAOD.root");
    mgr->SetOutputEventHandler(aodHandler);
  }

  // === Set up tasks ================================================
  //
  // --- Create tasks ------------------------------------------------
  AddAnalysisTasks(cdbPath);

  // --- Debugging if needed -----------------------------------------
  if (aodCfg->UseDBG()) mgr->SetDebugLevel(3);


  // --- If merging, do so here and exit -----------------------------
  if (stage > 0) {
    AODMerge(xmlfile, stage);
    return;
  }
  // === Run the analysis ============================================
  //
  // --- Make our chain ----------------------------------------------
  TChain *chain = CreateChain();
  if (!chain) return;

  // --- Run the thing -----------------------------------------------
  TStopwatch timer;
  timer.Start();
  if (!mgr->InitAnalysis()) return;

  
  mgr->PrintStatus();
  mgr->SetSkipTerminate(kTRUE);
  mgr->StartAnalysis("local", chain);
  timer.Print();
}

// 
// EOF
// 

 AOD.C:1
 AOD.C:2
 AOD.C:3
 AOD.C:4
 AOD.C:5
 AOD.C:6
 AOD.C:7
 AOD.C:8
 AOD.C:9
 AOD.C:10
 AOD.C:11
 AOD.C:12
 AOD.C:13
 AOD.C:14
 AOD.C:15
 AOD.C:16
 AOD.C:17
 AOD.C:18
 AOD.C:19
 AOD.C:20
 AOD.C:21
 AOD.C:22
 AOD.C:23
 AOD.C:24
 AOD.C:25
 AOD.C:26
 AOD.C:27
 AOD.C:28
 AOD.C:29
 AOD.C:30
 AOD.C:31
 AOD.C:32
 AOD.C:33
 AOD.C:34
 AOD.C:35
 AOD.C:36
 AOD.C:37
 AOD.C:38
 AOD.C:39
 AOD.C:40
 AOD.C:41
 AOD.C:42
 AOD.C:43
 AOD.C:44
 AOD.C:45
 AOD.C:46
 AOD.C:47
 AOD.C:48
 AOD.C:49
 AOD.C:50
 AOD.C:51
 AOD.C:52
 AOD.C:53
 AOD.C:54
 AOD.C:55
 AOD.C:56
 AOD.C:57
 AOD.C:58
 AOD.C:59
 AOD.C:60
 AOD.C:61
 AOD.C:62
 AOD.C:63
 AOD.C:64
 AOD.C:65
 AOD.C:66
 AOD.C:67
 AOD.C:68
 AOD.C:69
 AOD.C:70
 AOD.C:71
 AOD.C:72
 AOD.C:73
 AOD.C:74
 AOD.C:75
 AOD.C:76
 AOD.C:77
 AOD.C:78
 AOD.C:79
 AOD.C:80
 AOD.C:81
 AOD.C:82
 AOD.C:83
 AOD.C:84
 AOD.C:85
 AOD.C:86
 AOD.C:87
 AOD.C:88
 AOD.C:89
 AOD.C:90
 AOD.C:91
 AOD.C:92
 AOD.C:93
 AOD.C:94
 AOD.C:95
 AOD.C:96
 AOD.C:97
 AOD.C:98
 AOD.C:99
 AOD.C:100
 AOD.C:101
 AOD.C:102
 AOD.C:103
 AOD.C:104
 AOD.C:105
 AOD.C:106
 AOD.C:107
 AOD.C:108
 AOD.C:109
 AOD.C:110
 AOD.C:111
 AOD.C:112
 AOD.C:113
 AOD.C:114
 AOD.C:115
 AOD.C:116
 AOD.C:117
 AOD.C:118
 AOD.C:119
 AOD.C:120
 AOD.C:121
 AOD.C:122
 AOD.C:123
 AOD.C:124
 AOD.C:125
 AOD.C:126
 AOD.C:127
 AOD.C:128
 AOD.C:129
 AOD.C:130
 AOD.C:131
 AOD.C:132
 AOD.C:133
 AOD.C:134
 AOD.C:135
 AOD.C:136
 AOD.C:137
 AOD.C:138
 AOD.C:139
 AOD.C:140
 AOD.C:141
 AOD.C:142
 AOD.C:143
 AOD.C:144
 AOD.C:145
 AOD.C:146
 AOD.C:147
 AOD.C:148
 AOD.C:149
 AOD.C:150
 AOD.C:151
 AOD.C:152
 AOD.C:153
 AOD.C:154
 AOD.C:155
 AOD.C:156
 AOD.C:157
 AOD.C:158
 AOD.C:159
 AOD.C:160
 AOD.C:161
 AOD.C:162
 AOD.C:163
 AOD.C:164
 AOD.C:165
 AOD.C:166
 AOD.C:167
 AOD.C:168
 AOD.C:169
 AOD.C:170
 AOD.C:171
 AOD.C:172
 AOD.C:173
 AOD.C:174
 AOD.C:175
 AOD.C:176
 AOD.C:177
 AOD.C:178
 AOD.C:179
 AOD.C:180
 AOD.C:181
 AOD.C:182
 AOD.C:183
 AOD.C:184
 AOD.C:185
 AOD.C:186
 AOD.C:187
 AOD.C:188
 AOD.C:189
 AOD.C:190
 AOD.C:191
 AOD.C:192
 AOD.C:193
 AOD.C:194
 AOD.C:195
 AOD.C:196
 AOD.C:197
 AOD.C:198
 AOD.C:199
 AOD.C:200
 AOD.C:201
 AOD.C:202
 AOD.C:203
 AOD.C:204
 AOD.C:205
 AOD.C:206
 AOD.C:207
 AOD.C:208
 AOD.C:209
 AOD.C:210
 AOD.C:211
 AOD.C:212
 AOD.C:213
 AOD.C:214
 AOD.C:215
 AOD.C:216
 AOD.C:217
 AOD.C:218
 AOD.C:219
 AOD.C:220
 AOD.C:221
 AOD.C:222
 AOD.C:223
 AOD.C:224
 AOD.C:225
 AOD.C:226
 AOD.C:227
 AOD.C:228
 AOD.C:229
 AOD.C:230
 AOD.C:231
 AOD.C:232
 AOD.C:233
 AOD.C:234
 AOD.C:235
 AOD.C:236
 AOD.C:237
 AOD.C:238
 AOD.C:239
 AOD.C:240
 AOD.C:241
 AOD.C:242
 AOD.C:243
 AOD.C:244
 AOD.C:245
 AOD.C:246
 AOD.C:247
 AOD.C:248
 AOD.C:249
 AOD.C:250
 AOD.C:251
 AOD.C:252
 AOD.C:253
 AOD.C:254
 AOD.C:255
 AOD.C:256
 AOD.C:257
 AOD.C:258
 AOD.C:259
 AOD.C:260
 AOD.C:261
 AOD.C:262
 AOD.C:263
 AOD.C:264
 AOD.C:265
 AOD.C:266
 AOD.C:267
 AOD.C:268
 AOD.C:269
 AOD.C:270
 AOD.C:271
 AOD.C:272
 AOD.C:273
 AOD.C:274
 AOD.C:275
 AOD.C:276
 AOD.C:277
 AOD.C:278
 AOD.C:279
 AOD.C:280
 AOD.C:281
 AOD.C:282
 AOD.C:283
 AOD.C:284
 AOD.C:285
 AOD.C:286
 AOD.C:287
 AOD.C:288
 AOD.C:289
 AOD.C:290
 AOD.C:291
 AOD.C:292
 AOD.C:293
 AOD.C:294
 AOD.C:295
 AOD.C:296
 AOD.C:297
 AOD.C:298
 AOD.C:299
 AOD.C:300
 AOD.C:301
 AOD.C:302
 AOD.C:303
 AOD.C:304
 AOD.C:305
 AOD.C:306
 AOD.C:307
 AOD.C:308
 AOD.C:309
 AOD.C:310
 AOD.C:311
 AOD.C:312
 AOD.C:313
 AOD.C:314
 AOD.C:315
 AOD.C:316
 AOD.C:317
 AOD.C:318
 AOD.C:319
 AOD.C:320
 AOD.C:321
 AOD.C:322
 AOD.C:323
 AOD.C:324
 AOD.C:325
 AOD.C:326
 AOD.C:327
 AOD.C:328
 AOD.C:329
 AOD.C:330
 AOD.C:331
 AOD.C:332
 AOD.C:333
 AOD.C:334
 AOD.C:335
 AOD.C:336
 AOD.C:337
 AOD.C:338
 AOD.C:339
 AOD.C:340
 AOD.C:341
 AOD.C:342
 AOD.C:343
 AOD.C:344
 AOD.C:345
 AOD.C:346
 AOD.C:347
 AOD.C:348
 AOD.C:349
 AOD.C:350
 AOD.C:351
 AOD.C:352
 AOD.C:353
 AOD.C:354
 AOD.C:355
 AOD.C:356
 AOD.C:357
 AOD.C:358
 AOD.C:359
 AOD.C:360
 AOD.C:361
 AOD.C:362
 AOD.C:363
 AOD.C:364
 AOD.C:365
 AOD.C:366
 AOD.C:367
 AOD.C:368
 AOD.C:369
 AOD.C:370
 AOD.C:371
 AOD.C:372
 AOD.C:373
 AOD.C:374
 AOD.C:375
 AOD.C:376
 AOD.C:377
 AOD.C:378
 AOD.C:379
 AOD.C:380
 AOD.C:381
 AOD.C:382
 AOD.C:383
 AOD.C:384
 AOD.C:385
 AOD.C:386
 AOD.C:387
 AOD.C:388
 AOD.C:389
 AOD.C:390
 AOD.C:391
 AOD.C:392
 AOD.C:393
 AOD.C:394
 AOD.C:395
 AOD.C:396
 AOD.C:397
 AOD.C:398
 AOD.C:399
 AOD.C:400
 AOD.C:401
 AOD.C:402
 AOD.C:403
 AOD.C:404
 AOD.C:405
 AOD.C:406
 AOD.C:407
 AOD.C:408
 AOD.C:409
 AOD.C:410
 AOD.C:411
 AOD.C:412
 AOD.C:413
 AOD.C:414
 AOD.C:415
 AOD.C:416
 AOD.C:417
 AOD.C:418
 AOD.C:419
 AOD.C:420
 AOD.C:421
 AOD.C:422
 AOD.C:423
 AOD.C:424
 AOD.C:425
 AOD.C:426
 AOD.C:427
 AOD.C:428
 AOD.C:429
 AOD.C:430
 AOD.C:431
 AOD.C:432
 AOD.C:433
 AOD.C:434
 AOD.C:435
 AOD.C:436
 AOD.C:437
 AOD.C:438
 AOD.C:439
 AOD.C:440
 AOD.C:441
 AOD.C:442
 AOD.C:443
 AOD.C:444
 AOD.C:445
 AOD.C:446
 AOD.C:447
 AOD.C:448
 AOD.C:449
 AOD.C:450
 AOD.C:451
 AOD.C:452
 AOD.C:453
 AOD.C:454
 AOD.C:455
 AOD.C:456
 AOD.C:457
 AOD.C:458
 AOD.C:459
 AOD.C:460
 AOD.C:461
 AOD.C:462
 AOD.C:463
 AOD.C:464
 AOD.C:465
 AOD.C:466
 AOD.C:467
 AOD.C:468
 AOD.C:469
 AOD.C:470
 AOD.C:471
 AOD.C:472
 AOD.C:473
 AOD.C:474
 AOD.C:475
 AOD.C:476
 AOD.C:477
 AOD.C:478
 AOD.C:479
 AOD.C:480
 AOD.C:481
 AOD.C:482
 AOD.C:483
 AOD.C:484
 AOD.C:485
 AOD.C:486
 AOD.C:487
 AOD.C:488
 AOD.C:489
 AOD.C:490
 AOD.C:491
 AOD.C:492
 AOD.C:493
 AOD.C:494
 AOD.C:495
 AOD.C:496
 AOD.C:497
 AOD.C:498
 AOD.C:499
 AOD.C:500
 AOD.C:501
 AOD.C:502
 AOD.C:503
 AOD.C:504
 AOD.C:505
 AOD.C:506
 AOD.C:507
 AOD.C:508
 AOD.C:509
 AOD.C:510
 AOD.C:511
 AOD.C:512
 AOD.C:513
 AOD.C:514
 AOD.C:515
 AOD.C:516
 AOD.C:517
 AOD.C:518
 AOD.C:519
 AOD.C:520
 AOD.C:521
 AOD.C:522
 AOD.C:523
 AOD.C:524
 AOD.C:525
 AOD.C:526
 AOD.C:527
 AOD.C:528
 AOD.C:529
 AOD.C:530
 AOD.C:531
 AOD.C:532
 AOD.C:533
 AOD.C:534
 AOD.C:535
 AOD.C:536
 AOD.C:537
 AOD.C:538
 AOD.C:539
 AOD.C:540
 AOD.C:541
 AOD.C:542
 AOD.C:543
 AOD.C:544
 AOD.C:545
 AOD.C:546
 AOD.C:547
 AOD.C:548
 AOD.C:549
 AOD.C:550
 AOD.C:551
 AOD.C:552
 AOD.C:553
 AOD.C:554
 AOD.C:555
 AOD.C:556
 AOD.C:557
 AOD.C:558
 AOD.C:559
 AOD.C:560
 AOD.C:561
 AOD.C:562
 AOD.C:563
 AOD.C:564
 AOD.C:565
 AOD.C:566
 AOD.C:567
 AOD.C:568
 AOD.C:569
 AOD.C:570
 AOD.C:571
 AOD.C:572
 AOD.C:573
 AOD.C:574
 AOD.C:575
 AOD.C:576
 AOD.C:577
 AOD.C:578
 AOD.C:579
 AOD.C:580
 AOD.C:581
 AOD.C:582
 AOD.C:583
 AOD.C:584
 AOD.C:585
 AOD.C:586
 AOD.C:587
 AOD.C:588
 AOD.C:589
 AOD.C:590
 AOD.C:591
 AOD.C:592
 AOD.C:593
 AOD.C:594
 AOD.C:595
 AOD.C:596
 AOD.C:597
 AOD.C:598
 AOD.C:599
 AOD.C:600
 AOD.C:601
 AOD.C:602
 AOD.C:603
 AOD.C:604
 AOD.C:605
 AOD.C:606
 AOD.C:607
 AOD.C:608
 AOD.C:609
 AOD.C:610
 AOD.C:611
 AOD.C:612
 AOD.C:613
 AOD.C:614
 AOD.C:615
 AOD.C:616
 AOD.C:617
 AOD.C:618
 AOD.C:619
 AOD.C:620
 AOD.C:621
 AOD.C:622
 AOD.C:623
 AOD.C:624
 AOD.C:625
 AOD.C:626
 AOD.C:627
 AOD.C:628
 AOD.C:629
 AOD.C:630
 AOD.C:631
 AOD.C:632
 AOD.C:633
 AOD.C:634
 AOD.C:635
 AOD.C:636
 AOD.C:637
 AOD.C:638
 AOD.C:639
 AOD.C:640
 AOD.C:641
 AOD.C:642
 AOD.C:643
 AOD.C:644
 AOD.C:645
 AOD.C:646
 AOD.C:647
 AOD.C:648
 AOD.C:649
 AOD.C:650
 AOD.C:651
 AOD.C:652
 AOD.C:653
 AOD.C:654
 AOD.C:655
 AOD.C:656
 AOD.C:657
 AOD.C:658
 AOD.C:659
 AOD.C:660
 AOD.C:661
 AOD.C:662
 AOD.C:663
 AOD.C:664
 AOD.C:665
 AOD.C:666
 AOD.C:667
 AOD.C:668
 AOD.C:669
 AOD.C:670
 AOD.C:671
 AOD.C:672
 AOD.C:673
 AOD.C:674
 AOD.C:675
 AOD.C:676
 AOD.C:677
 AOD.C:678
 AOD.C:679
 AOD.C:680
 AOD.C:681
 AOD.C:682
 AOD.C:683
 AOD.C:684
 AOD.C:685
 AOD.C:686
 AOD.C:687
 AOD.C:688
 AOD.C:689
 AOD.C:690
 AOD.C:691
 AOD.C:692
 AOD.C:693
 AOD.C:694
 AOD.C:695
 AOD.C:696
 AOD.C:697
 AOD.C:698
 AOD.C:699
 AOD.C:700
 AOD.C:701
 AOD.C:702
 AOD.C:703
 AOD.C:704
 AOD.C:705
 AOD.C:706
 AOD.C:707
 AOD.C:708
 AOD.C:709
 AOD.C:710
 AOD.C:711
 AOD.C:712
 AOD.C:713
 AOD.C:714
 AOD.C:715
 AOD.C:716
 AOD.C:717
 AOD.C:718
 AOD.C:719
 AOD.C:720
 AOD.C:721
 AOD.C:722
 AOD.C:723
 AOD.C:724
 AOD.C:725
 AOD.C:726
 AOD.C:727
 AOD.C:728
 AOD.C:729
 AOD.C:730
 AOD.C:731
 AOD.C:732
 AOD.C:733
 AOD.C:734
 AOD.C:735
 AOD.C:736
 AOD.C:737
 AOD.C:738
 AOD.C:739
 AOD.C:740
 AOD.C:741
 AOD.C:742
 AOD.C:743
 AOD.C:744
 AOD.C:745
 AOD.C:746
 AOD.C:747