]> git.uio.no Git - u/mrichter/AliRoot.git/commitdiff
New structure for trains which allows usage of
authorcholm <cholm@f7af4fe6-9843-0410-8265-dc069ae4e863>
Thu, 7 Jun 2012 09:01:25 +0000 (09:01 +0000)
committercholm <cholm@f7af4fe6-9843-0410-8265-dc069ae4e863>
Thu, 7 Jun 2012 09:01:25 +0000 (09:01 +0000)
command line options and the like.  Increased the
flexibility quite a bit and added a program to run
trains defined via the TrainSetup base class.

16 files changed:
PWGLF/FORWARD/analysis2/trains/BuildTrain.C
PWGLF/FORWARD/analysis2/trains/MakeAODTrain.C
PWGLF/FORWARD/analysis2/trains/MakeFMDELossTrain.C
PWGLF/FORWARD/analysis2/trains/MakeFMDEventPlaneTrain.C
PWGLF/FORWARD/analysis2/trains/MakeFlowTrain.C
PWGLF/FORWARD/analysis2/trains/MakeFullTrain.C [new file with mode: 0644]
PWGLF/FORWARD/analysis2/trains/MakeMCCorrTrain.C
PWGLF/FORWARD/analysis2/trains/MakeQATrain.C
PWGLF/FORWARD/analysis2/trains/MakedNdetaTrain.C
PWGLF/FORWARD/analysis2/trains/MyAnalysis.C [new file with mode: 0644]
PWGLF/FORWARD/analysis2/trains/MyJob.sh [new file with mode: 0755]
PWGLF/FORWARD/analysis2/trains/MyTrain.C [new file with mode: 0644]
PWGLF/FORWARD/analysis2/trains/QATrain.C
PWGLF/FORWARD/analysis2/trains/RunTrain.C [new file with mode: 0644]
PWGLF/FORWARD/analysis2/trains/TrainSetup.C
PWGLF/FORWARD/analysis2/trains/runMain.cxx [new file with mode: 0644]

index 12b4e0b83c58e406298d87dfd0c25f987f3eb716..8f65ce684d018d3615cee911057faafeba3ffd20 100644 (file)
@@ -82,6 +82,7 @@ BuildTrain(const char* script, const char* extra="", Bool_t useTmp=false)
 
   return ret == 0;
 }
+
 //
 // EOF
 //
index d52f9c866a5141004886cf72299960f2efe1818d..dd2d506a4a8366557c291a083f6e06f64ef549c1 100644 (file)
@@ -1,5 +1,3 @@
-#include "TrainSetup.C"
-
 /**
  * @file   MakeAODTrain.C
  * @author Christian Holm Christensen <cholm@dalsgaard.hehi.nbi.dk>
@@ -9,22 +7,12 @@
  * 
  * @ingroup pwglf_forward_trains
  */
-//====================================================================
+#include "TrainSetup.C"
 
+//====================================================================
 /**
  * Analysis train to make Forward and Central multiplicity
  * 
- * To run, do 
- * @code 
- * gROOT->LoadMacro("TrainSetup.C");
- * // Make train 
- * MakeAODTrain t("My Analysis");
- * // Set variaous parameters on the train 
- * t.SetDataDir("/home/of/data");
- * t.AddRun(118506)
- * // Run it 
- * t.Run("LOCAL", "FULL", -1, false, false);
- * @endcode 
  *
  * @ingroup pwglf_forward_aod
  * @ingroup pwglf_forward_trains
@@ -37,104 +25,64 @@ public:
    * in Termiante mode on Grid
    * 
    * @param name     Name of train (free form)
-   * @param sys      Collision system (1: pp, 2: PbPb)
-   * @param sNN      Center of mass energy [GeV]
-   * @param field    L3 magnetic field - one of {-5,0,+5} kG
-   * @param useCent  Whether to use centrality 
-   * @param dateTime Append date and time to name 
-   * @param year     Year     - if not specified, current year
-   * @param month    Month    - if not specified, current month
-   * @param day      Day      - if not specified, current day
-   * @param hour     Hour     - if not specified, current hour
-   * @param min      Minutes  - if not specified, current minutes
    */
-  MakeAODTrain(const  char* name, 
-              UShort_t     sys      = 0, 
-              UShort_t     sNN      = 0, 
-              Short_t      field    = 0, 
-              Bool_t       useCent  = false, 
-              Bool_t       dateTime = false, 
-              UShort_t     year     = 0, 
-              UShort_t     month    = 0, 
-              UShort_t     day      = 0, 
-              UShort_t     hour     = 0, 
-              UShort_t     min      = 0) 
-    : TrainSetup(name, dateTime, 
-                year, month, day, hour, min),
-      fSys(sys), 
-      fSNN(sNN), 
-      fField(field),
-      fUseCent(useCent), 
-      fDebugLvl(0), 
-      fUseTPCEventPlane(false)
-  {}
+  MakeAODTrain(const  char* name) 
+    : TrainSetup(name),
+      fSys(0), 
+      fSNN(0), 
+      fField(0),
+      fUseCent(true), 
+      fUseTPCEventPlane(false),
+      fForwardConfig("ForwardAODConfig.C"), 
+      fCentralConfig("CentralAODConfig.C")
+  {
+    SetType(kESD);
+  }
   /** 
-   * Set the debug level on Forward objects
+   * Set the collision system 
    * 
-   * @param lvl Debug level
+   * @param sys 1: pp, 2: PbPb, 3: pPb 
    */
-  void SetDebugLevel(Int_t lvl) { fDebugLvl = lvl; }
+  void SetCollisionSystem(UShort_t sys) { fSys = sys; }
   /** 
-   * If set to true, add TPC event plane task. 
+   * Set the collision energy in GeV
    * 
-   * @param use Wheter to include TPC event plane task 
+   * @param sNN @f$\sqrt{s_{NN}}@f$ for PbPb and pPb, @f$\sqrt{s}@f$
+   * for pp
    */
-  void SetUseTPCEventPlance(Bool_t use) { fUseTPCEventPlane = use; }
+  void SetCollisionEnergy(UShort_t sNN) { fSNN = sNN; }
   /** 
-   * Run this analysis 
+   * Set the L3 magnetic field in kilo Gaus
    * 
-   * @param mode     Mode - see TrainSetup::EMode
-   * @param oper     Operation - see TrainSetup::EOperation
-   * @param nEvents  Number of events (negative means all)
-   * @param mc       If true, assume simulated events 
-   * @param usePar   If true, use PARs 
+   * @param fld Field value 
    */
-  void Run(const char* mode, 
-          const char* oper, 
-          Int_t       nEvents=-1, 
-          Bool_t      mc=false,
-          Bool_t      usePar=false, 
-          Int_t       dbg=0)
-  {
-    Info("Run", "Running in mode=%s, oper=%s, events=%d, MC=%d, Par=%d", 
-        mode, oper, nEvents, mc, usePar);
-    Exec("ESD", mode, oper, nEvents, mc, usePar, dbg);
-  }
+  void SetL3Field(Short_t fld) { fField = fld; }
   /** 
-   * Run this analysis 
+   * If set to true, add TPC event plane task. 
    * 
-   * @param mode     Mode - see TrainSetup::EMode
-   * @param oper     Operation - see TrainSetup::EOperation
-   * @param nEvents  Number of events (negative means all)
-   * @param mc       If true, assume simulated events 
-   * @param usePar   If true, use PARs 
+   * @param use Wheter to include TPC event plane task 
    */
-  void Run(EMode  mode, 
-          EOper  oper, 
-          Int_t  nEvents=-1, 
-          Bool_t mc=false, 
-          Bool_t usePar = false,
-          Int_t  dbg = 0)
-  {
-    Info("Run", "Running in mode=%d, oper=%d, events=%d, MC=%d, Par=%d", 
-        mode, oper, nEvents, mc, usePar);
-    Exec(kESD, mode, oper, nEvents, mc, usePar, dbg);
-  }
+  void SetUseTPCEventPlane(Bool_t use) { fUseTPCEventPlane = use; }
+  /** 
+   * Whether to process per centrality bin
+   * 
+   * @param use 
+   */
+  void SetUseCentrality(Bool_t use) { fUseCent = use; }
 protected:
   /** 
    * Create the tasks 
    * 
-   * @param mode Processing mode
    * @param par  Whether to use par files 
    * @param mgr  Analysis manager 
    */
-  void CreateTasks(EMode mode, Bool_t par, AliAnalysisManager* mgr)
+  void CreateTasks(EMode /*mode*/, Bool_t par, AliAnalysisManager* mgr)
   {
     // --- Output file name ------------------------------------------
     AliAnalysisManager::SetCommonFileName("forward.root");
 
     // --- Load libraries/pars ---------------------------------------
-    LoadLibrary("PWGLFforward2", mode, par, true);
+    LoadLibrary("PWGLFforward2", par, true);
     
     // --- Set load path ---------------------------------------------
     gROOT->SetMacroPath(Form("%s:$(ALICE_ROOT)/PWGLF/FORWARD/analysis2",
@@ -152,14 +100,14 @@ protected:
     gROOT->Macro("AddTaskCopyHeader.C");
 
     // --- Add the task ----------------------------------------------
-    gROOT->Macro(Form("AddTaskForwardMult.C(%d,%d,%d,%d,%d)", 
-                     mc, fSys, fSNN, fField, fDebugLvl));
-    AddExtraFile(gSystem->Which(gROOT->GetMacroPath(), "ForwardAODConfig.C"));
+    gROOT->Macro(Form("AddTaskForwardMult.C(%d,%d,%d,%d,\"%s\")", 
+                     mc, fSys, fSNN, fField, fForwarConfig.Data()));
+    AddExtraFile(gSystem->Which(gROOT->GetMacroPath(), fForwardConfig));
 
     // --- Add the task ----------------------------------------------
-    gROOT->Macro(Form("AddTaskCentralMult.C(%d,%d,%d,%d,%d)", 
-                     mc, fSys, fSNN, fField, fDebugLvl));
-    AddExtraFile(gSystem->Which(gROOT->GetMacroPath(), "CentralAODConfig.C"));
+    gROOT->Macro(Form("AddTaskCentralMult.C(%d,%d,%d,%d,\"%s\")", 
+                     mc, fSys, fSNN, fField, fCentralConfig.Data()));
+    AddExtraFile(gSystem->Which(gROOT->GetMacroPath(), fCentralConfig));
 
     // --- Add MC particle task --------------------------------------
     if (mc) gROOT->Macro("AddTaskMCParticleFilter.C");
@@ -172,8 +120,7 @@ protected:
    * @param mc Whether this is for MC 
    * @param mgr Manager 
    */
-  void CreatePhysicsSelection(Bool_t mc,
-                             AliAnalysisManager* mgr)
+  void CreatePhysicsSelection(Bool_t mc, AliAnalysisManager* mgr)
   {
     TrainSetup::CreatePhysicsSelection(mc, mgr);
 
@@ -206,96 +153,102 @@ protected:
     TrainSetup::CreateCentralitySelection(mc, mgr);
   }
   //__________________________________________________________________
-  /** 
-   * Create the setup script.  This is overloaded here, so that we can
-   * create our dN/deta job script here.
-   * 
-   * @param type   Type of analysis
-   * @param mode   Mode of the analysis 
-   * @param mc     Whether this is MC or not 
-   * @param usePar Whether to use par files or not 
-   * @param dbg    Debug level
-   */
-  virtual void CreateSetupScript(EType  type, 
-                                EMode  mode, 
-                                Bool_t mc, 
-                                Bool_t usePar, 
-                                Int_t  dbg) const
+  const char* ClassName() const { return "MakeAODTrain"; }
+  //__________________________________________________________________
+ void MakeOptions(Runner& r) 
   {
-    TrainSetup::CreateSetupScript(type, mode, mc, usePar, dbg);
-    
-    Info("CreateSetupScript", "Creating dNdeta train setup script");
-    TString base(Form("%s_dndeta", fName.Data()));
-    TString escaped = EscapeName(base, fDatime);
-    std::ofstream o(Form("%s.C", escaped.Data()));
-    if (!o) { 
-      Error("CreateSetupScript", "Failed to make dNdeta script %s.C", 
-           escaped.Data());
-      return;
-    }
-    
-    o << std::boolalpha 
-      << "// Script to analyse AOD pass " << EscapedName() << " for dN/deta\n"
-      << "// Automatically generated by MakeAODTrain\n"
-      << "void " << escaped << "(bool terminate=false,"
-      << "const char* trig=\"INEL\",Double_t vzMin=-10, Double_t vzMax=+10,"
-      << "const char* scheme=\"FULL\")\n"
-      << "{\n";
-    WriteBuild(o, "MakedNdetaTrain");
-
-    o << "  MakedNdetaTrain t(\"" << base << "\",trig,vzMin,vzMax,scheme,"
-      << fUseCent << ");\n";
-    TrainSetup::WriteSettings(o, "t");
-    o << "  t.SetDataDir(\"" << GetOutputDirectory(mode) << "\");\n";
-    WriteRuns(o, "t");
-      
-    const char* cmode = (mode == kLocal ? "\"LOCAL\"" : 
-                        mode == kProof ? "\"PROOF\"" : "\"GRID\"");
-    o << "  t.Run(" << cmode << ",(terminate ? \"TERMINATE\" : \"FULL\"),-1,"
-      << usePar << ',' << dbg << ");\n"
-      << "}\n"
-      << "// EOF" << std::endl;
-    
-    o.close();
+    TrainSetup::MakeOptions(r);
+    r.Add(new Option("sys", "Collision system",    "1|2|3"));
+    r.Add(new Option("sNN", "Collision energy",    "GEV"));
+    r.Add(new Option("field", "L3 magnetic field", "kG"));
+    r.Add(new Option("cent",  "Use centrality"));
+    r.Add(new Option("tep",   "Use TPC event plance"));
+    r.Add(new Option("forward-config","Forward configuration script","SCRIPT"));
+    r.Add(new Option("central-config","Central configuration script","SCRIPT"));
   }
   //__________________________________________________________________
-  const char* ClassName() const { return "MakeAODTrain"; }
-  //__________________________________________________________________
-  void WriteConstruction(std::ostream& o, const char* obj) const
+  void SetOptions(Runner& r)
   {
-    o << "  UShort_t sys = " << fSys     << "; // 1:pp, 2:PbPb, 3:pPb\n"
-      << "  UShort_t sNN = " << fSNN     << "; // sqrt(sNN) in GeV\n"
-      << "  Short_t  fld = " << fField   << "; // L3 field in kG\n"
-      << "  Bool_t   cen = " << fUseCent << "; // enable centrality\n" 
-      << "  MakeAODTrain "<< obj << "(\"" << fName << "\",sys,sNN,fld,cen);\n"; 
+    TrainSetup::SetOptions(r);
+    Option* sys                = r.FindOption("sys");
+    Option* sNN                = r.FindOption("sNN");
+    Option* field      = r.FindOption("field");
+    Option* cent       = r.FindOption("cent");
+    Option* tep                = r.FindOption("tep");
+    Option* fwdConfig   = r.FindOption("forward-config");
+    Option* cenConfig   = r.FindOption("central-config");
+    
+    if (sys)   SetCollisionSystem(sys->AsInt());
+    if (sNN)   SetCollisionEnergy(sNN->AsInt());
+    if (field) SetL3Field(field->AsInt());
+    if (cent)  SetUseCentrality(cent->AsBool());
+    if (tep)   SetUseTPCEventPlane(tep->AsBool());
+    if (fwdConfig && fwdConfig->IsSet()) 
+      fForwardConfig = fwdConfig->AsString(); 
+    if (cenConfig && cenConfig->IsSet()) 
+      fCentralConfig = cenConfig->AsString(); 
   }
   //__________________________________________________________________
-  void WriteSettings(std::ostream& o, const char* obj) const
+  void SaveOptions(std::ostream& o, const char* str, Runner& r)
   {
-    TrainSetup::WriteSettings(o, obj);
-    o << "  " << obj << ".SetDebugLvl(" << fDebugLvl << ");\n"
-      << "  " << obj << ".SetUseTPCEventPlane(" << fUseTPCEventPlane << ");\n"
-      << std::endl;
+    TrainSetup::SaveOptions(o, str, r);
+    Option* sys                = r.FindOption("sys");
+    Option* sNN                = r.FindOption("sNN");
+    Option* field      = r.FindOption("field");
+    Option* cent       = r.FindOption("cent");
+    Option* tep                = r.FindOption("tep");
+    Option* fwdConfig   = r.FindOption("forward-config");
+    Option* cenConfig   = r.FindOption("central-config");
+
+    if (sys)   sys->Save(o, str, fSys);
+    if (sNN)   sNN->Save(o, str, fSNN);
+    if (field) field->Save(o, str, fField);
+    if (cent)  cent->Save(o, str, fUseCent);
+    if (tep)   tep->Save(o, str, fUseTPCEventPlane);
+    if (fwdConfig) fwdConfig->Save(o. str, fForwardConfig);
+    if (cenConfig) cenConfig->Save(o. str, fCentralConfig);
+    
   }
   //__________________________________________________________________
-  void WriteRun(std::ostream& o, 
-               const char* obj, 
-               const char* /*type*/, 
-               const char* mode, 
-               const char* oper, 
-               Bool_t      mc, 
-               Bool_t      usePar, 
-               Int_t       dbg) const
+  void SaveSetupROOT(Runner& r, Int_t nEvents)
   {
-    o << "  " << obj << ".Run(" << mode << ',' << oper << ",-1," << mc << ','
-      << usePar << ',' << dbg << ");" << std::endl;
+    TrainSetup::SaveSetup(r, nEvents);
+    
+    TString base(Form("dndeta_%s", fEscapedName.Data()));
+    
+    std::ofstream o(Form("%s.C", base.Data()));
+    o << "void " << base << "()\n"
+      << "{\n"
+      << "  TString opts;\n";
+    TrainSetup::SaveOptions(o, "opts", r);
+    o << "  // Note, `type' from above overwritten here\n"
+      << "  opts.Append(\"type=AOD:\");\n"
+      << "  opts.Append(\"trig=INEL:\");\n"
+      << "  opts.Append(\"vzMin=-10:\");\n"
+      << "  opts.Append(\"vzMax=-10:\");\n"
+      << "  opts.Append(\"scheme=full:\");\n"
+      << "  opts.Append(\"datadir=" << GetOutputDirectory(fExecMode) 
+      << ":\");\n\n"
+      << "  TString runs(\"";
+    for (Int_t i = 0; i < fRunNumbers.GetSize(); i++) 
+      o << (i == 0 ? "" : ", ") << fRunNumbers.At(i);
+    o << "\");\n\n"
+      << "  Int_t   nEvents = " << nEvents << ";\n\n"
+      << "  gROOT->LoadMacro(\"$ALICE_ROOT/PWGLF/FORWARD/analysis2/trains/RunTrain.C\");\n"
+      << "  RunTrain(\"MakedNdetaTrain\",\"dndeta_" << fName << "\",opts,runs,nEvents);\n"
+      << "}\n"
+      << "// EOF" << std::endl;
+    o.close();
   }
-  UShort_t fSys;
-  UShort_t fSNN;
-  Short_t  fField;
-  Bool_t   fUseCent;
-  Int_t    fDebugLvl;
-  Bool_t   fUseTPCEventPlane;
+
+  UShort_t fSys;                // Pre-set collision system
+  UShort_t fSNN;                // Pre-set collision energy 
+  Short_t  fField;              // Pre-set magnetic field
+  Bool_t   fUseCent;            // Whether to use centrality 
+  Bool_t   fUseTPCEventPlane;   // Whether to use TPC event plane 
+  TString  fForwardConfig;      // Forward configuration script 
+  TString  fCentralConfig;      // Central configuration script 
+
 };
 //
 // EOF
index fc8eab12ee4d9ce7c9b3cfa670fbae750fefa3bd..ca48d0ee88d37e5dae6d5159d730c14286819fdc 100644 (file)
@@ -1,8 +1,21 @@
+/**
+ * @file   MakeFMDELossTrain.C
+ * @author Christian Holm Christensen <cholm@master.hehi.nbi.dk>
+ * @date   Fri Jun  1 13:53:02 2012
+ * 
+ * @brief  
+ * 
+ * 
+ * @ingroup pwglf_forward_trains
+ */
+#include "TrainSetup.C"
+
 //====================================================================
 /**
  * Analysis train to do energy loss fits
  * 
  * @ingroup pwglf_forward_trains
+ * @ingroup pwglf_forward_eloss
  */
 class MakeFMDELossTrain : public TrainSetup
 {
@@ -12,71 +25,34 @@ public:
    * in Termiante mode on Grid
    * 
    * @param name     Name of train 
-   * @param useCent  Whether to use centrality or not 
-   * @param dateTime Append date and time to name
-   * @param year     Year
-   * @param month    Month 
-   * @param day      Day
-   * @param hour     Hour 
-   * @param min      Minutes
-   */
-  MakeFMDELossTrain(const char* name  = "FMD Energy Loss",
-                   Bool_t   useCent  = false,
-                   Bool_t   dateTime = false, 
-                   UShort_t year     = 0, 
-                   UShort_t month    = 0, 
-                   UShort_t day      = 0, 
-                   UShort_t hour     = 0, 
-                   UShort_t min      = 0) 
-    : TrainSetup(name, dateTime, year, month, day, hour, min), 
-      fUseCent(useCent)
-  {}
-  //__________________________________________________________________
-  /** 
-   * Run this analysis 
-   * 
-   * @param mode     Mode
-   * @param oper     Operation
-   * @param nEvents  Number of events (negative means all)
-   * @param mc       If true, assume simulated events 
-   * @param par      IF true, use par files 
    */
-  void Run(const char* mode, const char* oper, 
-          Int_t nEvents=-1, Bool_t mc=false, Bool_t par=false)
+  MakeFMDELossTrain(const char* name  = "FMD Energy Loss")
+    : TrainSetup(name),
+      fUseCent(false)
   {
-    Exec("ESD", mode, oper, nEvents, mc, par);
+    SetType(kESD);
   }
-  //__________________________________________________________________
   /** 
-   * Run this analysis 
+   * Whether to process per centrality bin
    * 
-   * @param mode     Mode
-   * @param oper     Operation
-   * @param nEvents  Number of events (negative means all)
-   * @param mc       If true, assume simulated events 
-   * @param par      IF true, use par files 
+   * @param use 
    */
-  void Run(EMode mode, EOper oper, Int_t nEvents=-1, Bool_t mc=false,
-          Bool_t par=false)
-  {
-    Exec(kESD, mode, oper, nEvents, mc, par);
-  }
+  void SetUseCentrality(Bool_t use) { fUseCent = use; }
 protected:
   //__________________________________________________________________
   /** 
    * Create the tasks 
    * 
-   * @param mode Processing mode
    * @param par  Whether to use par files 
    * @param mgr  Analysis manager 
    */
-  void CreateTasks(EMode mode, Bool_t par, AliAnalysisManager* mgr)
+  void CreateTasks(EMode /*mode*/, Bool_t par, AliAnalysisManager* mgr)
   {
     // --- Output file name ------------------------------------------
     AliAnalysisManager::SetCommonFileName("forward_eloss.root");
 
     // --- Load libraries/pars ---------------------------------------
-    LoadLibrary("PWGLFforward2", mode, par, true);
+    LoadLibrary("PWGLFforward2", par, true);
     
     // --- Set load path ---------------------------------------------
     gROOT->SetMacroPath(Form("%s:$(ALICE_ROOT)/PWGLF/FORWARD/analysis2",
@@ -98,11 +74,12 @@ protected:
   {
     if (!fUseCent) return;
 
+    const char* name = "CentralitySelection";
     gROOT->Macro("AddTaskCentrality.C");
     AliCentralitySelectionTask* ctask = 
-      dynamic_cast<AliCentralitySelectionTask*>(mgr->GetTask("CentralitySelection"));
+      dynamic_cast<AliCentralitySelectionTask*>(mgr->GetTask(name));
     if (!ctask) return;
-    ctask->SetPass(fESDPass);
+    // ctask->SetPass(fESDPass);
     if (mc) ctask->SetMCInput();
   }
   /** 
@@ -111,6 +88,21 @@ protected:
    * @return 0
    */
   AliVEventHandler* CreateOutputHandler(EType) { return 0; }
+  //__________________________________________________________________
+  const char* ClassName() const { return "MakeFMDElossTrain"; }
+  //__________________________________________________________________
+  void MakeOptions(Runner& r) 
+  {
+    TrainSetup::MakeOptions(r);
+    r.Add(new Option("cent",   "Use centrality"));
+  }
+  //__________________________________________________________________
+  void SetOptions(Runner& r)
+  {
+    TrainSetup::SetOptions(r);
+    Option*   cent     = r.FindOption("cent");
+    if (cent) fUseCent  = cent->AsBool();
+  }
   Bool_t fUseCent; // Whether to use centrality or not 
 };
 
index ba84440a7959392896fc089a0ccd25f55bf6e24d..da8b1b67871e8c09e515ac964ef4791e2773658c 100644 (file)
@@ -1,20 +1,19 @@
+/**
+ * @file   MakeFMDEventPlaneTrain.C
+ * @author Christian Holm Christensen <cholm@master.hehi.nbi.dk>
+ * @date   Fri Jun  1 13:52:39 2012
+ * 
+ * @brief  
+ * 
+ * 
+ * @ingroup pwglf_forward_trains
+ */
 #include "TrainSetup.C"
 
 //====================================================================
 /**
- * Analysis train to make @f$ flow@f$
+ * Analysis train to make @f$ \Psi_R@f$
  * 
- * To run, do 
- * @code 
- * gROOT->LoadMacro("TrainSetup.C");
- * // Make train 
- * MakeFMDEventPlaneTrain t("My Analysis");
- * // Set variaous parameters on the train 
- * t.SetDataDir("/home/of/data");
- * t.AddRun(118506)
- * // Run it 
- * t.Run("LOCAL", "FULL", -1, false, false);
- * @endcode 
  *
  * @ingroup pwglf_forward_flow
  * @ingroup pwglf_forward_trains
@@ -27,65 +26,25 @@ public:
    * in Termiante mode on Grid
    * 
    * @param name     Name of train (free form)
-   * @param dateTime Append date and time to name 
-   * @param year     Year     - if not specified, current year
-   * @param month    Month    - if not specified, current month
-   * @param day      Day      - if not specified, current day
-   * @param hour     Hour     - if not specified, current hour
-   * @param min      Minutes  - if not specified, current minutes
-   */
-  MakeFMDEventPlaneTrain(const char* name, 
-               Bool_t      mc = false,
-               Bool_t      dateTime=false,
-               UShort_t    year  = 0, 
-               UShort_t    month = 0, 
-               UShort_t    day   = 0, 
-               UShort_t    hour  = 0, 
-               UShort_t    min   = 0) 
-    : TrainSetup(name, dateTime, year, month, day, hour, min),
-      fMC(mc)
-  {
-  }
-  /** 
-   * Run this analysis 
-   * 
-   * @param mode     Mode - see TrainSetup::EMode
-   * @param oper     Operation - see TrainSetup::EOperation
-   * @param nEvents  Number of events (negative means all)
-   * @param usePar   If true, use PARs 
-   */
-  void Run(const char* mode, const char* oper, 
-          Int_t nEvents=-1, Bool_t usePar=false)
-  {
-    Exec("AOD", mode, oper, nEvents, false, usePar);
-  }
-  /** 
-   * Run this analysis 
-   * 
-   * @param mode     Mode - see TrainSetup::EMode
-   * @param oper     Operation - see TrainSetup::EOperation
-   * @param nEvents  Number of events (negative means all)
-   * @param usePar   If true, use PARs 
    */
-  void Run(EMode mode, EOper oper, Int_t nEvents=-1, 
-          Bool_t usePar=false)
+  MakeFMDEventPlaneTrain(const char* name) 
+  : TrainSetup(name)
   {
-    Exec(kAOD, mode, oper, nEvents, false, usePar);
+    SetType(kAOD);
   }
 protected:
   /** 
    * Create the tasks 
    * 
-   * @param mode Processing mode
    * @param par  Whether to use par files 
    */
-  void CreateTasks(EMode mode, Bool_t par, AliAnalysisManager*)
+  void CreateTasks(EMode /*mode*/, Bool_t par, AliAnalysisManager*)
   {
     // --- Output file name ------------------------------------------
     AliAnalysisManager::SetCommonFileName("AnalysisResults.root");
 
     // --- Load libraries/pars ---------------------------------------
-    LoadLibrary("PWGLFforward2", mode, par, true);
+    LoadLibrary("PWGLFforward2", par, true);
     
     // --- Set load path ---------------------------------------------
     gROOT->SetMacroPath(Form("%s:$(ALICE_ROOT)/PWGLF/FORWARD/analysis2:"
@@ -105,7 +64,8 @@ protected:
    * @return 0
    */
   AliVEventHandler* CreateOutputHandler(EType) { return 0; }
-  Bool_t fMC;
+  //__________________________________________________________________
+  const char* ClassName() const { return "MakeFMDEventPlaneTrain"; }
 };
 //
 // EOF
index 3a0f350ee1fb3f4ed1e399541e1c2aa1da21c8fa..3c8fa9793b2341ebb3b8fe9c705892a6b753b870 100644 (file)
@@ -1,20 +1,19 @@
+/**
+ * @file   MakeFlowTrain.C
+ * @author Christian Holm Christensen <cholm@master.hehi.nbi.dk>
+ * @date   Fri Jun  1 13:51:48 2012
+ * 
+ * @brief  
+ * 
+ * @ingroup pwglf_forward_trains
+ * 
+ */
 #include "TrainSetup.C"
 
 //====================================================================
 /**
  * Analysis train to make @f$ flow@f$
  * 
- * To run, do 
- * @code 
- * gROOT->LoadMacro("TrainSetup.C");
- * // Make train 
- * MakeFlowTrain t("My Analysis");
- * // Set variaous parameters on the train 
- * t.SetDataDir("/home/of/data");
- * t.AddRun(118506)
- * // Run it 
- * t.Run("LOCAL", "FULL", -1, false, false);
- * @endcode 
  *
  * @ingroup pwglf_forward_flow
  * @ingroup pwglf_forward_trains
@@ -27,101 +26,168 @@ public:
    * in Termiante mode on Grid
    * 
    * @param name     Name of train (free form)
-   * @param dateTime Append date and time to name 
-   * @param year     Year     - if not specified, current year
-   * @param month    Month    - if not specified, current month
-   * @param day      Day      - if not specified, current day
-   * @param hour     Hour     - if not specified, current hour
-   * @param min      Minutes  - if not specified, current minutes
    */
-  MakeFlowTrain(const char* name, 
-               char*       type="", 
-               Bool_t      mc = false,
-               char*       addFlow = "",
-               Int_t       addFType = 0,
-               Int_t       addFOrder = 0,
-               Bool_t      dateTime=false,
-               UShort_t    year  = 0, 
-               UShort_t    month = 0, 
-               UShort_t    day   = 0, 
-               UShort_t    hour  = 0, 
-               UShort_t    min   = 0) 
-    : TrainSetup(name, dateTime, year, month, day, hour, min),
-      fType(type), 
-      fMC(mc),
-      fAddFlow(addFlow),
-      fAddFType(addFType),
-      fAddFOrder(addFOrder)
+  MakeFlowTrain(const char* name)
+  : TrainSetup(name),
+    fType("123456"), 
+    fOutlierCutFMD(4.1), 
+    fOutlierCutSPD(4.1),
+    fAddFlow(""),
+      fAddFType(0),
+    fAddFOrder(0)
   {
+    TrainSetup::SetType(kAOD);
   }
   /** 
-   * Run this analysis 
+   * Set the flow moments to calculate.  A string of or more of the
+   * numbers from 1 to 6
    * 
-   * @param mode     Mode - see TrainSetup::EMode
-   * @param oper     Operation - see TrainSetup::EOperation
-   * @param nEvents  Number of events (negative means all)
-   * @param usePar   If true, use PARs 
+   * @param m 
    */
-  void Run(const char* mode, const char* oper, 
-          Int_t nEvents=-1, Bool_t usePar=false)
-  {
-    Exec("AOD", mode, oper, nEvents, false, usePar, fDebug);
-  }
+  void SetMoments(const char* m) { fType = m; }
   /** 
-   * Run this analysis 
+   * Set parameters on the MC flow after burner 
    * 
-   * @param mode     Mode - see TrainSetup::EMode
-   * @param oper     Operation - see TrainSetup::EOperation
-   * @param nEvents  Number of events (negative means all)
-   * @param usePar   If true, use PARs 
+   * @param f  How the flow should be parameterized 
+   * @param t  Type of parameterization 
+   * @param n  Order of flow to add 
    */
-  void Run(EMode mode, EOper oper, Int_t nEvents=-1, 
-          Bool_t usePar=false)
-  {
-    Exec(kAOD, mode, oper, nEvents, false, usePar, fDebug);
+  void SetFlowAfterburner(const char* f, Int_t t, Int_t n) 
+  { 
+    fAddFlow   = f;
+    fAddFType  = t;
+    fAddFOrder = n;
   }
-  void SetDebugLevel(Int_t dbg = 0) { fDebug = dbg; }
+  /** 
+   * Set wether to use displaced (or satellite) interaction vertices
+   * 
+   * @param use If true, use displaced interaction vertices 
+   */
   void SetUseDispVtx(Bool_t use = kTRUE) { fDispVtx = use; }
+  /** 
+   * Set the outlier cuts 
+   * 
+   * @param fmd Cut for FMD 
+   * @param spd Cut for SPD 
+   */
+  void SetOutlierCuts(Double_t fmd, Double_t spd) 
+  { 
+    fOutlierCutFMD = fmd; 
+    fOutlierCutSPD = spd;
+  }
 protected:
+  //__________________________________________________________________
   /** 
    * Create the tasks 
    * 
-   * @param mode Processing mode
    * @param par  Whether to use par files 
    */
-  void CreateTasks(EMode mode, Bool_t par, AliAnalysisManager*)
+  void CreateTasks(EMode /*mode*/, Bool_t par, AliAnalysisManager*)
   {
     // --- Output file name ------------------------------------------
     AliAnalysisManager::SetCommonFileName("AnalysisResults.root");
 
     // --- Load libraries/pars ---------------------------------------
-    LoadLibrary("PWGLFforward2", mode, par, true);
+    LoadLibrary("PWGLFforward2", par, true);
     
     // --- Set load path ---------------------------------------------
     gROOT->SetMacroPath(Form("%s:$(ALICE_ROOT)/PWGLF/FORWARD/analysis2",
                             gROOT->GetMacroPath()));
 
     // --- Add the task ----------------------------------------------
-    gROOT->Macro(Form("AddTaskForwardFlow.C(\"%s\",%d,%d,\"%s\",%d,%d)",
-                     fType, fMC, fDispVtx, fAddFlow, fAddFType, fAddFOrder));
+    gROOT->Macro(Form("AddTaskForwardFlow.C(\"%s\",%d,%d,%f,%f,\"%s\",%d,%d)",
+                     fType.Data(), 
+                     fMC, 
+                     fDispVtx, 
+                     fOutlierCutFMD, 
+                     fOutlierCutSPD, 
+                     fAddFlow.Data(), 
+                     fAddFType, 
+                     fAddFOrder));
   }
+  //__________________________________________________________________
   /** 
    * Do not the centrality selection
    */
   void CreateCentralitySelection(Bool_t, AliAnalysisManager*) {}
+  //__________________________________________________________________
   /** 
    * Crete output handler - we don't want one here. 
    * 
    * @return 0
    */
   AliVEventHandler* CreateOutputHandler(EType) { return 0; }
-  char* fType;
-  Bool_t fMC;
-  char* fAddFlow;
-  Int_t fAddFType;
-  Int_t fAddFOrder;
-  Int_t fDebug;
-  Bool_t fDispVtx;
+  //__________________________________________________________________
+  /** 
+   * Create MC input handler.  Since this train does not use the MC
+   * information from @c galice.root, @c Kinematics.root, and @c
+   * TrackRefs.root directly, we define this member function to return
+   * null even when doing MC analysis.  This train _only_ looks at the
+   * AOD object of the _processed_ MC data.
+   * 
+   * @return Always 0
+   */
+  AliVEventHandler* CreateMCHandler(EType /*type*/, bool /*mc*/)
+  { 
+    return 0;
+  }
+  //__________________________________________________________________
+  /** 
+   * Get the class name of the train setup 
+   * 
+   * @return Class name 
+   */
+  const char* ClassName() const { return "MakeFlowTrain"; }
+  //__________________________________________________________________
+  /** 
+   * Declare options 
+   * 
+   * @param r Runner object to add options to 
+   */
+  void MakeOptions(Runner& r)
+  {
+    TrainSetup::MakeOptions(r);
+    r.Add(new Option("mom", "Flow moments to analyse", "123456"));
+    r.Add(new Option("afterburner", "What to afterburn", "[eta,phi,b,pid]"));
+    r.Add(new Option("ab-type", "Type of afterburner", "1|2|3|4"));
+    r.Add(new Option("ab-order", "Order of afterburner", "1|2|3|4|5|6"));
+    r.Add(new Option("disp-vtx", "Whether to use satellite interactions"));
+    r.Add(new Option("outlier-fmd", "Outlier cut for FMD", "NSIGMA"));
+    r.Add(new Option("outlier-spd", "Outlier cut for SPD", "NSIGMA"));
+  }
+  //__________________________________________________________________
+  /** 
+   * Set the internal parameters from the defined options in the
+   * Runner object
+   * 
+   * @param r Runner object 
+   */
+  void SetOptions(Runner& r)
+  {
+    TrainSetup::SetOptions(r);
+    Option* mom                = r.FindOption("mom");
+    Option* ab_what    = r.FindOption("afterburner");
+    Option* ab_type    = r.FindOption("ab-type");
+    Option* ab_order   = r.FindOption("ab-order");
+    Option* disp        = r.FindOption("disp-vtx");
+    Option* out_fmd     = r.FindOption("outlier-fmd");
+    Option* out_spd     = r.FindOption("outlier-spd");
+    
+    if (mom && mom->IsSet())  SetMoments(mom->AsString());
+    if (ab_what)              fAddFlow       = ab_what->AsString();
+    if (ab_type)              fAddFType      = ab_type->AsInt();
+    if (ab_order)             fAddFOrder     = ab_type->AsInt();
+    if (disp)                 fDispVtx       = disp->AsBool();    
+    if (out_fmd)              fOutlierCutFMD = out_fmd->AsDouble();
+    if (out_spd)              fOutlierCutSPD = out_spd->AsDouble();
+  }
+  TString  fType;          // Type of moments to determine 
+  Double_t fOutlierCutFMD; // Outlier cut for FMD 
+  Double_t fOutlierCutSPD; // Outlier cut for SPD 
+  TString  fAddFlow;       // After-burn MC input 
+  Int_t    fAddFType;      // How the afterburner is parameterized
+  Int_t    fAddFOrder;     // Order of afterburning
+  Bool_t   fDispVtx;       // Whether to use satellite interactions
 };
 //
 // EOF
diff --git a/PWGLF/FORWARD/analysis2/trains/MakeFullTrain.C b/PWGLF/FORWARD/analysis2/trains/MakeFullTrain.C
new file mode 100644 (file)
index 0000000..c9f07cb
--- /dev/null
@@ -0,0 +1,318 @@
+#include "TrainSetup.C"
+/**
+ * @file   MakeFullTrain.C
+ * @author Christian Holm Christensen <cholm@master.hehi.nbi.dk>
+ * @date   Fri Jun  1 13:53:43 2012
+ * 
+ * @brief  
+ * 
+ * 
+ * @ingroup pwglf_forward_trains
+ */
+
+//====================================================================
+/**
+ * Analysis train to make Forward and Central multiplicity, @f$
+ * dN/d\eta@f$, flow and @f$\Psi_R@f$ in one loop over the ESDs 
+ *
+ * @ingroup pwglf_forward_aod
+ * @ingroup pwglf_forward_dndete
+ * @ingroup pwglf_forward_flow
+ * @ingroup pwglf_forward_trains
+ */
+class MakeFullTrain : public TrainSetup
+{
+public:
+  /** 
+   * Constructor.  Date and time must be specified when running this
+   * in Termiante mode on Grid
+   * 
+   * @param name     Name of train (free form)
+   */
+  MakeFullTrain(const  char* name) 
+    : TrainSetup(name),
+      fSys(0), 
+      fSNN(0), 
+      fField(0),
+      fUseCent(true), 
+      fTrig("INEL"), 
+      fVzMin(-10),
+      fVzMax(+10), 
+      fScheme("FULL"),
+      fCutEdges(false),
+      fFlowMoments("123456"),
+      fFlowAfterburnerWhat("pt eta pid cent"), 
+      fFlowAfterburnerType(1), 
+      fFlowAfterburnerOrder(2),
+      fUseTPCEventPlane(false),
+      fDebugLvl(0)
+  {
+    SetType(kESD);
+  }
+  /** 
+   * Set the collision system 
+   * 
+   * @param sys 1: pp, 2: PbPb, 3: pPb 
+   */
+  void SetCollisionSystem(UShort_t sys) { fSys = sys; }
+  /** 
+   * Set the collision energy in GeV
+   * 
+   * @param sNN @f$\sqrt{s_{NN}}@f$ for PbPb and pPb, @f$\sqrt{s}@f$
+   * for pp
+   */
+  void SetCollisionEnergy(UShort_t sNN) { fSNN = sNN; }
+  /** 
+   * Set the L3 magnetic field in kilo Gaus
+   * 
+   * @param fld Field value 
+   */
+  void SetL3Field(Short_t fld) { fField = fld; }
+  /** 
+   * Whether to use the centrality information 
+   * 
+   * @param use Use it or not
+   */
+  void SetUseCentrality(Bool_t use) { fUseCent = use; } 
+  /** 
+   * Set the trigger type to generate the final @f$dN/d\eta@f$ for
+   *
+   * - INEL
+   * - INEL>0
+   * - NSD 
+   *
+   * Only makes sense for pp.  
+   * 
+   * @param trig Trigger string 
+   */
+  void SetTriggerType(const char* trig) { fTrig = trig; } 
+  /** 
+   * Set the range for the interaction point @f$l \le v_z \le h@f$
+   * 
+   * @param l Lower bound
+   * @param h Upper bound 
+   */
+  void SetVertexRange(Double_t l, Double_t h) { fVzMin = l; fVzMax = h; }
+  /** 
+   * Set the normalization scheme to use.  Only makes sense for pp. 
+   * 
+   * @param s Scheme to use 
+   */
+  void SetNormalizationScheme(const char* s) { fScheme = s; }
+  /** 
+   * Cut off edges of the acceptance 
+   * 
+   * @param cut 
+   */
+  void SetCutEdges(Bool_t cut) { fCutEdges = cut; }
+  /** 
+   * Set the flow moments to calculate.  A string of or more of the
+   * numbers from 1 to 6
+   * 
+   * @param m 
+   */
+  void SetFlowMoments(const char* m) { fFlowMoments = m; }
+  /** 
+   * Set parameters on the MC flow after burner 
+   * 
+   * @param f  How the flow should be parameterized 
+   * @param t  Type of parameterization 
+   * @param n  Order of flow to add 
+   */
+  void SetFlowAfterburner(const char* f, Int_t t, Int_t n) 
+  { 
+    fFlowAfterburnerWhat = f;
+    fFlowAfterburnerType = t;
+    fFlowAfterburnerOrder = n;
+  }
+  /** 
+   * If set to true, add TPC event plane task. 
+   * 
+   * @param use Wheter to include TPC event plane task 
+   */
+  void SetUseTPCEventPlane(Bool_t use) { fUseTPCEventPlane = use; }
+  /** 
+   * Set the debug level on Forward objects
+   * 
+   * @param lvl Debug level
+   */
+  void SetDebugLevel(Int_t lvl) { fDebugLvl = lvl; }
+protected:
+  /** 
+   * Create the tasks 
+   * 
+   * @param par  Whether to use par files 
+   * @param mgr  Analysis manager 
+   */
+  void CreateTasks(EMode /*mode*/, Bool_t par, AliAnalysisManager* mgr)
+  {
+    // --- Output file name ------------------------------------------
+    AliAnalysisManager::SetCommonFileName("forward.root");
+
+    // --- Load libraries/pars ---------------------------------------
+    LoadLibrary("PWGLFforward2", par, true);
+    
+    // --- Set load path ---------------------------------------------
+    gROOT->SetMacroPath(Form("%s:$(ALICE_ROOT)/PWGLF/FORWARD/analysis2",
+                            gROOT->GetMacroPath()));
+    gROOT->SetMacroPath(Form("%s:$(ALICE_ROOT)/ANALYSIS/macros",
+                            gROOT->GetMacroPath()));
+
+    // --- Check if this is MC ---------------------------------------
+    Bool_t mc = mgr->GetMCtruthEventHandler() != 0;
+    
+    // --- Add TPC eventplane task
+    if (fUseTPCEventPlane) gROOT->Macro("AddTaskEventplane.C");
+
+    // --- Task to copy header information ---------------------------
+    gROOT->Macro("AddTaskCopyHeader.C");
+
+    // --- Add the task ----------------------------------------------
+    gROOT->Macro(Form("AddTaskForwardMult.C(%d,%d,%d,%d,%d)", 
+                     mc, fSys, fSNN, fField, fDebugLvl));
+    AddExtraFile(gSystem->Which(gROOT->GetMacroPath(), "ForwardAODConfig.C"));
+
+    // --- Add the task ----------------------------------------------
+    gROOT->Macro(Form("AddTaskCentralMult.C(%d,%d,%d,%d,%d)", 
+                     mc, fSys, fSNN, fField, fDebugLvl));
+    AddExtraFile(gSystem->Which(gROOT->GetMacroPath(), "CentralAODConfig.C"));
+
+    // --- Add the task ----------------------------------------------
+    gROOT->Macro(Form("AddTaskForwarddNdeta.C(\"%s\",%f,%f,%d,\"%s\",%d",
+                     fTrig.Data(), fVzMin, fVzMax, fUseCent, 
+                     fScheme.Data(), fCutEdges));
+
+    // --- Add the task ----------------------------------------------
+    gROOT->Macro(Form("AddTaskCentraldNdeta.C(\"%s\",%f,%f,%d,\"%s\",%d",
+                     fTrig.Data(), fVzMin, fVzMax, fUseCent, 
+                     fScheme.Data(), fCutEdges));
+
+    // --- Add the task ----------------------------------------------
+    gROOT->Macro(Form("AddTaskMCTruthdNdeta.C(\"%s\",%f,%f,%d,\"%s\")",
+                     fTrig.Data(), fVzMin, fVzMax, fUseCent, fScheme.Data()));
+
+    // --- Add the task ----------------------------------------------
+    gROOT->Macro(Form("AddTaskFMDEventPlane.C(%d)", mc));
+
+    // --- Add MC particle task --------------------------------------
+    if (mc) gROOT->Macro("AddTaskMCParticleFilter.C");
+
+    // --- Add the task ----------------------------------------------
+    gROOT->Macro(Form("AddTaskForwardFlow.C(\"%s\",%d,\"%s\",%d,%d)", 
+                     fFlowMoments.Data(), mc, fFlowAfterburnerWhat.Data(), 
+                     fFlowAfterburnerType, fFlowAfterburnerOrder));
+    
+
+  }
+  //__________________________________________________________________
+  /** 
+   * Create physics selection , and add to manager
+   * 
+   * @param mc Whether this is for MC 
+   * @param mgr Manager 
+   */
+  void CreatePhysicsSelection(Bool_t mc,
+                             AliAnalysisManager* mgr)
+  {
+    TrainSetup::CreatePhysicsSelection(mc, mgr);
+
+    // --- Get input event handler -----------------------------------
+    AliInputEventHandler* ih =
+      dynamic_cast<AliInputEventHandler*>(mgr->GetInputEventHandler());
+    if (!ih) 
+      Fatal("CreatePhysicsSelection", "Couldn't get input handler (%p)", ih);
+    
+    // --- Get Physics selection -------------------------------------
+    AliPhysicsSelection* ps = 
+      dynamic_cast<AliPhysicsSelection*>(ih->GetEventSelection());
+    if (!ps) 
+      Fatal("CreatePhysicsSelection", "Couldn't get PhysicsSelection (%p)",ps);
+
+    // --- Ignore trigger class when selecting events.  This means ---
+    // --- that we get offline+(A,C,E) events too --------------------
+    // ps->SetSkipTriggerClassSelection(true);
+  }
+  //__________________________________________________________________
+  /** 
+   * Create the centrality selection only if requested
+   * 
+   * @param mc  Monte-Carlo truth flag 
+   * @param mgr Manager
+   */
+  void CreateCentralitySelection(Bool_t mc, AliAnalysisManager* mgr)
+  {
+    if (!fUseCent) return;
+    TrainSetup::CreateCentralitySelection(mc, mgr);
+  }
+  //__________________________________________________________________
+  const char* ClassName() const { return "MakeFullTrain"; }
+  //__________________________________________________________________
+ void MakeOptions(Runner& r) 
+  {
+    TrainSetup::MakeOptions(r);
+    r.Add(new Option("sys",    "Collision system",    "1|2|3"));
+    r.Add(new Option("sNN",    "Collision energy",    "GEV"));
+    r.Add(new Option("field",  "L3 magnetic field", "kG"));
+    r.Add(new Option("cent",   "Use centrality"));
+    r.Add(new Option("tep",    "Use TPC event plance"));
+    r.Add(new Option("trig",   "Trigger class", "INEL|INEL>0|NSD"));
+    r.Add(new Option("vzmin",  "Low cut on IP z", "CENTIMETER"));
+    r.Add(new Option("vzmax",  "High cut on IP z", "CENTIMETER"));
+    r.Add(new Option("scheme", "Normalization scheme", "NONE|FULL"));
+    r.Add(new Option("mom", "Flow moments to analyse", "123456"));
+    r.Add(new Option("afterburner", "What to afterburn", "[eta,phi,b,pid]"));
+    r.Add(new Option("ab-type", "Type of afterburner", "1|2|3|4"));
+    r.Add(new Option("ab-order", "Order of afterburner", "1|2|3|4|5|6"));
+  }
+  //__________________________________________________________________
+  void SetOptions(Runner& r)
+  {
+    TrainSetup::SetOptions(r);
+    Option* sys                = r.FindOption("sys");
+    Option* sNN                = r.FindOption("sNN");
+    Option* field      = r.FindOption("field");
+    Option* cent       = r.FindOption("cent");
+    Option* tep                = r.FindOption("tep");
+    Option* trig       = r.FindOption("trig");
+    Option* vzmin      = r.FindOption("vzmin");
+    Option* vzmax      = r.FindOption("vzmax");
+    Option* scheme     = r.FindOption("scheme");
+    Option* mom                = r.FindOption("mom");
+    Option* ab_what    = r.FindOption("afterburner");
+    Option* ab_type    = r.FindOption("ab-type");
+    Option* ab_order   = r.FindOption("ab-order");
+
+    if (sys)   SetCollisionSystem(sys->AsInt());
+    if (sNN)   SetCollisionEnergy(sNN->AsInt());
+    if (field) SetL3Field(field->AsInt());
+    if (cent)  SetUseCentrality(cent->AsBool());
+    if (tep)   SetUseTPCEventPlane(tep->AsBool());
+    if (trig   && trig->IsSet())   fTrig     = trig->AsString();
+    if (vzmin  && vzmin->IsSet())  fVzMin    = vzmin->AsDouble();
+    if (vzmax  && vzmax->IsSet())  fVzMax    = vzmax->AsDouble();
+    if (scheme && scheme->IsSet()) fScheme   = scheme->AsString();
+    if (mom && mom->IsSet())      SetFlowMoments(mom->AsString());
+    if (ab_what)              fFlowAfterburnerWhat  = ab_what->AsString();
+    if (ab_type)              fFlowAfterburnerType  = ab_type->AsInt();
+    if (ab_order)             fFlowAfterburnerOrder = ab_type->AsInt();
+  }
+
+  UShort_t  fSys;
+  UShort_t  fSNN;
+  Short_t   fField;
+  Bool_t    fUseCent;
+  TString   fTrig;
+  Double_t  fVzMin;
+  Double_t  fVzMax;
+  TString   fScheme;
+  Bool_t    fCutEdges;
+  TString   fFlowMoments;
+  TString   fFlowAfterburnerWhat;
+  Int_t     fFlowAfterburnerType;
+  Int_t     fFlowAfterburnerOrder;
+  Bool_t    fUseTPCEventPlane;
+  Int_t     fDebugLvl;
+};
+//
+// EOF
+//
index 05f4c6267ce96db4e2099df1cffc4b0f9c9d533e..7ce2c706001189033c95f9145da753117e3454bb 100644 (file)
@@ -1,20 +1,18 @@
+/**
+ * @file   MakeMCCorrTrain.C
+ * @author Christian Holm Christensen <cholm@master.hehi.nbi.dk>
+ * @date   Fri Jun  1 13:54:47 2012
+ * 
+ * @brief  
+ * 
+ * @ingroup pwglf_forward_trains
+ */
 #include "TrainSetup.C"
 
 //====================================================================
 /**
  * Analysis train to make Forward and Central MC corrections
  * 
- * To run, do 
- * @code 
- * gROOT->LoadMacro("TrainSetup.C");
- * // Make train 
- * MakeMCCorrTrain t("My Analysis");
- * // Set variaous parameters on the train 
- * t.SetDataDir("/home/of/data");
- * t.AddRun(118506)
- * // Run it 
- * t.Run("LOCAL", "FULL", -1, false, false);
- * @endcode 
  *
  * @ingroup pwglf_forward_mc
  * @ingroup pwglf_forward_trains
@@ -27,68 +25,26 @@ public:
    * in Termiante mode on Grid
    * 
    * @param name     Name of train (free form)
-   * @param dateTime Append date and time to name 
-   * @param year     Year     - if not specified, current year
-   * @param month    Month    - if not specified, current month
-   * @param day      Day      - if not specified, current day
-   * @param hour     Hour     - if not specified, current hour
-   * @param min      Minutes  - if not specified, current minutes
-   */
-  MakeMCCorrTrain(const  char* name, 
-                 Bool_t       dateTime = false,
-                 UShort_t     year     = 0, 
-                 UShort_t     month    = 0, 
-                 UShort_t     day      = 0, 
-                 UShort_t     hour     = 0, 
-                 UShort_t     min      = 0) 
-    : TrainSetup(name, dateTime, 
-                year, month, day, hour, min)
-  {}
-  /** 
-   * Run this analysis 
-   * 
-   * @param mode     Mode - see TrainSetup::EMode
-   * @param oper     Operation - see TrainSetup::EOperation
-   * @param nEvents  Number of events (negative means all)
-   * @param usePar   If true, use PARs 
    */
-  void Run(const char* mode, const char* oper, 
-          Int_t nEvents=-1, Bool_t usePar=false)
+  MakeMCCorrTrain(const  char* name) 
+  : TrainSetup(name)
   {
-    Info("Run", "Running in mode=%s, oper=%s, events=%d, Par=%d", 
-        mode, oper, nEvents, usePar);
-    Exec("ESD", mode, oper, nEvents, true, usePar);
-  }
-  /** 
-   * Run this analysis 
-   * 
-   * @param mode     Mode - see TrainSetup::EMode
-   * @param oper     Operation - see TrainSetup::EOperation
-   * @param nEvents  Number of events (negative means all)
-   * @param usePar   If true, use PARs 
-   */
-  void Run(EMode mode, EOper oper, Int_t nEvents=-1,
-          Bool_t usePar = false)
-  {
-    Info("Run", "Running in mode=%d, oper=%d, events=%d, Par=%d", 
-        mode, oper, nEvents, usePar);
-    Exec(kESD, mode, oper, nEvents, true, usePar);
+    SetType(kESD);
   }
 protected:
   /** 
    * Create the tasks 
    * 
-   * @param mode Processing mode
    * @param par  Whether to use par files 
    * @param mgr  Analysis manager 
    */
-  void CreateTasks(EMode mode, Bool_t par, AliAnalysisManager* mgr)
+  void CreateTasks(EMode /*mode*/, Bool_t par, AliAnalysisManager* mgr)
   {
     // --- Output file name ------------------------------------------
     AliAnalysisManager::SetCommonFileName("forward_mccorr.root");
 
     // --- Load libraries/pars ---------------------------------------
-    LoadLibrary("PWGLFforward2", mode, par, true);
+    LoadLibrary("PWGLFforward2", par, true);
     
     // --- Set load path ---------------------------------------------
     gROOT->SetMacroPath(Form("%s:$(ALICE_ROOT)/PWGLF/FORWARD/analysis2",
@@ -135,8 +91,8 @@ protected:
    * Do not the centrality selection
    */
   void CreateCentralitySelection(Bool_t, AliAnalysisManager*) {}
-  Double_t fVzMin;     // Least v_z
-  Double_t fVzMax;     // Largest v_z
+  //__________________________________________________________________
+  const char* ClassName() const { return "MakeMCCorrTrain"; }
 };
 
 //
index 334a4dfb2362761c72958264c0b4816a03861d7e..58a795c96e7f660f4bf4cc830869bcecfa163334 100644 (file)
@@ -1,10 +1,21 @@
+/**
+ * @file   MakeQATrain.C
+ * @author Christian Holm Christensen <cholm@master.hehi.nbi.dk>
+ * @date   Fri Jun  1 13:55:02 2012
+ * 
+ * @brief  
+ * 
+ * 
+ * @ingroup pwglf_forward_trains
+ */
 #include "TrainSetup.C"
 
 //====================================================================
 /**
- * Analysis train to do energy loss fits
+ * Analysis train to do Quality assurance
  * 
  * @ingroup pwglf_forward_trains
+ * @ingroup pwglf_forward_qa
  */
 class MakeQATrain : public TrainSetup
 {
@@ -14,71 +25,28 @@ public:
    * in Termiante mode on Grid
    * 
    * @param name     Name of train 
-   * @param useCent  Whether to use centrality or not 
-   * @param dateTime Append date and time to name
-   * @param year     Year
-   * @param month    Month 
-   * @param day      Day
-   * @param hour     Hour 
-   * @param min      Minutes
    */
-  MakeQATrain(const char* name  = "Forward QA",
-             Bool_t   useCent  = false,
-             Bool_t   dateTime = false, 
-             UShort_t year     = 0, 
-             UShort_t month    = 0, 
-             UShort_t day      = 0, 
-             UShort_t hour     = 0, 
-             UShort_t min      = 0) 
-    : TrainSetup(name, dateTime, year, month, day, hour, min), 
-      fUseCent(useCent)
-  {}
-  //__________________________________________________________________
-  /** 
-   * Run this analysis 
-   * 
-   * @param mode     Mode
-   * @param oper     Operation
-   * @param nEvents  Number of events (negative means all)
-   * @param mc       If true, assume simulated events 
-   * @param par      IF true, use par files 
-   */
-  void Run(const char* mode, const char* oper, 
-          Int_t nEvents=-1, Bool_t mc=false, Bool_t par=false)
+  MakeQATrain(const char* name  = "Forward QA") 
+    : TrainSetup(name), 
+      fUseCent(false)
   {
-    Exec("ESD", mode, oper, nEvents, mc, par);
-  }
-  //__________________________________________________________________
-  /** 
-   * Run this analysis 
-   * 
-   * @param mode     Mode
-   * @param oper     Operation
-   * @param nEvents  Number of events (negative means all)
-   * @param mc       If true, assume simulated events 
-   * @param par      IF true, use par files 
-   */
-  void Run(EMode mode, EOper oper, Int_t nEvents=-1, Bool_t mc=false,
-          Bool_t par=false)
-  {
-    Exec(kESD, mode, oper, nEvents, mc, par);
+    SetType(kESD);
   }
 protected:
   //__________________________________________________________________
   /** 
    * Create the tasks 
    * 
-   * @param mode Processing mode
    * @param par  Whether to use par files 
    * @param mgr  Analysis manager 
    */
-  void CreateTasks(EMode mode, Bool_t par, AliAnalysisManager* mgr)
+  void CreateTasks(EMode /*mode*/, Bool_t par, AliAnalysisManager* mgr)
   {
     // --- Output file name ------------------------------------------
     AliAnalysisManager::SetCommonFileName("forward_qa.root");
 
     // --- Load libraries/pars ---------------------------------------
-    LoadLibrary("PWGLFforward2", mode, par, true);
+    LoadLibrary("PWGLFforward2", par, true);
     
     // --- Set load path ---------------------------------------------
     gROOT->SetMacroPath(Form("%s:$(ALICE_ROOT)/PWGLF/FORWARD/analysis2",
@@ -101,10 +69,11 @@ protected:
     if (!fUseCent) return;
 
     gROOT->Macro("AddTaskCentrality.C");
+    const char* cname = "CentralitySelection";
     AliCentralitySelectionTask* ctask = 
-      dynamic_cast<AliCentralitySelectionTask*>(mgr->GetTask("CentralitySelection"));
+      dynamic_cast<AliCentralitySelectionTask*>(mgr->GetTask(cname));
     if (!ctask) return;
-    ctask->SetPass(fESDPass);
+    // ctask->SetPass(fESDPass);
     if (mc) ctask->SetMCInput();
   }
   /** 
@@ -113,6 +82,21 @@ protected:
    * @return 0
    */
   AliVEventHandler* CreateOutputHandler(EType) { return 0; }
+  //__________________________________________________________________
+  const char* ClassName() const { return "MakeQATrain"; }
+  //__________________________________________________________________
+  void MakeOptions(Runner& r) 
+  {
+    TrainSetup::MakeOptions(r);
+    r.Add(new Option("cent",   "Use centrality"));
+  }
+  //__________________________________________________________________
+  void SetOptions(Runner& r)
+  {
+    TrainSetup::SetOptions(r);
+    Option*   cent     = r.FindOption("cent");
+    if (cent) fUseCent  = cent->AsBool();
+  }
   Bool_t fUseCent; // Whether to use centrality or not 
 };
 
index 3b2f8a4241f947e554234931f7f7a57239f9efcd..a50960d074f42b38f428898ca3e21b28ad61d316 100644 (file)
@@ -1,20 +1,20 @@
+/**
+ * @file   MakedNdetaTrain.C
+ * @author Christian Holm Christensen <cholm@master.hehi.nbi.dk>
+ * @date   Fri Jun  1 13:51:26 2012
+ * 
+ * @brief  
+ * 
+ * @ingroup pwglf_forward_trains
+ * 
+ */
+
 #include "TrainSetup.C"
 
 //====================================================================
 /**
  * Analysis train to make @f$ dN/d\eta@f$
  * 
- * To run, do 
- * @code 
- * gROOT->LoadMacro("TrainSetup.C");
- * // Make train 
- * MakedNdetaTrain t("My Analysis");
- * // Set variaous parameters on the train 
- * t.SetDataDir("/home/of/data");
- * t.AddRun(118506)
- * // Run it 
- * t.Run("LOCAL", "FULL", -1, false, false);
- * @endcode 
  *
  * @ingroup pwglf_forward_dndeta
  * @ingroup pwglf_forward_trains
@@ -27,62 +27,16 @@ public:
    * in Termiante mode on Grid
    * 
    * @param name     Name of train (free form)
-   * @param trig     Trigger to use 
-   * @param vzMin    Least @f$ v_z@f$
-   * @param vzMax    Largest @f$ v_z@f$
-   * @param scheme   Normalisation scheme 
-   * @param useCent  Whether to use centrality 
-   * @param dateTime Append date and time to name 
-   * @param year     Year     - if not specified, current year
-   * @param month    Month    - if not specified, current month
-   * @param day      Day      - if not specified, current day
-   * @param hour     Hour     - if not specified, current hour
-   * @param min      Minutes  - if not specified, current minutes
-   */
-  MakedNdetaTrain(const char* name, 
-                 const char* trig="INEL", 
-                 Double_t    vzMin=-10, 
-                 Double_t    vzMax=10, 
-                 const char* scheme="FULL", 
-                 Bool_t      useCent=false,
-                 Bool_t      dateTime=false,
-                 UShort_t    year  = 0, 
-                 UShort_t    month = 0, 
-                 UShort_t    day   = 0, 
-                 UShort_t    hour  = 0, 
-                 UShort_t    min   = 0) 
-    : TrainSetup(name, dateTime, year, month, day, hour, min),
-      fTrig(trig), 
-      fVzMin(vzMin), 
-      fVzMax(vzMax),
-      fScheme(scheme),
-      fUseCent(useCent)
-  {}
-  /** 
-   * Run this analysis 
-   * 
-   * @param mode     Mode - see TrainSetup::EMode
-   * @param oper     Operation - see TrainSetup::EOperation
-   * @param nEvents  Number of events (negative means all)
-   * @param usePar   If true, use PARs 
    */
-  void Run(const char* mode, const char* oper, 
-          Int_t nEvents=-1, Bool_t usePar=false, Int_t dbg=0)
+  MakedNdetaTrain(const char* name)
+  : TrainSetup(name),
+      fTrig("INEL"), 
+      fVzMin(-10), 
+      fVzMax(+10),
+      fScheme(""),
+      fUseCent(false)
   {
-    Exec("AOD", mode, oper, nEvents, false, usePar, dbg);
-  }
-  /** 
-   * Run this analysis 
-   * 
-   * @param mode     Mode - see TrainSetup::EMode
-   * @param oper     Operation - see TrainSetup::EOperation
-   * @param nEvents  Number of events (negative means all)
-   * @param usePar   If true, use PARs 
-   */
-  void Run(EMode mode, EOper oper, Int_t nEvents=-1, 
-          Bool_t usePar=false, Int_t dbg=0)
-  {
-    Exec(kAOD, mode, oper, nEvents, false, usePar, dbg);
+    SetType(kAOD);
   }
   /** 
    * Set the trigger to use (INEL, INEL>0, NSD)
@@ -102,7 +56,7 @@ public:
    * 
    * @param scheme Normalisation scheme options 
    */
-  void SetScheme(const char* scheme) { fScheme = scheme; }
+  void SetNormalizationScheme(const char* scheme) { fScheme = scheme; }
   /** 
    * Whether to use centrality or not 
    * 
@@ -113,16 +67,15 @@ protected:
   /** 
    * Create the tasks 
    * 
-   * @param mode Processing mode
    * @param par  Whether to use par files 
    */
-  void CreateTasks(EMode mode, Bool_t par, AliAnalysisManager*)
+  void CreateTasks(EMode /*mode*/, Bool_t par, AliAnalysisManager*)
   {
     // --- Output file name ------------------------------------------
     AliAnalysisManager::SetCommonFileName("forward_dndeta.root");
 
     // --- Load libraries/pars ---------------------------------------
-    LoadLibrary("PWGLFforward2", mode, par, true);
+    LoadLibrary("PWGLFforward2", par, true);
     
     // --- Set load path ---------------------------------------------
     gROOT->SetMacroPath(Form("%s:$(ALICE_ROOT)/PWGLF/FORWARD/analysis2",
@@ -151,28 +104,32 @@ protected:
   //__________________________________________________________________
   const char* ClassName() const { return "MakedNdetaTrain"; }
   //__________________________________________________________________
-  void WriteConstruction(std::ostream& o, const char* obj) const
+  void MakeOptions(Runner& r) 
   {
-    o << "  const char* trig   = \"" << fTrig << "\";\n"
-      << "  Double_t    vzMin  = " << fVzMin << ";\n"
-      << "  Double_t    vzMax  = " << fVzMax << ";\n"
-      << "  const char* scheme = \"" << fScheme << "\";\n"
-      << "  Bool_t      cent   = " << fUseCent << ";\n"
-      << "  MakedNdetaTrain " << obj << "(\"" 
-      << fName << "\",trig,vzMin,vzMax,scheme,cent);\n";
+    TrainSetup::MakeOptions(r);
+    r.Add(new Option("trig", "Trigger class", "INEL|INEL>0|NSD"));
+    r.Add(new Option("vzmin", "Low cut on IP z", "CENTIMETER"));
+    r.Add(new Option("vzmax", "High cut on IP z", "CENTIMETER"));
+    r.Add(new Option("scheme", "Normalization scheme", "NONE|FULL"));
+    r.Add(new Option("cent",   "Use centrality"));
   }
-  void WriteRun(std::ostream& o, 
-               const char* obj, 
-               const char* /* type */, 
-               const char* mode, 
-               const char* oper, 
-               Bool_t      mc, 
-               Bool_t      usePar, 
-               Int_t       dbg) const
+  //__________________________________________________________________
+  void SetOptions(Runner& r)
   {
-    o << "  " << obj << ".Run(" << mode << ',' << oper << ",-1," 
-      << usePar << ',' << dbg << ");" << std::endl;
+    TrainSetup::SetOptions(r);
+    Option* trig       = r.FindOption("trig");
+    Option* vzmin      = r.FindOption("vzmin");
+    Option* vzmax      = r.FindOption("vzmax");
+    Option* scheme     = r.FindOption("scheme");
+    Option* cent       = r.FindOption("cent");
+
+    if (trig   && trig->IsSet())   fTrig     = trig->AsString();
+    if (vzmin  && vzmin->IsSet())  fVzMin    = vzmin->AsDouble();
+    if (vzmax  && vzmax->IsSet())  fVzMax    = vzmax->AsDouble();
+    if (scheme && scheme->IsSet()) fScheme   = scheme->AsString();
+    if (cent)                      fUseCent  = cent->AsBool();
   }
+  //__________________________________________________________________
   TString  fTrig;      // Trigger to use 
   Double_t fVzMin;     // Least v_z
   Double_t fVzMax;     // Largest v_z
diff --git a/PWGLF/FORWARD/analysis2/trains/MyAnalysis.C b/PWGLF/FORWARD/analysis2/trains/MyAnalysis.C
new file mode 100644 (file)
index 0000000..81f342c
--- /dev/null
@@ -0,0 +1,132 @@
+// MyAnalysis.C 
+#ifndef __CINT__
+# include <AliAnalysisManager.h>
+# include <AliESDEvent.h>
+# include <AliMultiplicity.h>
+# include <AliESDVertex.h>
+# include <TH1D.h>
+# include <TH2D.h>
+#else 
+class TH1D;
+class TH2D;
+#endif 
+#include <AliAnalysisTaskSE.h>
+class MyAnalysis : public AliAnalysisTaskSE
+{
+public:
+  MyAnalysis() 
+    : AliAnalysisTaskSE(), fList(0), fMult(0), fVz(0)
+  {}
+  MyAnalysis(const char* name) 
+  : AliAnalysisTaskSE(name), fList(0), fMult(0), fVz(0)
+  {
+    DefineOutput(1, TList::Class());
+    DefineOutput(2, TList::Class()); // For output from Terminate
+    fBranchNames = "AliMultiplicity.,SPDVertex.,PrimaryVertex.";
+  }
+  MyAnalysis(const MyAnalysis& o) 
+  : AliAnalysisTaskSE(o), fList(o.fList), fMult(o.fMult), fVz(o.fVz)
+  {}
+  virtual ~MyAnalysis() {}
+  MyAnalysis& operator=(const MyAnalysis&) { return *this; }
+  virtual void UserCreateOutputObjects()
+  {
+    fList = new TList();
+    fList->SetName("Sums");
+    fList->SetOwner();
+
+    fMult = new TH2D("mult", "SPD tracklets", 80, -2, 2, 10, -10, 10);
+    fMult->SetXTitle("#eta");
+    fMult->SetYTitle("v_{z} [cm]");
+    fMult->Sumw2();
+    fMult->SetDirectory(0); // Disassociate from file 
+    
+    fVz = new TH1D("vz", "Interaction point", 10, -10, 10);
+    fVz->SetXTitle("v_{z} [cm]");
+    fVz->Sumw2();
+    fVz->SetDirectory(0); // Disassociate from file 
+
+    fList->Add(fMult);
+    fList->Add(fVz);
+
+    PostData(1, fList);
+  }
+  virtual void UserExec(Option_t* )
+  {
+    AliESDEvent* event = dynamic_cast<AliESDEvent*>(InputEvent());
+    if (!event) return;
+    if (event->IsPileupFromSPD(3,0.8))   return;
+
+    const AliESDVertex* vtx = event->GetPrimaryVertexSPD();
+    if (!vtx || !vtx->GetStatus()) return;
+    if (vtx->IsFromVertexerZ() && 
+        (vtx->GetDispersion() > 0.2 ||  vtx->GetZRes() > 1.25 * 0.2))
+      return;
+
+    const AliMultiplicity* mult = event->GetMultiplicity();
+    if (!mult) return;
+    
+    Double_t vz = vtx->GetZ();
+    fVz->Fill(vz);
+
+    Int_t nTracklets = mult->GetNumberOfTracklets();
+    for (Int_t i = 0; i < nTracklets; i++) 
+      fMult->Fill(mult->GetEta(i), vz);
+
+    PostData(1, fList);
+  }
+  void  Terminate(Option_t *)
+  {
+    TList* l = dynamic_cast<TList*>(GetOutputData(1));
+    if (!l) {
+      Warning("Terminate", "No out data # 1 found");
+      return;
+    }
+    TH2D* mult = static_cast<TH2D*>(l->FindObject("mult"));
+    TH1D* vz   = static_cast<TH1D*>(l->FindObject("vz"));
+    if (!mult || !vz) {
+      Warning("Terminate", "Either 'mult' (%p) or 'vz' (%p) or both not found",
+              mult, vz);
+      return;
+    }
+
+    TList* output = new TList;   // Needed for new output from Terminate
+    output->SetName("Results");  // 1st output re-opened read-only
+    output->SetOwner();
+
+    TH2D* out = static_cast<TH2D*>(mult->Clone("dndeta"));
+    out->SetTitle("dN_{ch}/d#eta from SPD tracklets per vertex bin");
+    out->SetZTitle("#frac{1}{N}#frac{dN_{ch}}{d#eta}");
+    out->SetDirectory(0); // Disassociate from file 
+    Int_t    nVz  = mult->GetNbinsY();
+    Int_t    nEta = mult->GetNbinsX();
+    for (Int_t iVz = 1; iVz <= nVz; iVz++) { 
+      Double_t nEv = vz->GetBinContent(iVz);
+      Double_t e1  = vz->GetBinError(iVz);
+      Double_t sca = (nEv == 0 ? 0 : 1. / nEv);
+      for (Int_t iEta = 1; iEta <= nEta; iEta++) { 
+        Double_t c  = mult->GetBinContent(iEta,iVz);
+        Double_t e  = mult->GetBinError(iEta,iVz);
+        Double_t ee = TMath::Sqrt(c*c * e1*e1 + nEv*nEv * e*e) * sca*sca;
+        out->SetBinContent(iEta, iVz, sca * c);
+        out->SetBinError(iEta, iVz, ee);
+      }
+    }
+    Double_t etaMin = mult->GetXaxis()->GetXmin();
+    Double_t etaMax = mult->GetXaxis()->GetXmax();
+    out->Scale(Double_t(nEta) / (etaMax-etaMin));
+
+    output->Add(out);
+    PostData(2, output);
+  }
+protected:
+  TList*  fList;
+  TH2D*   fMult;
+  TH1D*   fVz;
+  ClassDef(MyAnalysis, 1);  
+};
+//
+// EOF
+//
+
diff --git a/PWGLF/FORWARD/analysis2/trains/MyJob.sh b/PWGLF/FORWARD/analysis2/trains/MyJob.sh
new file mode 100755 (executable)
index 0000000..2789450
--- /dev/null
@@ -0,0 +1,19 @@
+#!/bin/sh 
+
+oper=$1 
+if test "x$oper" = "x" ; then oper=init ; fi 
+
+runTrain --class=MyTrain --name=myJob          \
+    --root=v5-33-02b                   \
+    --aliroot=v5-03-24-AN              \
+    --alien=V1.1x                      \
+    --overwrite                                \
+    --date=now                         \
+    --verbose=1                                \
+    --run=178028                       \
+    --run=178026                       \
+    --datadir=/alice/data/2012/LHC12b  \
+    --pattern=ESDs/pass1/*/            \
+    --mode=grid                        \
+    --per-run-merge                    \
+    --oper=${oper}
diff --git a/PWGLF/FORWARD/analysis2/trains/MyTrain.C b/PWGLF/FORWARD/analysis2/trains/MyTrain.C
new file mode 100644 (file)
index 0000000..dd467c3
--- /dev/null
@@ -0,0 +1,42 @@
+#ifndef __CINT__
+# include <AliAnalysisManager.h>
+#else 
+class AliAnalysisManager;
+#endif
+#include "TrainSetup.C"
+class MyTrain : public TrainSetup
+{
+public:
+  MyTrain(const char* name="myTest") : TrainSetup(name) { SetType(kESD); }
+  void CreateTasks(EMode mode, Bool_t par, AliAnalysisManager* mgr)
+  {
+    if (!MakeScriptPAR(mode, "MyAnalysis.C", 
+                       "STEERBase,ESD,AOD,ANALYSIS,OADB,ANALYSISalice"))
+      Fatal("CreateTasks", "Failed to create PAR file");
+    LoadLibrary("MyAnalysis", true, true);
+    
+    Long_t             r = gROOT->ProcessLine("new MyAnalysis(\"test\")");
+    AliAnalysisTaskSE* t = reinterpret_cast<AliAnalysisTaskSE*>(r);
+    if (!t) Fatal("CreateTasks", "Failed to make task");
+    mgr->AddTask(t);
+    
+    AliAnalysisDataContainer* sums = 
+      mgr->CreateContainer("Sums", TList::Class(), 
+                           AliAnalysisManager::kOutputContainer,
+                           AliAnalysisManager::GetCommonFileName());
+    AliAnalysisDataContainer* results = // Needed for output from Terminate
+      mgr->CreateContainer("Results", TList::Class(), 
+                          AliAnalysisManager::kParamContainer, // Important!
+                          AliAnalysisManager::GetCommonFileName());
+    
+    mgr->ConnectOutput(t, 1, sums);
+    mgr->ConnectOutput(t, 2, results);
+    mgr->ConnectInput(t, 0, mgr->GetCommonInputContainer());
+  }
+  void CreateCentralitySelection(Bool_t, AliAnalysisManager*) {}
+  AliVEventHandler* CreateOutputHandler(EType type) { return 0; }
+  const char* ClassName() const { return "MyTrain"; }
+};
+//
+// EOF
+//
index 58f90be19ffa4273eb5574cbeb5336a92584ad7c..1a1338afe620338b3251f2be0011759f62908cd8 100644 (file)
@@ -1,10 +1,21 @@
+/**
+ * @file   QATrain.C
+ * @author Christian Holm Christensen <cholm@master.hehi.nbi.dk>
+ * @date   Fri Jun  1 13:55:50 2012
+ * 
+ * @brief  
+ * 
+ * 
+ * @ingroup pwglf_forward_trains
+ */
+
 #include "TrainSetup.C"
 #include <AliESDInputHandlerRP.h>
 #include <AliCDBManager.h>
 
 //====================================================================
 /**
- * Analysis train to do energy loss fits
+ * Analysis train to do full Quality Assurance train
  * 
  * @ingroup pwglf_forward_trains
  */
@@ -57,57 +68,21 @@ public:
    * in Termiante mode on Grid
    * 
    * @param name     Name of train 
-   * @param useCent  Whether to use centrality or not 
-   * @param dateTime Append date and time to name
-   * @param year     Year
-   * @param month    Month 
-   * @param day      Day
-   * @param hour     Hour 
-   * @param min      Minutes
    */
-  QATrain(UInt_t      run  = 0,
-         UShort_t    flags = kDefaultFlags, 
-         UInt_t      modules = kDefaultModules)
-    : TrainSetup("PilotAnalysis", false, 0, 0, 0, 0, 0), 
-      fRun(run),
-      fFlags(flags), 
-      fModules(modules), 
+  QATrain(const char* name="PilotAnalysis")
+    : TrainSetup(name, false, 0, 0, 0, 0, 0), 
+      fRun(0),
+      fFlags(kDefaultFlags), 
+      fModules(kDefaultModules), 
       fTriggerMask(AliVEvent::kAnyINT), 
       fTriggerHM(AliVEvent::kHighMult),
       fTriggerEMC(AliVEvent::kEMC7), 
       fTriggerMUONBarrel(AliVEvent::kMUU7),
       fCollisionType(0) // 0: pp, 1: PbPb
   {}
-  //__________________________________________________________________
-  /** 
-   * Run this analysis 
-   * 
-   * @param mode     Mode
-   * @param oper     Operation
-   * @param nEvents  Number of events (negative means all)
-   * @param mc       If true, assume simulated events 
-   * @param par      IF true, use par files 
-   */
-  void Run(const char* oper, 
-          Int_t nEvents=-1, Bool_t mc=false, Bool_t par=false)
-  {
-    Exec("ESD", "Local", oper, nEvents, mc, par);
-  }
-  //__________________________________________________________________
-  /** 
-   * Run this analysis 
-   * 
-   * @param mode     Mode
-   * @param oper     Operation
-   * @param nEvents  Number of events (negative means all)
-   * @param mc       If true, assume simulated events 
-   * @param par      IF true, use par files 
-   */
-  void Run(EOper oper, Int_t nEvents=-1, Bool_t mc=false,
-          Bool_t par=false)
-  {
-    Exec(kESD, kLocal, oper, nEvents, mc, par);
-  }
+  void SetFlags(UShort_t flags) { fFlags = flags; }
+  void SetRun(UInt_t run) { fRun = run; }
+  void SetModules(UInt_t m) { fModules = m; }
 protected:
   AliVEventHandler* CreateInputHandler(EType type)
   {
diff --git a/PWGLF/FORWARD/analysis2/trains/RunTrain.C b/PWGLF/FORWARD/analysis2/trains/RunTrain.C
new file mode 100644 (file)
index 0000000..e79a918
--- /dev/null
@@ -0,0 +1,107 @@
+/**
+ * @file   RunTrain.C
+ * @author Christian Holm Christensen <cholm@master.hehi.nbi.dk>
+ * @date   Tue May 29 09:15:22 2012
+ * 
+ * @brief  Wrapper script to run trains 
+ * 
+ * 
+ * @ingroup pwglf_forward_trains
+ */
+class TrainSetup;
+
+/** Global pointer to train setup */
+TrainSetup* trainObj = 0;
+
+/** 
+ * Function to run a train. 
+ *
+ * @verbatim 
+Usage: RunTrain(CLASS,NAME,OPTIONS,RUNS,NEVENTS)
+
+CLASS:       The train-setup class to use
+NAME:        Name of the train
+OPTIONS:     Comma separated list of one or more of:
+             help                           Show this help
+             par                            Use PAR files (PROOF and Grid)
+             mc                             Assume simulation input
+             debug                          Execute in debugger
+             type=AOD|ESD                   Type of train
+             mode=LOCAL|PROOF|GRID          Execution mode
+             oper=TEST|TERMINATE|FULL|INIT  Operation mode
+             date=YYYY-MM-DD HH:MM:SS       Set date string
+             cluster=HOST                   PROOF cluster
+             dataSet=NAME                   Data set (PROOF only)
+             dataDir=DIRECTORY              Data directory
+             pass=NUMBER                    ESD Pass (grid only)
+             verb=NUMBER                    Verbosity
+             root=TAG                       ROOT version (Grid)
+             aliroot=TAG                    AliROOT version (Grid)
+             alien=TAG                      AliEn API version (Grid)
+             overwrite                      Allow overwrite
+RUNS:        Comma separated list of run numbers, or file names of
+             files that contain run numbers
+NEVENTS:     Number of events to analyse
+@endverbatim
+ * 
+ * Individual classes derived from TrainSetup may define additional
+ * (or less) options.  Pass the option @b help to see the list of
+ * available options
+ *
+ * Usually, the train defines the execution mode (ESD or AOD) and the
+ * option @b type should not be given
+ *
+ * If a date is set (option @b date) either to a string of the form 
+ * @c YYYY-MM-DD HH:MM:SS or to the string @c now, then the date will be 
+ * appended to the job name. 
+ * 
+ * A sub-directory named according to the name passed will be made,
+ * and relevant files will copied there.
+ *
+ * @param trainClass Class name of the train setup
+ * @param trainName  Name of the train 
+ * @param options    Options for the train 
+ * @param runs       Runs to add to the train 
+ * @param nEvents    Number of events to analyse 
+ *
+ * @ingroup pwglf_forward_trains_run
+ */
+void RunTrain(const char* trainClass, 
+             const char* trainName, 
+             const char* options="", 
+             const char* runs="", 
+             Int_t       nEvents=-1)
+{
+  const char* builder = 
+    "$(ALICE_ROOT)/PWGLF/FORWARD/analysis2/trains/BuildTrain.C";
+  gROOT->LoadMacro(builder);
+  
+  BuildTrain(trainClass);
+
+  gROOT->ProcessLine(Form("trainObj = new %s(\"%s\")", 
+                         trainClass, trainName));
+  if (!trainObj) {
+    Error("RunTrain", "Failed to make train %s of class %s", 
+         trainName, trainClass);
+    gApplication->Terminate();
+  }
+  TrainSetup::Runner r(*trainObj);
+  if (!r.Init(options)) return;
+  if (r.IsHelpAsked()) { 
+    std::ostream& o = std::cout;
+    o << "Usage: RunTrain(CLASS,NAME,OPTIONS,RUNS,NEVENTS)\n\n"
+      << "CLASS:       The train-setup class to use\n"
+      << "NAME:        Name of the train\n"
+      << "OPTIONS:     Comma separated list of one or more of:\n";
+    r.PrintHelp(o, "           ");
+    o << "RUNS:        Comma separated list of run numbers, or file names of\n"
+      << "             files that contain run numbers\n"
+      << "NEVENTS:     Number of events to analyse\n"
+      << std::endl;
+    return;
+  }
+  r.Run(runs, nEvents);
+}
+/*
+ * EOF
+ */
index 9cd3c12d9cb01ba6626761b6f9192b3da063a88d..4121156ecc291feee67ed2c95a94c12af6ae316d 100644 (file)
@@ -1,6 +1,8 @@
 /**
  * @defgroup pwglf_forward_trains Trains
  * 
+ * Train specifications 
+ *
  * @ingroup pwglf_forward
  */
 /**
@@ -50,91 +52,25 @@ class TArrayI;
 class TChain;
 class AliAnalysisManager;
 class TDatime;
+class TString;
+class TSystemDirectory;
 #endif
 
+
+
 //====================================================================
 /** 
  * Generic set-up of an analysis train using the grid-handler (AliEn plugin). 
- * 
- * Users should define a class that derives from this.  The class
- * should implement the member function CreateTasks to add needed
- * tasks to the train
- * 
- * @code 
- * // MyTrain.C 
- * class MyTrain : public TrainSetup
- * {
- * public:
- *   MyTrain(Bool_t   dateTime = false, 
- *           UShort_t year     = 0, 
- *           UShort_t month    = 0, 
- *           UShort_t day      = 0, 
- *           UShort_t hour     = 0, 
- *           UShort_t min      = 0) 
- *     : TrainSetup("My train", dateTime, year, month, day, hour, min)
- *   {}
- *   void Run(const char* type, const char* mode, const char* oper, 
- *            Int_t nEvents=-1, Bool_t mc=false,
- *            Bool_t usePar=false)
- *   {
- *     Exec(type, mode, oper, nEvents, mc, usePar);
- *   }
- * protected:
- *   void CreateTasks(EMode mode, Bool_t par, AliAnalysisManager* mgr)
- *   {
- *     AliAnalysisManager::SetCommonFileName("my_analysis.root");
- *     LoadLibrary("MyAnalysis", mode, par, true);
- *     Bool_t mc = mgr->GetMCtruthEventHandler() != 0;
- *     gROOT->Macro("MyAnalysis.C");
- *   }
- * };
- * @endcode 
- * 
- * This can then be run like 
- * 
- * @verbatim 
- * > aliroot 
- * Root> .L TrainSetup.C 
- * Root> .L MyTrain.C 
- * Root> MyTrain t;
- * Root> t.Run();
- * @endverbatim 
- * 
- * or as a script 
- * 
- * @code 
- * {
- *   gROOT->LoadMacro("TrainSetup.C");
- *   gROOT->LoadMacro("MyTrain.C");
- *   MyTrain t;
- *   t.Run();
- * }
- * @endcode 
- * 
- * To byte compile this, you need to 
- * - load the ROOT AliEn library
- * - load the analysis libraries 
- * - add $ALICE_ROOT/include to header search 
- * first 
  *
- * @verbatim 
- * > aliroot 
- * Root> gROOT->SetMacroPath(Form("%s:$(ALICE_ROOT)/PWGLF/FORWARD/analysis2:"
- * Root>                          "$ALICE_ROOT/ANALYSIS/macros",
- * Root>                         gROOT->GetMacroPath()));
- * Root> gSystem->AddIncludePath("-I${ALICE_ROOT}/include");
- * Root> gSystem->Load("libRAliEn");
- * Root> gSystem->Load("libANALYSIS");
- * Root> gSystem->Load("libANALYSISalice");
- * Root> gROOT->LoadMacro("TrainSetup.C+");
- * @endverbatim 
- * 
- * 
+ * See also @ref train_setup_doc
+ *
  * @ingroup pwglf_forward_trains
  * 
  */
 struct TrainSetup
 {
+  // Forward declaration 
+  class Runner;
   /** 
    * Data type to process 
    */
@@ -142,7 +78,9 @@ struct TrainSetup
     /** Event Summary Data */
     kESD, 
     /** Analysis Object Data */
-    kAOD
+    kAOD,
+    /** User defined */
+    kUser
   };
   /**
    * How to run the analysis
@@ -170,7 +108,9 @@ struct TrainSetup
     /** Merge and terminate */
     kTerminate, 
     /** Full run */
-    kFull
+    kFull,
+    /** Only intialize */
+    kInitialize
   };
 
 
@@ -182,16 +122,8 @@ struct TrainSetup
    * Constructor 
    * 
    * @param name         Name of analysis (free-form)
-   * @param useDateTime  Whether to append date and time to the name 
-   * @param year         Year - if not specified, taken from current date
-   * @param month        Month - if not specified, taken from current date 
-   * @param day          Day - if not specified, taken from current date 
-   * @param hour         Hour - if not specified, taken from current time  
-   * @param min          Minute - if not specified, taken from current time  
-   */
-  TrainSetup(const char* name, Bool_t useDateTime=true, 
-            UShort_t year=0, UShort_t month=0, 
-            UShort_t day=0, UShort_t hour=0, UShort_t min=0) 
+   */
+  TrainSetup(const char* name)
     : fName(name),
       fEscapedName(name),
       fRootVersion("v5-28-00a"),
@@ -199,11 +131,10 @@ struct TrainSetup
       fAliEnAPIVersion("V1.1x"),
       fProofServer("alicecaf.cern.ch"),
       fDataDir("/alice/data/2010/LHC10c"),
+      fDataPattern("*"),
       fDataSet("/COMMON/COMMON/LHC09a4_run8100X#/esdTree"),
       fXML(""), 
       fNReplica(4),
-      fESDPass(3),
-      fPassPostfix(""),
       fAllowOverwrite(kFALSE),
       fUseGDB(kFALSE), 
       fMaxSplit(50),
@@ -212,227 +143,220 @@ struct TrainSetup
       fListOfSources(),
       fListOfLibraries(),
       fListOfExtras(),
-      fDatime((year<1995?1995:year), month, day, hour, min, 0)
-  {
-    // If no time is specified, set to now 
-    if (useDateTime && (year == 0 || month == 0 || day == 0)) fDatime.Set();
-      
-    fEscapedName = EscapeName(fName, fDatime);
-  }
-  
-  static TString EscapeName(const char* name, const TDatime& datime)
-  {
-    TString escaped = name;
-    char  c[] = { ' ', '/', '@', 0 };
-    char* p   = c;
-    while (*p) { 
-      escaped.ReplaceAll(Form("%c", *p), "_");
-      p++;
-    }
-    if (datime.GetYear() <= 1995 && 
-       datime.GetMonth() == 0 && 
-       datime.GetDay() == 0) return escaped;
-    escaped.Append(Form("_%04d%02d%02d_%02d%02d", 
-                       datime.GetYear(), 
-                       datime.GetMonth(), 
-                       datime.GetDay(), 
-                       datime.GetHour(), 
-                       datime.GetMinute()));
-    return escaped;
-  }    
-  void SetDateTime(UShort_t year, UShort_t month, UShort_t day, 
-                  UShort_t hour, UShort_t minutes)
+      fDatime(1995, 0, 0, 0, 0, 0), 
+      fExecType(kUser), 
+      fExecMode(kLocal), 
+      fExecOper(kFull),
+      fUsePar(false), 
+      fMC(false), 
+      fPerRunMerge(false),
+      fVerbose(0)
   {
-    fDatime.Set((year<1995?1995:year), month, day, hour, minutes, 0);
     fEscapedName = EscapeName(fName, fDatime);
   }
   //__________________________________________________________________
   /** 
-   * Parse a string into a type enum
+   * @{ 
+   * @name Software environment 
+   */
+  /** 
+   * Set ROOT version to use 
    * 
-   * @param type String to pass
+   * @param v Version string of ROOT 
+   */
+  void SetROOTVersion(const char* v)    { fRootVersion = v; }
+  /** 
+   * Set AliROOT version to use 
    * 
-   * @return Enumaration value 
+   * @param v Version string of AliROOT 
    */
-  static EType ParseType(const char* type, Bool_t& /*mc*/)
-  {
-    // mc = false;
-    TString sType(type);
-    sType.ToUpper();
-    EType eType = kESD;
-    // if      (sType.Contains("MC"))    mc    = true;
-    if      (sType.Contains("ESD"))   eType = kESD; 
-    else if (sType.Contains("AOD"))   eType = kAOD;
-    else 
-      Fatal("Run", "Unknown type '%s'", type);
-    
-    return eType;
-  }
-  //__________________________________________________________________
+  void SetAliROOTVersion(const char* v) { fAliRootVersion = v; }
   /** 
-   * Return a string that reflects the passed mode
+   * Set the AliEn API version to use 
    * 
-   * @param eMode Mode 
+   * @param v AliEn API version 
+   */
+  void SetAliEnAPIVersion(const char* v) { fAliEnAPIVersion = v; }
+  /** 
+   * Wether to use par files through-out. Mandetory and enforced in
+   * case of a PROOF job,
    * 
-   * @return String representation of mode 
+   * @param usePar If true, use PAR files - even for base libraries 
    */
-  static const char* ModeString(EMode eMode) 
-  {
-    switch (eMode) {
-    case kLocal:       return "LOCAL";
-    case kProof:       return "PROOF";
-    case kGrid:                return "GRID";
-    }
-    return 0;
-  }
+  void SetUsePar(Bool_t usePar) { fUsePar = usePar; }
+  /* @} */
+
   //__________________________________________________________________
   /** 
-   * Parse a string for mode specifier 
+   * @{ 
+   * @name Input data  
+   */
+  /** 
+   * Set the GRID/Local data dir 
    * 
-   * @param mode Mode string
+   * @param d Directory with data 
+   */
+  void SetDataDir(const char* d) { fDataDir = d; }
+  /** 
+   * Set the glob pattern to search input files in - Grid only
    * 
-   * @return EMode value
+   * @param pattern Glob pattern
    */
-  static EMode ParseMode(const char* mode)
-  {
-    TString sMode(mode);
-    sMode.ToUpper();
-    EMode eMode = kLocal;
-    if      (sMode == "LOCAL") eMode = kLocal;
-    else if (sMode == "PROOF") eMode = kProof;
-    else if (sMode == "GRID")  eMode = kGrid;
-    else 
-      Fatal("Run", "Unknown mode '%s'", mode);
-    return eMode;
-  }
+  void SetDataPattern(const char* pattern) { fDataPattern = pattern; }
+  /** 
+   * Set the PROOF data set 
+   * 
+   * @param d PROOF registered data set 
+   */
+  void SetDataSet(const char* d) { fDataSet = d; }
+  /** 
+   * Set the XML file to use 
+   * 
+   * @param x XML file 
+   */
+  void SetXML(const char* x) { fXML = x; }
+  /** 
+   * Wether to assume the input comes from MC.  If this is set to
+   * true, and the CreateMCHandler member function isn't overloaded to
+   * return null, then the files @c galice.root, @c Kinematics.root,
+   * and @c TrackRefs.root must be present for each input file (@c
+   * AliESDs.root or @c AliAOD.root)
+   * 
+   * @param isMC If true, assume MC input 
+   */
+  void SetMC(Bool_t isMC) { fMC = isMC; } 
+  /* @} */
 
   //__________________________________________________________________
   /** 
-   * Return a string that reflects the passed operation
-   * 
-   * @param eOper Operation
+   * @{ 
+   * @name Grid storage and splitting 
+   */
+  /** 
+   * Set how many replicas of the output we want 
    * 
-   * @return String representation of operation 
+   * @param n Number of replicas requested 
    */
-  static const char* OperString(EOper eOper) 
-  {
-    switch (eOper) {
-    case kTest:                return "TEST";
-    case kOffline:     return "OFFLINE";
-    case kSubmit:      return "SUBMIT";
-    case kTerminate:   return "TERMINATE";
-    case kFull:                return "FULL";
-    }
-    return 0;
-  }
+  void SetNReplica(Int_t n) { fNReplica = n; }
+  /** 
+   * Set the maximum number of files per sub-job.  
+   * 
+   * @param max Maximum number of files per sub-job
+   */  
+  void SetMaxSplit(UShort_t max=50) { fMaxSplit = max; }
+  /* @} */
+
   //__________________________________________________________________
   /** 
-   * Parse an operation string 
+   * @{ 
+   * @name Name and local working directory 
+   */
+  /** 
+   * Set whether to allow overwritting existing files/directories 
    * 
-   * @param oper Operation 
+   * @param allow If true, allow overwritting files/directories
+   */
+  void SetAllowOverwrite(Bool_t allow) { fAllowOverwrite = allow; }
+  /** 
+   * Set the date and time 
    * 
-   * @return An EOper value
+   * @param year     Year (>1994) 
+   * @param month    Month
+   * @param day      Day
+   * @param hour     Hour
+   * @param minutes  Minute
    */
-  static EOper ParseOperation(const char* oper)
+  void SetDateTime(UShort_t year, UShort_t month, UShort_t day, 
+                  UShort_t hour, UShort_t minutes)
   {
-    TString sOper(oper);
-    sOper.ToUpper();
-    EOper eOper = kFull;
-    if      (sOper == "TEST")      eOper = kTest;
-    else if (sOper == "OFFLINE")   eOper = kOffline;
-    else if (sOper == "SUBMIT")    eOper = kSubmit;
-    else if (sOper == "TERMINATE") eOper = kTerminate;
-    else if (sOper == "FULL")      eOper = kFull;
-    else 
-      Fatal("Run", "unknown operation '%s'", oper);
-    return eOper;
+    fDatime.Set((year<1995?1995:year), month, day, hour, minutes, 0);
+    fEscapedName = EscapeName(fName, fDatime);
   }
-
-  //__________________________________________________________________
   /** 
-   * Set ROOT version to use 
+   * Set the date and time from a string.
    * 
-   * @param v Version string of ROOT 
+   * @param date Formatted like YYYY/MM/DD HH:MM:SS
    */
-  void SetROOTVersion(const char* v)    { fRootVersion = v; }
-  //__________________________________________________________________
+  void SetDateTime(const TString& date)
+  {
+    if (date.IsNull())
+      fDatime.Set(1985,0,0,0,0,0);
+    else if (date.EqualTo("now", TString::kIgnoreCase)) 
+      fDatime.Set();
+    else 
+      fDatime.Set(date);
+    fEscapedName = EscapeName(fName, fDatime);
+  }
   /** 
-   * Set AliROOT version to us
+   * Return the escaped nam
    * 
-   * @param v Version string of AliROOT 
+   * @return Escaped name 
    */
-  void SetAliROOTVersion(const char* v) { fAliRootVersion = v; }
+  const TString& EscapedName() const 
+  {
+    return fEscapedName;
+  }
+  /* @} */
   //__________________________________________________________________
   /** 
-   * Set the AliEn API version to use 
-   * 
-   * @param v AliEn API version 
+   * @{ 
+   * @name Execution parameters 
    */
-  void SetAliEnAPIVersion(const char* v) { fAliEnAPIVersion = v; }
-  //__________________________________________________________________
   /** 
    * Set the PROOF server URL
    * 
    * @param s PROOF server URL 
    */
   void SetProofServer(const char* s)    { fProofServer = s; }
-  //__________________________________________________________________
   /** 
-   * Set the GRID/Local data dir 
+   * Set the type of analysis
    * 
-   * @param d Directory with data 
+   * @param type AOD or ESD
    */
-  void SetDataDir(const char* d) { fDataDir = d; }
-  //__________________________________________________________________
+  void SetType(EType type) { fExecType = type; }
   /** 
-   * Set the PROOF data set 
+   * Set the type of analysis
    * 
-   * @param d PROOF registered data set 
+   * @param type AOD or ESD
    */
-  void SetDataSet(const char* d) { fDataSet = d; }
-  //__________________________________________________________________
+  void SetType(const char* type) { SetType(ParseType(type)); }
   /** 
-   * Set the XML file to use 
+   * Set the execution mode of analysis
    * 
-   * @param x XML file 
+   * @param mode LOCAL, PROOF, GRID 
    */
-  void SetXML(const char* x) { fXML = x; }
-  //__________________________________________________________________
+  void SetMode(EMode mode) { fExecMode = mode; }
   /** 
-   * Set how many replicas of the output we want 
+   * Set the execution mode of analysis
    * 
-   * @param n Number of replicas requested 
+   * @param mode LOCAL, PROOF, GRID 
    */
-  void SetNReplica(Int_t n) { fNReplica = n; }
-  //__________________________________________________________________
+  void SetMode(const char* mode) { SetMode(ParseMode(mode)); }
   /** 
-   * Set the ESD pass to use 
+   * Set the execution operation of analysis
    * 
-   * @param pass Pass number 
+   * @param oper FULL, TERMINATE, INIT 
    */
-  void SetESDPass(Int_t pass) { fESDPass = pass; }
-  //__________________________________________________________________
+  void SetOperation(EOper oper) { fExecOper = oper; }
   /** 
-   * Set the ESD pass to use 
+   * Set the execution operation of analysis
    * 
-   * @param postfix Post fix to pass number 
+   * @param oper FULL, TERMINATE, INIT 
    */
-  void SetPassPostfix(const char* postfix) { fPassPostfix = postfix; }
-  //__________________________________________________________________
+  void SetOperation(const char* oper) { SetOperation(ParseOperation(oper)); }
   /** 
    * Use GDB to wrap PROOF slaves 
    * 
    * @param use Whether to use GDB or not 
    */
   void SetUseGDB(Bool_t use=kTRUE) { fUseGDB = use; }
+  /* @} */
+
   //__________________________________________________________________
   /** 
-   * Set the maximum number of files per sub-job.  
-   * 
-   * @param max Maximum number of files per sub-job
-   */  
-  void SetMaxSplit(UShort_t max=50) { fMaxSplit = max; }
-  //__________________________________________________________________
+   * @{ 
+   * @name Stuff to upload 
+   */
   /** 
    * Add a source file to be copied and byte compiled on slaves 
    * 
@@ -444,14 +368,29 @@ struct TrainSetup
     fListOfSources.Add(new TObjString(src)); 
     if (addToExtra) AddExtraFile(src); // Source code isn't copied!
   }
-  //__________________________________________________________________
   /** 
    * Add binary data to be uploaded to slaves 
    * 
    * @param lib Name of binary file 
    */
   void AddLibrary(const char* lib) { fListOfLibraries.Add(new TObjString(lib));}
+  /** 
+   * Add an extra file to be uploaded to slave 
+   * 
+   * @param file Extra file to be uploaded 
+   */
+  void AddExtraFile(const char* file)
+  {
+    if (!file || file[0] == '\0') return;
+    fListOfExtras.Add(new TObjString(file));
+  }
+  /* @} */
+
   //__________________________________________________________________
+  /** 
+   * @{ 
+   * @name Run numbers 
+   */
   /** 
    * Add a run to be analysed
    *  
@@ -461,7 +400,6 @@ struct TrainSetup
   {
     Int_t i = fRunNumbers.fN; fRunNumbers.Set(i+1); fRunNumbers[i] = run;
   }
-  //__________________________________________________________________
   /** 
    * Read run numbers from a file 
    * 
@@ -483,357 +421,76 @@ struct TrainSetup
     }
     file.close();
   }
-  //__________________________________________________________________
   /** 
-   * Add an extra file to be uploaded to slave 
+   * Set the runs to read from a string.  The parts should be
+   * delimited by a character in the string @a delim.  If a non-number
+   * part is seen, it is assumed to be the name of a file containing
+   * run numbers.
    * 
-   * @param file Extra file to be uploaded 
+   * @param runs   String of runs
+   * @param delim  Delimiters 
    */
-  void AddExtraFile(const char* file)
+  void SetRuns(const TString& runs, const char* delim=":, \t") 
   {
-    if (!file || file[0] == '\0') return;
-    fListOfExtras.Add(new TObjString(file));
+    TIter next(runs.Tokenize(delim));
+    TObjString* os = 0;
+    while ((os = static_cast<TObjString*>(next()))) {
+      TString s(os->String());
+      if (s.IsNull()) continue;
+      if (!s.IsDigit()) ReadRunNumbers(s);
+      else              AddRun(s.Atoi());
+    }
   }
-  //__________________________________________________________________
   /** 
-   * Set whether to allow overwritting existing files/directories 
+   * Whether final merge should be done over all runs (argument true),
+   * or for each run individually. 
    * 
-   * @param allow If true, allow overwritting files/directories
+   * @param perRun If true, do final merge over all runs 
    */
-  void SetAllowOverwrite(Bool_t allow) { fAllowOverwrite = allow; }
+  void SetPerRunMerge(Bool_t perRun) { fPerRunMerge = perRun; }
+  /* @} */
   //__________________________________________________________________
+  /**
+   * @{ 
+   * @name Execution 
+   */
   /** 
-   * Service function to make a PAR out of a script.  
-   * 
-   * The script should contain can contain a sub-class of AliAnalysisTask. 
-   * The script will be compiled on the slaves before loading the 
-   * AliAnalysisManager.  Parts to (not) be compiled can be protected like 
-   * 
-   * @code 
-   * #ifdef BUILD_PAR
-   * // This will _only_ be compiled in the servers 
-   * #endif
-   * #ifndef BUILD_PAR
-   * // This will not be compiled in the servers 
-   * #endif
-   * @endcode
-   * 
-   * @param script Script to upload and compile in the PAR
-   * @param deps   Dependency pars 
-   * 
-   * @return true on success. 
-   */
-  static Bool_t MakeScriptPAR(const char* script, const char* deps)
-  {
-    // Get the base name 
-    TString base(gSystem->BaseName(script));
-    Int_t   idx = base.Last('.');
-    if (idx != kNPOS) base.Remove(idx);
-    Bool_t retval = true;
-    // Info("MakeScriptPAR", "script=%s, base=%s", script, base.Data());
-
-    TString tmpdir(gSystem->TempDirectory());
-    int   ltempl = tmpdir.Length() + 1 + 5 + 6 + 1;
-    char* templ  = new char[ltempl];
-    snprintf(templ, ltempl, "%s/trainXXXXXX", tmpdir.Data());
-    if (!mkdtemp(templ)) {
-      Error("MakeScriptPAR", 
-           "Failed to generate temporary directory from template %s", 
-           templ);
-      return false;
-    }
-
-    try {
-      // Check name of script file 
-      TString scr(script);
-      TString ext;
-      if      (scr.EndsWith(".C"))   ext = "C"; 
-      else if (scr.EndsWith(".cxx")) ext = "cxx";
-      else                           { ext = "C"; scr.Append(".C"); }
-      
-      // Check if we can access the file 
-      TString path = TString::Format(".:%s", TROOT::GetMacroPath());
-      char* loc = gSystem->Which(path, scr);
-      if (!loc) throw TString::Format("Script %s not found in %s", 
-                                     scr.Data(), path.Data());
-      TString full(loc);
-      
-      TString dir = TString::Format("%s/%s", templ, base.Data());
-      // Set-up directories 
-      if (gSystem->MakeDirectory(dir) < 0) 
-       throw TString::Format("Could not make directory '%s'", base.Data());
-      
-      if (gSystem->MakeDirectory(Form("%s/PROOF-INF", dir.Data()))) 
-       throw TString::Format("Could not make directory %s/PROOF-INF", 
-                             base.Data());
-      
-      // Copy the script to the setup directory 
-      TString dest = TString::Format("%s/%s.%s", dir.Data(),
-                                    base.Data(), ext.Data());
-      Int_t ret = gSystem->CopyFile(full, dest, true);
-      switch (ret) { 
-      case -1: throw TString::Format("Couldn't open %s for copy", scr.Data());
-      case -2: throw TString::Format("File %s exists", dest.Data());
-      case -3: throw TString::Format("Error while copying %s", scr.Data());
-      }
-      
-      // Make our build file 
-      std::ofstream b(Form("%s/PROOF-INF/BUILD.sh", dir.Data()));
-      if (!b) 
-       throw TString::Format("Failed to open b shell script");
-      b << "#!/bin/sh\n"
-       << "echo BUILD.sh@`hostname`: Building " << base << "\n"
-       << "root.exe -l -b -q PROOF-INF/BUILD.C 2>&1 | tee " << base << ".log\n"
-       << "echo BUILD.sh@`hostname`: done: $?\n"
-       << std::endl;
-      b.close();
-      if (gSystem->Chmod(Form("%s/PROOF-INF/BUILD.sh", dir.Data()), 0755) != 0)
-       throw TString::Format("Failed to set exectuable flags on "
-                             "%s/PROOF-INF/BUILD.sh", dir.Data());
-      
-      std::ofstream u(Form("%s/PROOF-INF/UTIL.C", dir.Data()));
-      if (!u) 
-       throw TString::Format("Failed to open utility script");
-      u << "void LoadROOTLibs() {\n"
-       << "  gSystem->Load(\"libVMC\");\n"
-       << "  gSystem->Load(\"libNet\");\n"
-       << "  gSystem->Load(\"libTree\");\n"
-       << "  gSystem->Load(\"libPhysics\");\n"
-       << "  gSystem->Load(\"libMinuit\");\n"
-       << "}\n\n"
-       << "void AddDep(const char* env) {\n"
-       << "  TString val(gSystem->Getenv(Form(\"%s_INCLUDE\",env)));\n"
-       << "  if (val.IsNull())\n"
-       << "    Warning(\"Add\",\"%s_INCLUDE not defined\", env);\n"
-       << "  else {\n"
-       << "    gSystem->AddIncludePath(Form(\"-I../%s\",val.Data()));\n"
-       << "  }\n"
-       << "}\n\n"
-       << "void LoadDep(const char* name) {\n"
-       << "  gSystem->AddDynamicPath(Form(\"../%s\",name));\n"
-       << "  char* full = gSystem->DynamicPathName(name,true);\n"
-       << "  if (!full) \n"
-       << "   full = gSystem->DynamicPathName(Form(\"lib%s\",name),true);\n"
-       << "  if (!full) \n"
-       << "   full = gSystem->DynamicPathName(Form(\"lib%s.so\",name),true);\n"
-       << "  if (!full) {\n"
-       << "    Warning(\"LoadDep\",\"Module %s not found\", name);\n"
-       << "    return;\n"
-       << "  }\n"
-       << "  gSystem->Load(full);\n"
-       << "}\n"
-       << std::endl;
-      u.close();
-
-      std::ofstream cbuild(Form("%s/PROOF-INF/BUILD.C", dir.Data()));
-      if (!cbuild) 
-       throw TString::Format("Failed to open build script");
-      cbuild << "void BUILD() {\n"
-            << "  gSystem->AddIncludePath(\"-DBUILD_PAR=1\");\n"
-            << "  gROOT->LoadMacro(\"PROOF-INF/UTIL.C\");\n"
-            << "  LoadROOTLibs();\n";
-      TObjArray*  depList = TString(deps).Tokenize(",");
-      TIter       next(depList);
-      TObject*    dep = 0;
-      while ((dep = next())) {
-       cbuild << "  AddDep(\"" << dep->GetName() << "\");\t"
-              << "  LoadDep(\"" << dep->GetName() << "\");\n";
-      }
-      cbuild << "  // gDebug = 5;\n"
-            << "  int ret = gROOT->LoadMacro(\"" 
-            << base << "." << ext << "++g\");\n"
-            << "  if (ret != 0) Fatal(\"BUILD\",\"Failed to build\");\n"
-            << "  else Info(\"BUILD\", \"Made " << base << "\");\n"
-            << "}\n"
-            << std::endl;
-      cbuild.close();
-      
-      // Make our set-up script 
-      std::ofstream setup(Form("%s/PROOF-INF/SETUP.C", dir.Data()));
-      if (!setup) 
-       throw TString::Format("Failed to open setup script");
-      setup << "void SETUP() {\n"
-           << "  gROOT->LoadMacro(\"PROOF-INF/UTIL.C\");\n"
-           << "  LoadROOTLibs();\n"
-           << "  Info(\"SETUP\",\"Loading libraries\");\n";
-      next.Reset();
-      dep = 0;
-      while ((dep = next())) 
-       setup << "  LoadDep(\"" << dep->GetName() << "\");\n";
-      setup << "  // gDebug = 5;\n"
-           << "  gSystem->Load(\"" << base << "_" << ext << ".so\");\n"
-           << "  // gDebug = 0;\n"
-           << "  gROOT->ProcessLine(\".include " << base << "\");\n"
-           << "  gSystem->Setenv(\"" << base << "_INCLUDE\",\"" 
-           << base << "\");\n"
-           << "  Info(\"SETUP\", \"Done\");\n"
-           << "}\n"
-           << std::endl;
-      setup.close();
-
-      ret = gSystem->Exec(Form("(cd %s && tar -czvf %s.par %s)", 
-                              templ, base.Data(),base.Data()));
-      if (ret != 0) 
-       throw TString::Format("Failed to create PAR file %s.PAR from %s", 
-                             base.Data(), dir.Data());
-      ret = gSystem->Exec(Form("mv -vf %s/%s.par %s.par", templ, base.Data(), 
-                              base.Data()));
-      if (ret != 0) 
-       throw TString::Format("Failed to rename %s/%s.par to %s.par: %s", 
-                             templ, base.Data(), base.Data(), 
-                             gSystem->GetError());
-    }
-    catch (TString& e) { 
-      Error("MakeScriptPAR", "%s", e.Data()); 
-      retval = false;
-    }
-    gSystem->Exec(Form("rm -vrf %s", templ));
-    return retval;
-  }
-  //__________________________________________________________________
-  static void PrintFieldName(std::ostream& o, const char* name)
-  {
-    o << "  " << std::left << std::setw(20) << name << ": " << std::flush;
-  }
-  //__________________________________________________________________
-  static void PrintFieldList(std::ostream& o, const char* name, 
-                            const TCollection& c)
-  {
-    PrintFieldName(o, name);
-    Bool_t   first = true;
-    TObject* obj = 0;
-    TIter    next(&c);
-    while ((obj = next())) {
-      o << (first ? "" : ", ") << obj->GetName();
-      first = false;
-    }
-    std::cout << std::endl;
-  }
-  //__________________________________________________________________
-  template <typename T>
-  static void PrintField(std::ostream& o, const char* name, T& value) 
-  {
-    PrintFieldName(o, name);
-    o << value << std::endl;
-  }
-  //__________________________________________________________________
-  /** 
-   * Print the setup 
-   * 
-   */
-  virtual void Print() const 
-  {
-    bool mc = AliAnalysisManager::GetAnalysisManager()
-      ->GetMCtruthEventHandler();
-    std::cout << fName << " train setup\n"
-             << std::boolalpha;
-    PrintField(std::cout, "Escaped name",               fEscapedName);
-    PrintField(std::cout, "ROOT version",              fRootVersion);
-    PrintField(std::cout, "AliROOT version",           fAliRootVersion);
-    PrintField(std::cout, "AliEn API version",         fAliEnAPIVersion);
-    PrintField(std::cout, "Name of proof server",      fProofServer);
-    PrintField(std::cout, "Input directory",           fDataDir);
-    PrintField(std::cout, "Proof data set name",       fDataSet);
-    PrintField(std::cout, "XML collection",            fXML);
-    PrintField(std::cout, "Storage replication",       fNReplica);
-    PrintField(std::cout, "ESD pass",                  fESDPass);
-    PrintField(std::cout, "ESD pass postfix",          fPassPostfix);
-    PrintField(std::cout, "Allow overwrite",            fAllowOverwrite);
-    PrintField(std::cout, "Do GDB debugging",           fUseGDB);
-    PrintField(std::cout, "Max # files per split",      fMaxSplit);
-    PrintField(std::cout, "Monte-Carlo input",         mc);
-
-    PrintFieldName(std::cout, "Run numbers");
-    for (Int_t i = 0; i < fRunNumbers.GetSize(); i++) 
-      std::cout << (i == 0 ? "" : ", ") << fRunNumbers.At(i);
-    std::cout << std::endl;
-
-    PrintFieldList(std::cout, "PAR files",             fListOfPARs);
-    PrintFieldList(std::cout, "Script sources",        fListOfSources);
-    PrintFieldList(std::cout, "Libraries",             fListOfLibraries);
-    PrintFieldList(std::cout, "Extras",                fListOfExtras);
-
-    std::cout << std::noboolalpha << std::endl;
-
-    AliAnalysisGrid* plugin = 
-      AliAnalysisManager::GetAnalysisManager()->GetGridHandler();
-    if (!plugin) return;
-    
-  }
-  //__________________________________________________________________
-  /** 
-   * Initialize the job 
-   * 
-   * @param type   Type of job (ESD, AOD)
-   * @param mode   Where to do it (local, proof, grid)
-   * @param oper   What to do
-   * @param mc     If true, assume MC input
-   * @param usePar Whether to use PAR files 
-   * @param dbg    Debug flag 
+   * Initialize the job 
    * 
    * @return true on success, false otherwise
    */
-  Bool_t Init(EType   type, 
-             EMode   mode, 
-             EOper   oper,
-             Bool_t  mc=false, 
-             bool    usePar=false, 
-             Int_t   dbg=0)
+  Bool_t Init()
   {
-    Info("Init", "Connecting in mode=%d", mode);
-    if (!Connect(mode)) return false;
+    if (fExecMode == kProof) fUsePar    = true;
+
+    // Info("Init", "Connecting in mode=%d", mode);
+    if (!Connect()) return false;
 
     // --- Get current directory and set-up sub-directory ------------
     TString cwd = gSystem->WorkingDirectory();
-    TString nam = EscapedName();
-    Info("Init", "Current directory=%s, escaped name=%s", 
-        cwd.Data(), nam.Data());
-    if (oper != kTerminate) { 
-      if (!fAllowOverwrite && !gSystem->AccessPathName(nam.Data())) {
-       Error("Init", "File/directory %s already exists", nam.Data());
-       return false;
-      }
-      if (gSystem->AccessPathName(nam.Data())) {
-       if (gSystem->MakeDirectory(nam.Data())) {
-         Error("Init", "Failed to make directory '%s'", nam.Data());
-         return false;
-       }
-      }
-    }
-    else {
-      if (gSystem->AccessPathName(nam.Data())) {
-       Error("Init", "File/directory %s does not exists", nam.Data());
-       return false;
-      }
-    }
-      
-    if (!gSystem->ChangeDirectory(nam.Data())) { 
-      Error("Init", "Failed to change directory to %s", nam.Data());
-      return false;
-    }
-    Info("Init", "Made subdirectory %s, and cd'ed there", nam.Data());
-      
+    if (!SetupWorkingDirectory()) return false;
+
     // --- Load the common libraries ---------------------------------
-    if (!LoadCommonLibraries(mode, usePar)) return false;
+    if (!LoadCommonLibraries()) return false;
     
     // --- Create analysis manager -----------------------------------
     AliAnalysisManager *mgr  = new AliAnalysisManager(fName,"Analysis Train");
 
     // In test mode, collect system information on every event 
     // if (oper == kTest)  mgr->SetNSysInfo(1); 
-    if (dbg  >  0)      mgr->SetDebugLevel(dbg);
-    if (mode == kLocal) mgr->SetUseProgressBar(kTRUE, 100);
+    if (fVerbose  >  0)      mgr->SetDebugLevel(fVerbose);
+    if (fExecMode == kLocal) mgr->SetUseProgressBar(kTRUE, 100);
    
     // --- ESD input handler ------------------------------------------
-    AliVEventHandler*  inputHandler = CreateInputHandler(type);
+    AliVEventHandler*  inputHandler = CreateInputHandler(fExecType);
     if (inputHandler) mgr->SetInputEventHandler(inputHandler);
     
     // --- Monte-Carlo ------------------------------------------------
-    AliVEventHandler*  mcHandler = CreateMCHandler(type,mc);
+    AliVEventHandler*  mcHandler = CreateMCHandler(fExecType,fMC);
     if (mcHandler) mgr->SetMCtruthEventHandler(mcHandler);
     
     // --- AOD output handler -----------------------------------------
-    AliVEventHandler*  outputHandler = CreateOutputHandler(type);
+    AliVEventHandler*  outputHandler = CreateOutputHandler(fExecType);
     if (outputHandler) mgr->SetOutputEventHandler(outputHandler);
     
     // --- Include analysis macro path in search path ----------------
@@ -841,22 +498,19 @@ struct TrainSetup
                             cwd.Data(), gROOT->GetMacroPath()));
 
     // --- Physics selction - only for ESD ---------------------------
-    if (type == kESD) CreatePhysicsSelection(mc, mgr);
+    if (fExecType == kESD) CreatePhysicsSelection(fMC, mgr);
     
     // --- Create centrality task ------------------------------------
-    CreateCentralitySelection(mc, mgr);
+    CreateCentralitySelection(fMC, mgr);
 
     // --- Create tasks ----------------------------------------------
-    CreateTasks(mode, usePar, mgr);
+    CreateTasks(fExecMode, fUsePar, mgr);
 
     // --- Create Grid handler ----------------------------------------
     // _must_ be done after all tasks has been added
-    AliAnalysisAlien* gridHandler = CreateGridHandler(type, mode, oper);
+    AliAnalysisAlien* gridHandler = CreateGridHandler();
     if (gridHandler) mgr->SetGridHandler(gridHandler);
     
-    // --- Print setup -----------------------------------------------
-    CreateSetupScript(type, mode, mc, usePar, dbg);
-
     // --- Print setup -----------------------------------------------
     Print();
     // if (mode == kProof) {
@@ -878,32 +532,99 @@ struct TrainSetup
 
     return true;
   }
-  //__________________________________________________________________
+  //------------------------------------------------------------------
   /** 
-   * Initialize the job 
+   * Run the analysis. 
    * 
-   * @param type   Type of analysis (ESD, AOD)
-   * @param mode   Where to do the analysis (LOCAL, GRID, PROOF)
-   * @param oper   What to do 
-   * @param mc     If true, assume MC input
-   * @param usePar Whether to use PARs or not. 
-   * @param dbg    Debug flag 
-   * 
-   * @return true on success, false otherwise 
-   */
-  Bool_t Init(const char*  type="ESD", 
-             const char*  mode="LOCAL", 
-             const char*  oper="FULL",
-             Bool_t       mc=false, 
-             bool         usePar=false, 
-             Int_t        dbg=0)
+   * @param nEvents Number of events to analyse 
+   * @param r       Possible runner object 
+   * @param asShell Passed to SaveSetup
+   */
+  virtual void Run(Int_t nEvents, Runner* r=0, Bool_t asShell=false)
   {
-    return Init(ParseType(type, mc), ParseMode(mode), ParseOperation(oper), 
-               mc, usePar, dbg);
+    // Info("Exec", "Doing exec with type=%d, mode=%d, oper=%d, events=%d "
+    //      "mc=%d, usePar=%d", type, mode, oper, nEvents, mc, usePar);
+
+    TString cwd = gSystem->WorkingDirectory();
+    
+    Init();
+    if (r) SaveSetup(*r, nEvents, asShell);
+    if (fExecOper == kInitialize) return;
+    
+    // --- Create the chain ------------------------------------------
+    TChain* chain = CreateChain();
+    if (fExecMode == kLocal && !chain) {
+      Error("Exec", "No chain defined in local mode!");
+      return;
+    }
+
+    // --- Get manager and execute -----------------------------------
+    AliAnalysisManager *mgr  =AliAnalysisManager::GetAnalysisManager();
+    Long64_t ret = StartAnalysis(mgr, chain, nEvents);
+
+    // Make sure we go back 
+    gSystem->ChangeDirectory(cwd.Data());
+
+    // Return. 
+    if (ret < 0) Error("Exec", "Analysis failed");
   }
+  //------------------------------------------------------------------
+  /** 
+   * Print the setup 
+   * 
+   */
+  virtual void Print() const 
+  {
+    bool mc=AliAnalysisManager::GetAnalysisManager()->GetMCtruthEventHandler();
+    std::cout << fName << " train setup\n"
+             << std::boolalpha;
+    PrintField(std::cout, "Escaped name",               fEscapedName);
+    PrintField(std::cout, "ROOT version",              fRootVersion);
+    PrintField(std::cout, "AliROOT version",           fAliRootVersion);
+    PrintField(std::cout, "AliEn API version",         fAliEnAPIVersion);
+    PrintField(std::cout, "Name of proof server",      fProofServer);
+    PrintField(std::cout, "Input directory",           fDataDir);
+    PrintField(std::cout, "Data pattern",              fDataPattern);
+    PrintField(std::cout, "Proof data set name",       fDataSet);
+    PrintField(std::cout, "XML collection",            fXML);
+    PrintField(std::cout, "Storage replication",       fNReplica);
+    PrintField(std::cout, "Allow overwrite",            fAllowOverwrite);
+    PrintField(std::cout, "Do GDB debugging",           fUseGDB);
+    PrintField(std::cout, "Max # files per split",      fMaxSplit);
+    PrintField(std::cout, "Monte-Carlo input",         fMC);
+    PrintField(std::cout, "Monte-Carlo handler",        mc);
+    PrintField(std::cout, "Per run merge",              fPerRunMerge);
+    PrintFieldName(std::cout, "Run numbers");
+    for (Int_t i = 0; i < fRunNumbers.GetSize(); i++) 
+      std::cout << (i == 0 ? "" : ", ") << fRunNumbers.At(i);
+    std::cout << std::endl;
+
+    PrintFieldList(std::cout, "PAR files",             fListOfPARs);
+    PrintFieldList(std::cout, "Script sources",        fListOfSources);
+    PrintFieldList(std::cout, "Libraries",             fListOfLibraries);
+    PrintFieldList(std::cout, "Extras",                fListOfExtras, "\n  ");
+
+    std::cout << std::noboolalpha << std::endl;
 
+    AliAnalysisGrid* plugin = 
+      AliAnalysisManager::GetAnalysisManager()->GetGridHandler();
+    if (!plugin) return;
+    
+  }
+  /** 
+   * Whether to be verbosity level.  0 means no messages, while higher
+   * numbers increase the verbosity
+   * 
+   * @param verb Verbosity level 
+   */
+  void SetVerbose(Int_t verb) { fVerbose = verb; }
+  /* @} */
 protected:
   //__________________________________________________________________
+  /** 
+   * @{ 
+   * @name Copying 
+   */
   /** 
    * Copy constructor 
    * 
@@ -911,15 +632,16 @@ protected:
    */
   TrainSetup(const TrainSetup& o)
   : fName(o.fName),
+    fEscapedName(o.fEscapedName),
     fRootVersion(o.fRootVersion),
     fAliRootVersion(o.fAliRootVersion),
+    fAliEnAPIVersion(o.fAliEnAPIVersion),
     fProofServer(o.fProofServer),
     fDataDir(o.fDataDir),      
+    fDataPattern(o.fDataPattern),
     fDataSet(o.fDataSet),      
     fXML(o.fXML),      
     fNReplica(o.fNReplica),
-    fESDPass(o.fESDPass),
-    fPassPostfix(o.fPassPostfix),
     fAllowOverwrite(o.fAllowOverwrite),
     fUseGDB(o.fUseGDB),
     fMaxSplit(o.fMaxSplit),
@@ -928,7 +650,14 @@ protected:
     fListOfSources(),
     fListOfLibraries(),
     fListOfExtras(),
-    fDatime(o.fDatime)
+    fDatime(o.fDatime),
+    fExecType(o.fExecType), 
+    fExecMode(o.fExecMode), 
+    fExecOper(o.fExecOper),
+    fUsePar(o.fUsePar), 
+    fMC(o.fMC), 
+    fPerRunMerge(o.fPerRunMerge),
+    fVerbose(o.fVerbose)
   {
     if (isdigit(fName[0])) { 
       Warning("TrainSetup", "Name starts with a digit, prepending 'a' to name");
@@ -944,7 +673,7 @@ protected:
     TIter nextExa(&o.fListOfExtras);
     while ((obj = nextExa())) fListOfExtras.Add(obj->Clone());
   }
-  //__________________________________________________________________
+  //------------------------------------------------------------------
   /** 
    * Assignment operator 
    * 
@@ -959,10 +688,10 @@ protected:
     fAliRootVersion    = o.fAliRootVersion;
     fProofServer       = o.fProofServer;
     fDataDir           = o.fDataDir;   
+    fDataPattern        = o.fDataPattern;
     fDataSet           = o.fDataSet;   
     fXML               = o.fXML;       
     fNReplica          = o.fNReplica;  
-    fESDPass            = o.fESDPass;
     fRunNumbers         = o.fRunNumbers;
     TObject* obj = 0;
     TIter nextPar(&o.fListOfPARs);
@@ -976,172 +705,286 @@ protected:
 
     return *this;
   }
+  /* @} */
 
   //__________________________________________________________________
   /** 
-   * Run this analysis 
-   * 
-   * @param type    Type of input for analysis  (kESD, kAOD)
-   * @param mode    Mode of job (kLocal, kProof, kGrid)
-   * @param oper    Operation 
-   * @param nEvents Number of events to analyse (<0 means all)
-   * @param mc      Whether to connect MC data 
-   * @param usePar  Whether to use PARs  
-   * @param dbg     Debug level
-   */
-  void Exec(const char*  type, 
-           const char*  mode="GRID", 
-           const char*  oper="FULL", 
-           Int_t        nEvents=-1, 
-           Bool_t       mc=false, 
-           Bool_t       usePar=false, 
-           Int_t        dbg=0)
+   * @{ 
+   * @name Utility functions 
+   */
+  /** 
+   * Escape bad elements of the name 
+   * 
+   * @param name   Name to escape 
+   * @param datime Date and Time 
+   * 
+   * @return escaped name 
+   */  
+  static TString EscapeName(const char* name, const TDatime& datime)
   {
-    Info("Exec", "Doing exec with type=%s, mode=%s, oper=%s, events=%d "
-        "mc=%d, usePar=%d", type, mode, oper, nEvents, mc, usePar);
-    EType eType = ParseType(type, mc);
-    EMode eMode = ParseMode(mode);
-    EOper eOper = ParseOperation(oper);
-
-    Exec(eType, eMode, eOper, nEvents, mc, usePar, dbg);
+    TString escaped = name;
+    char  c[] = { ' ', '/', '@', 0 };
+    char* p   = c;
+    while (*p) { 
+      escaped.ReplaceAll(Form("%c", *p), "_");
+      p++;
+    }
+    if (datime.GetYear() <= 1995 ||
+       datime.GetMonth() == 0 || 
+       datime.GetDay() == 0) return escaped;
+    escaped.Append(Form("_%04d%02d%02d_%02d%02d", 
+                       datime.GetYear(), 
+                       datime.GetMonth(), 
+                       datime.GetDay(), 
+                       datime.GetHour(), 
+                       datime.GetMinute()));
+    return escaped;
+  }    
+  //------------------------------------------------------------------
+  static void PrintFieldName(std::ostream& o, const char* name)
+  {
+    o << "  " << std::left << std::setw(25) << name << ": " << std::flush;
   }
-
-  //__________________________________________________________________
+  //------------------------------------------------------------------
+  static void PrintFieldList(std::ostream& o, const char* name, 
+                            const TCollection& c, const char* sep=", ")
+  {
+    PrintFieldName(o, name);
+    Bool_t   first = true;
+    TObject* obj = 0;
+    TIter    next(&c);
+    while ((obj = next())) {
+      o << (first ? "" : sep) << obj->GetName();
+      first = false;
+    }
+    std::cout << std::endl;
+  }
+  //------------------------------------------------------------------
+  template <typename T>
+  static void PrintField(std::ostream& o, const char* name, T& value) 
+  {
+    PrintFieldName(o, name);
+    o << value << std::endl;
+  }
+  //------------------------------------------------------------------
   /** 
-   * Run this analysis 
-   * 
-   * @param type    Type of input for analysis  (kESD, kAOD)
-   * @param mode    Mode of job (kLocal, kProof, kGrid)
-   * @param oper    Operation 
-   * @param nEvents Number of events to analyse (<0 means all)
-   * @param mc      Whether to connect MC data 
-   * @param usePar  Whether to use PARs  
-   * @param dbg     Debug level
-   */
-  void Exec(EType  type, 
-           EMode  mode, 
-           EOper  oper, 
-           Int_t  nEvents, 
-           Bool_t mc, 
-           Bool_t usePar, 
-           Int_t  dbg=0)
+   * Return a string that reflects the passed operation
+   * 
+   * @param eOper Operation
+   * 
+   * @return String representation of operation 
+   */
+  static const char* OperString(EOper eOper) 
   {
-    Info("Exec", "Doing exec with type=%d, mode=%d, oper=%d, events=%d "
-        "mc=%d, usePar=%d", type, mode, oper, nEvents, mc, usePar);
-
-    TString cwd = gSystem->WorkingDirectory();
-    if (mode == kProof) usePar    = true;
-    
-    if (!Init(type, mode, oper, mc, usePar, dbg))  return;
-
-    // --- Create the chain ------------------------------------------
-    TChain* chain = CreateChain(type, mode, oper, mc);
-    if (mode == kLocal && !chain) {
-      Error("Exec", "No chain defined in local mode!");
-      return;
+    switch (eOper) {
+    case kTest:                return "TEST";
+    case kOffline:     return "OFFLINE";
+    case kSubmit:      return "SUBMIT";
+    case kTerminate:   return "TERMINATE";
+    case kFull:                return "FULL";
+    case kInitialize:   return "INIT";
     }
-
-    // --- Get manager and execute -----------------------------------
-    AliAnalysisManager *mgr  =AliAnalysisManager::GetAnalysisManager();
-    Long64_t ret = StartAnalysis(mgr, mode, chain, nEvents);
-
-    // Make sure we go back 
-    gSystem->ChangeDirectory(cwd.Data());
-
-    // Return. 
-    if (ret < 0) Error("Exec", "Analysis failed");
+    return 0;
   }
-  //__________________________________________________________________
+  //------------------------------------------------------------------
   /** 
-   * Start the analysis 
+   * Parse an operation string 
    * 
-   * @param mgr       Analysis manager
-   * @param mode      Run mode
-   * @param chain     Input data (local and proof only)
-   * @param nEvents   Number of events to analyse 
+   * @param oper Operation 
+   * 
+   * @return An EOper value
    */
-  Long64_t StartAnalysis(AliAnalysisManager* mgr, 
-                        EMode               mode, 
-                        TChain*             chain,
-                        Int_t               nEvents)
+  static EOper ParseOperation(const char* oper)
   {
-    // --- Run the analysis ------------------------------------------
-    switch (mode) { 
-    case kLocal: 
-      if (!chain) {
-       Error("StartAnalysis", "No chain defined");
-       return -1;
-      }
-      if (nEvents < 0) nEvents = chain->GetEntries();
-      return mgr->StartAnalysis(ModeString(mode), chain, nEvents);
-    case kProof: 
-      if (fDataSet.IsNull()) {
-       if (!chain) { 
-         Error("StartAnalysis", "No chain defined");
-         return -1;
-       }
-       if (nEvents < 0) nEvents = chain->GetEntries();
-       return mgr->StartAnalysis(ModeString(mode), chain, nEvents);
-      }
-      return mgr->StartAnalysis(ModeString(mode), fDataSet);
-    case kGrid: 
-      if (nEvents < 0)
-       return mgr->StartAnalysis(ModeString(mode));
-      return mgr->StartAnalysis(ModeString(mode), nEvents);
+    TString sOper(oper);
+    sOper.ToUpper();
+    EOper eOper = kFull;
+    if      (sOper.Contains("TEST"))      eOper = kTest;
+    else if (sOper.Contains("OFFLINE"))   eOper = kOffline;
+    else if (sOper.Contains("SUBMIT"))    eOper = kSubmit;
+    else if (sOper.Contains("TERMINATE")) eOper = kTerminate;
+    else if (sOper.Contains("FULL"))      eOper = kFull;
+    else if (sOper.Contains("INIT"))      eOper = kInitialize;
+    else 
+      Fatal("Run", "unknown operation '%s'", oper);
+    return eOper;
+  }
+  //------------------------------------------------------------------
+  /** 
+   * Return a string that reflects the passed mode
+   * 
+   * @param eType Type of analysis 
+   * 
+   * @return String representation of execution type
+   */
+  static const char* TypeString(EType eType) 
+  {
+    switch (eType) {
+    case kESD: return "ESD";
+    case kAOD: return "AOD";
+    case kUser:        return "USER";
     }
-    // We should never get  here 
-    return -1;
+    return 0;
   }
-  //__________________________________________________________________
+  //------------------------------------------------------------------
   /** 
-   * Return the escaped name 
+   * Parse a string into a type enum
    * 
-   * @return Escaped name 
+   * @param type String to pass
+   * 
+   * @return Enumaration value 
    */
-  const TString& EscapedName() const 
+  static EType ParseType(const char* type)
   {
-    return fEscapedName;
+    // mc = false;
+    TString sType(type);
+    sType.ToUpper();
+    EType eType = kESD;
+    // if      (sType.Contains("MC"))    mc    = true;
+    if      (sType.Contains("ESD"))   eType = kESD; 
+    else if (sType.Contains("AOD"))   eType = kAOD;
+    else 
+      Fatal("Run", "Unknown type '%s'", type);
+    
+    return eType;
+  }
+  //------------------------------------------------------------------
+  /** 
+   * Return a string that reflects the passed mode
+   * 
+   * @param eMode Mode 
+   * 
+   * @return String representation of mode 
+   */
+  static const char* ModeString(EMode eMode) 
+  {
+    switch (eMode) {
+    case kLocal:       return "LOCAL";
+    case kProof:       return "PROOF";
+    case kGrid:                return "GRID";
+    }
+    return 0;
+  }
+  //------------------------------------------------------------------
+  /** 
+   * Parse a string for mode specifier 
+   * 
+   * @param mode Mode string
+   * 
+   * @return EMode value
+   */
+  static EMode ParseMode(const char* mode)
+  {
+    TString sMode(mode);
+    sMode.ToUpper();
+    EMode eMode = kLocal;
+    if      (sMode.Contains("LOCAL")) eMode = kLocal;
+    else if (sMode.Contains("PROOF")) eMode = kProof;
+    else if (sMode.Contains("GRID"))  eMode = kGrid;
+    else 
+      Fatal("Run", "Unknown mode '%s'", mode);
+    return eMode;
   }
+  /* @} */
+
+
   //__________________________________________________________________
+  /** 
+   * @{ 
+   * @name Overloadable creators 
+   */
   /** 
    * Create a grid handler 
    * 
-   * @param type Data type
-   * @param mode Run mode 
-   * @param oper Operation 
-   * 
    * @return Grid handler 
    */
   virtual AliAnalysisAlien* 
-  CreateGridHandler(EType type, EMode mode, EOper oper)
+  CreateGridHandler()
   {
-    if (mode != kGrid) return 0;
+    if (fExecMode != kGrid) return 0;
 
     TString name = EscapedName();
 
     // Create the plug-in object, and set run mode 
     AliAnalysisAlien* plugin = new AliAnalysisAlien();
-    plugin->SetRunMode(OperString(oper));
+    plugin->SetRunMode(OperString(fExecOper == kInitialize ? 
+                                 kFull : fExecOper));
     
     // Production mode - not used here 
     // plugin->SetProductionMode();
     
     // Set output to be per run 
-    plugin->SetOutputToRunNo();
+    plugin->SetOutputToRunNo(true); 
 
     // Set the job tag 
     plugin->SetJobTag(fName);
 
     // Set number of test files - used in test mode only 
     plugin->SetNtestFiles(1);
+
+    // Set name of generated analysis macro 
+    plugin->SetAnalysisMacro(Form("%s.C", name.Data()));
     
-    // Set required version of software 
-    if (!fAliEnAPIVersion.IsNull()) plugin->SetAPIVersion(fAliEnAPIVersion);
-    if (!fRootVersion.IsNull())     plugin->SetROOTVersion(fRootVersion);
-    if (!fAliRootVersion.IsNull())  plugin->SetAliROOTVersion(fAliRootVersion);
+    // Maximum number of sub-jobs 
+    // plugin->SetSplitMaxInputFileNumber(25);
+    
+    // Set the Time-To-Live 
+    plugin->SetTTL(70000);
+    
+    // Re-submit failed jobs as long as the ratio of failed jobs is
+    // below this percentage. 
+    plugin->SetMasterResubmitThreshold(95);
 
-    // Keep log files 
-    plugin->SetKeepLogs();
+    // Set the input format
+    plugin->SetInputFormat("xml-single");
+
+    // Set the name of the generated jdl 
+    plugin->SetJDLName(Form("%s.jdl", name.Data()));
+
+    // Set the name of the generated executable 
+    plugin->SetExecutable(Form("%s.sh", name.Data()));
+    
+    // Set the job price !?
+    plugin->SetPrice(1);
+
+    // Set whether to merge via JDL 
+    plugin->SetMergeViaJDL(true);
+    
+    // Fast read otion 
+    plugin->SetFastReadOption(false);
+
+    // Whether to overwrite existing output 
+    plugin->SetOverwriteMode(true);
+
+    // Set the executable binary name and options 
+    plugin->SetExecutableCommand("aliroot -b -q -x");
+    
+    // Split by storage element - must be lower case!
+    plugin->SetSplitMode("se");
+    plugin->SetSplitMaxInputFileNumber(fMaxSplit);
+
+    // Disable default outputs 
+    plugin->SetDefaultOutputs(true);
+
+    // Merge parameters 
+    plugin->SetMaxMergeFiles(20);
+    plugin->SetMergeExcludes("AliAOD.root "
+                           "*EventStat*.root "
+                           "*event_stat*.root");
+    
+    // Keep log files 
+    plugin->SetKeepLogs();
+
+    // Set the working directory to be the trains name (with special
+    // characters replaced by '_' and the date appended), and also set
+    // the output directory (relative to working directory)
+    plugin->SetGridWorkingDir(name.Data());
+    plugin->SetGridOutputDir("output");
+
+    // Set required version of software 
+    if (!fAliEnAPIVersion.IsNull()) plugin->SetAPIVersion(fAliEnAPIVersion);
+    if (!fRootVersion.IsNull())     plugin->SetROOTVersion(fRootVersion);
+    if (!fAliRootVersion.IsNull())  plugin->SetAliROOTVersion(fAliRootVersion);
 
     // Declare root of input data directory 
     TString dataDir(fDataDir);
@@ -1151,30 +994,27 @@ protected:
 
     // Data search patterns 
     TString pat;
-    if (AliAnalysisManager::GetAnalysisManager()->GetMCtruthEventHandler() ||
-       type == kAOD) {
-      pat = "*/";
-      plugin->SetRunPrefix(type == kAOD ? "000" : "");
-    }
+    if (AliAnalysisManager::GetAnalysisManager()->GetMCtruthEventHandler())
+      plugin->SetRunPrefix("");
     else {
-      pat = Form("*ESDs/pass%d%s/*/", fESDPass, fPassPostfix.Data());
       plugin->SetRunPrefix("000");
     }
-    pat.Append(Form("*%s.root", type == kESD ? "ESDs" : "AOD"));
+    pat = fDataPattern;
+    if (!pat.EndsWith("/")) pat.Append("/");
+    pat.Append(Form("*%s.root", fExecType == kESD ? "ESDs" : "AOD"));
     plugin->SetDataPattern(pat);
 
     // Add the run numbers 
+    Int_t nRun = 0;
     for (Int_t i = 0; i < fRunNumbers.fN; i++) {
       if (fRunNumbers[i] < 0) continue; 
       plugin->AddRunNumber(fRunNumbers[i]);
+      nRun++;
     }
+    // Set number of runs per master - set to one to per run
+    if (fPerRunMerge) plugin->SetNrunsPerMaster(1);
+    else              plugin->SetNrunsPerMaster(nRun+1);
     
-    // Set the working directory to be the trains name (with special
-    // characters replaced by '_' and the date appended), and also set
-    // the output directory (relative to working directory)
-    plugin->SetGridWorkingDir(name.Data());
-    plugin->SetGridOutputDir("output");
-
     // Enable configured PARs 
     TIter nextPar(&fListOfPARs);
     TObject* parName;
@@ -1190,18 +1030,6 @@ protected:
     TString addLibs = SetupLibraries();
     if (!addLibs.IsNull()) plugin->SetAdditionalLibs(addLibs.Data());
     
-    // Disable default outputs 
-    plugin->SetDefaultOutputs(true);
-
-    // Merge parameters 
-    plugin->SetMaxMergeFiles(20);
-    plugin->SetMergeExcludes("AliAOD.root "
-                           "*EventStat*.root "
-                           "*event_stat*.root");
-
-    // Set number of runs per master - set to one to per run
-    plugin->SetNrunsPerMaster(1);
-
     // Loop over defined containers in the analysis manager, 
     // and declare these as outputs 
     TString listOfAODs  = "";
@@ -1239,50 +1067,10 @@ protected:
     // Disabled for now 
     // plugin->SetOutputArchive(outArchive);
     
-    // Set name of generated analysis macro 
-    plugin->SetAnalysisMacro(Form("%s.C", name.Data()));
-    
-    // Maximum number of sub-jobs 
-    // plugin->SetSplitMaxInputFileNumber(25);
-    
-    // Set the Time-To-Live 
-    plugin->SetTTL(70000);
-    
-    // Re-submit failed jobs as long as the ratio of failed jobs is
-    // below this percentage. 
-    plugin->SetMasterResubmitThreshold(95);
-
-    // Set the input format
-    plugin->SetInputFormat("xml-single");
-
-    // Set the name of the generated jdl 
-    plugin->SetJDLName(Form("%s.jdl", name.Data()));
-
-    // Set the name of the generated executable 
-    plugin->SetExecutable(Form("%s.sh", name.Data()));
-    
-    // Set the job price !?
-    plugin->SetPrice(1);
-
-    // Set whether to merge via JDL 
-    plugin->SetMergeViaJDL(true);
-    
-    // Fast read otion 
-    plugin->SetFastReadOption(false);
-
-    // Whether to overwrite existing output 
-    plugin->SetOverwriteMode(true);
-
-    // Set the executable binary name and options 
-    plugin->SetExecutableCommand("aliroot -b -q -x");
-    
-    // Split by storage element - must be lower case!
-    plugin->SetSplitMode("se");
-    plugin->SetSplitMaxInputFileNumber(fMaxSplit);
 
     return plugin;
   }
-  //__________________________________________________________________
+  //------------------------------------------------------------------
   /** 
    * Create input handler 
    * 
@@ -1295,10 +1083,11 @@ protected:
     switch (type) {
     case kESD: return new AliESDInputHandler(); 
     case kAOD: return new AliAODInputHandler(); 
+    case kUser: return 0;
     }
     return 0;
   }
-  //__________________________________________________________________
+  //------------------------------------------------------------------
   /** 
    * Create input handler 
    * 
@@ -1307,16 +1096,16 @@ protected:
    * 
    * @return 
    */
-  virtual AliVEventHandler* CreateMCHandler(EType type, bool mc)
+  virtual AliVEventHandler* CreateMCHandler(EType /*type*/, bool mc)
   {
     if (!mc)          return 0;
-    if (type != kESD) return 0;
+    // if (type != kESD) return 0;
     Info("CreateMCHandler", "Making MC handler");
     AliMCEventHandler* mcHandler = new AliMCEventHandler();
     mcHandler->SetReadTR(true); 
     return mcHandler;
   }
-  //__________________________________________________________________
+  //------------------------------------------------------------------
   /** 
    * Create output event handler 
    * 
@@ -1334,12 +1123,15 @@ protected:
     case kAOD: 
       ret->SetOutputFileName("AliAOD.pass2.root");
       break;
+    case kUser: 
+      break;
     }
+    
     return ret;
   }
-  //__________________________________________________________________
+  //------------------------------------------------------------------
   /** 
-   * Create physics selection , and add to manager
+   * Create physics selection, and add to manager
    * 
    * @param mc Whether this is for MC 
    * @param mgr Manager
@@ -1350,9 +1142,9 @@ protected:
     gROOT->Macro(Form("AddTaskPhysicsSelection.C(%d)", mc));
     mgr->RegisterExtraFile("event_stat.root");
   }
-  //__________________________________________________________________
+  //------------------------------------------------------------------
   /** 
-   * Create physics selection , and add to manager
+   * Create centrality selection, and add to manager
    * 
    * @param mc Whether this is for MC 
    * @param mgr Manager
@@ -1364,32 +1156,416 @@ protected:
     AliCentralitySelectionTask* ctask = 
       dynamic_cast<AliCentralitySelectionTask*>(mgr->GetTask(name));
     if (!ctask) return;
-    // ctask->SetPass(fESDPass);
     if (mc) ctask->SetMCInput();
   }
-  //__________________________________________________________________
+  //------------------------------------------------------------------
   /** 
-   * Create analysis tasks 
+   * Create analysis tasks.  Must be overloaded by sub-class
    * 
    * @param mode Run mode
    * @param mgr  Manager
    * @param par  Whether to use pars 
    */
   virtual void CreateTasks(EMode mode, Bool_t par, AliAnalysisManager* mgr)=0;
+  /* @} */
+
   //__________________________________________________________________
+  /** 
+   * @{ 
+   * @name Library loading 
+   */
+  //------------------------------------------------------------------
+  /** 
+   * Load common libraries 
+   * 
+   * @return true on success 
+   */
+  Bool_t LoadCommonLibraries() 
+  {
+    if (!gSystem->Getenv("ALICE_ROOT")) { 
+      Error("LoadCommonLibraries", "Local AliROOT not available");
+      return false;
+    }
+    gSystem->Load("libTree.so");
+    gSystem->Load("libGeom.so");
+    gSystem->Load("libVMC.so");
+    gSystem->Load("libPhysics.so");
+    gSystem->Load("libMinuit.so");
+    if (fExecMode == kProof) { 
+      gProof->Exec("gSystem->Load(\"libTree.so\");");
+      gProof->Exec("gSystem->Load(\"libGeom.so\");");
+      gProof->Exec("gSystem->Load(\"libMinuit.so\");");
+      gProof->Exec("gSystem->Load(\"libVMC.so\");");
+
+      
+    }
+
+    Bool_t ret   = true;
+    Bool_t basic = fExecMode == kGrid ? false : fUsePar;
+    
+    ret &= LoadLibrary("STEERBase",     basic, false);
+    ret &= LoadLibrary("ESD",           basic, false);
+    ret &= LoadLibrary("AOD",           basic, false);
+    ret &= LoadLibrary("ANALYSIS",      basic, true);
+    ret &= LoadLibrary("OADB",          basic, true);
+    ret &= LoadLibrary("ANALYSISalice", basic, true);
+
+    return ret;
+  }
+  //------------------------------------------------------------------
+  /** 
+   * Load a library 
+   * 
+   * @param what What library to load
+   * @param par  If true, load as PAR
+   * @param rec  If true, also load on slaves
+   * 
+   * @return true on success 
+   */
+  Bool_t LoadLibrary(const char* what, Bool_t par, Bool_t rec=false)
+  {
+    if (!what || what[0] == '\0') return true;
+    
+    TString module(what);
+    TString libName(what);
+    if (!libName.BeginsWith("lib")) { 
+      // Check if the library corresponds to a compiled macro 
+      if (!gSystem->AccessPathName(Form("%s_C.so", libName.Data()))) {
+       libName.Append("_C");
+      }
+      else if (!gSystem->AccessPathName(Form("../%s_C.so", libName.Data()))) {
+       libName = Form("../%s_C", what);
+      }
+      else 
+       libName = Form("lib%s", libName.Data());
+    }
+    if (!libName.EndsWith(".so"))   libName.Append(".so");
+
+    Int_t ret = 0;
+
+    switch (fExecMode) { 
+    case kLocal: // Just load and exit 
+      if (gSystem->Load(libName.Data()) < 0) {
+       Error("LoadLibrary", "Failed to load library %s", libName.Data());
+       return false;
+      }
+      break;
+    case kGrid: 
+      if (par) { 
+       ret = SetupPAR(what) ? 0 : -1;
+       if (rec) fListOfPARs.Add(new TObjString(what));
+      } else  {
+       ret = gSystem->Load(libName.Data());
+       if (rec) fListOfLibraries.Add(new TObjString(libName));
+      }
+      break;
+    case kProof: 
+      Info("LoadLibrary", "Uploading %s", what);
+      ret = gProof->UploadPackage(what, TProof::kRemoveOld);
+      if (ret < 0)  {  
+         ret = gProof->UploadPackage(gSystem->ExpandPathName(Form("../%s.par",
+                                                                  what)));
+       if (ret < 0) {  
+         ret = 
+           gProof->UploadPackage(gSystem
+                                 ->ExpandPathName(Form("$ALICE_ROOT/%s.par", 
+                                                       what)));
+         if (ret < 0) {
+           Error("LoadLibrary", 
+                 "Could not find module %s.par in current directory nor "
+                 "in $ALICE_ROOT", module.Data());
+           return false;
+         }
+       }
+      }
+      Info("LoadLibrary", "Enabling package %s", what);
+      ret = gProof->EnablePackage(what);
+      break;
+    }
+    if (ret < 0) { 
+      Error("LoadLibrary", "Couldn't load %s", what);
+      return false;
+    }
+    return true;
+  }
+  /* @} */
+
+  //__________________________________________________________________
+  /** 
+   * @{ 
+   * @name PAR generation from script 
+   */
+  /** 
+   * Service function to make a PAR out of a script.  
+   * 
+   * The script should contain can contain a sub-class of AliAnalysisTask. 
+   * The script will be compiled on the slaves before loading the 
+   * AliAnalysisManager.  Parts to (not) be compiled can be protected like 
+   * 
+   * @code 
+   * #ifdef BUILD_PAR
+   * // This will _only_ be compiled in the servers 
+   * #endif
+   * #ifndef BUILD_PAR
+   * // This will not be compiled in the servers 
+   * #endif
+   * @endcode
+   * 
+   * @param mode   Execution mode (Grid, PROOF, Local)
+   * @param script Script to upload and compile in the PAR
+   * @param deps   Dependency pars 
+   * 
+   * @return true on success. 
+   */
+  static Bool_t MakeScriptPAR(EMode mode, const char* script, const char* deps)
+  {
+    // Get the base name 
+    Info("MakeScriptPAR", "Making par file for %s", script);
+    TString base(gSystem->BaseName(script));
+    Int_t   idx = base.Last('.');
+    if (idx != kNPOS) base.Remove(idx);
+    Bool_t retval = true;
+    // Info("MakeScriptPAR", "script=%s, base=%s", script, base.Data());
+
+    if (mode == kLocal) { 
+      if (gROOT->LoadMacro(Form("%s.C++g", base.Data())) < 0)
+       return false;
+      return true;
+    }
+
+    TString tmpdir(gSystem->TempDirectory());
+    int   ltempl = tmpdir.Length() + 1 + 5 + 6 + 1;
+    char* templ  = new char[ltempl];
+    snprintf(templ, ltempl, "%s/trainXXXXXX", tmpdir.Data());
+    if (!mkdtemp(templ)) {
+      Error("MakeScriptPAR", 
+           "Failed to generate temporary directory from template %s", 
+           templ);
+      return false;
+    }
+
+    try {
+      // Check name of script file 
+      TString scr(script);
+      TString ext;
+      if      (scr.EndsWith(".C"))   ext = "C"; 
+      else if (scr.EndsWith(".cxx")) ext = "cxx";
+      else                           { ext = "C"; scr.Append(".C"); }
+      
+      // Check if we can access the file 
+      TString path = TString::Format(".:%s", TROOT::GetMacroPath());
+      char* loc = gSystem->Which(path, scr);
+      if (!loc) throw TString::Format("Script %s not found in %s", 
+                                     scr.Data(), path.Data());
+      TString full(loc);
+      
+      TString dir = TString::Format("%s/%s", templ, base.Data());
+      // Set-up directories 
+      if (gSystem->MakeDirectory(dir) < 0) 
+       throw TString::Format("Could not make directory '%s'", base.Data());
+      
+      if (gSystem->MakeDirectory(Form("%s/PROOF-INF", dir.Data()))) 
+       throw TString::Format("Could not make directory %s/PROOF-INF", 
+                             base.Data());
+      
+      // Copy the script to the setup directory 
+      TString dest = TString::Format("%s/%s.%s", dir.Data(),
+                                    base.Data(), ext.Data());
+      Int_t ret = gSystem->CopyFile(full, dest, true);
+      switch (ret) { 
+      case -1: throw TString::Format("Couldn't open %s for copy", scr.Data());
+      case -2: throw TString::Format("File %s exists", dest.Data());
+      case -3: throw TString::Format("Error while copying %s", scr.Data());
+      }
+      
+      // Make our build file 
+      // Info("MakeScriptPAR", "Making build script %s/PROOF-INF/BUILD.sh", dir.Data());
+      std::ofstream b(Form("%s/PROOF-INF/BUILD.sh", dir.Data()));
+      if (!b) 
+       throw TString::Format("Failed to open b shell script");
+      b << "#!/bin/sh\n"
+       << "echo BUILD.sh@`hostname`: Building " << base << "\n"
+       << "root.exe -l -b -q PROOF-INF/BUILD.C 2>&1 | tee " << base << ".log\n"
+       << "echo BUILD.sh@`hostname`: done: $?\n"
+       << std::endl;
+      b.close();
+      if (gSystem->Chmod(Form("%s/PROOF-INF/BUILD.sh", dir.Data()), 0755) != 0)
+       throw TString::Format("Failed to set exectuable flags on "
+                             "%s/PROOF-INF/BUILD.sh", dir.Data());
+      
+      // Info("MakeScriptPAR", "Making utility script %s/PROOF-INF/UTIL.C", dir.Data());
+      std::ofstream u(Form("%s/PROOF-INF/UTIL.C", dir.Data()));
+      if (!u) 
+       throw TString::Format("Failed to open utility script");
+      u << "void LoadROOTLibs() {\n"
+       << "  gSystem->Load(\"libVMC\");\n"
+       << "  gSystem->Load(\"libNet\");\n"
+       << "  gSystem->Load(\"libTree\");\n"
+       << "  gSystem->Load(\"libPhysics\");\n"
+       << "  gSystem->Load(\"libMinuit\");\n"
+       << "}\n\n"
+       << "void AddAliROOT() {\n"
+       << "  TString val(gSystem->Getenv(\"ALICE_ROOT\"));\n"
+       << "  if (val.IsNull())\n"
+       << "    Warning(\"Add\",\"ALICE_ROOT not defined\");\n"
+       << "  else\n"
+       << "    gSystem->AddIncludePath(Form(\"-I%s/include\",val.Data()));\n"
+       << "}\n\n"
+       << "void AddDep(const char* env) {\n"
+       << "  TString val(gSystem->Getenv(Form(\"%s_INCLUDE\",env)));\n"
+       << "  if (val.IsNull())\n"
+       << "    Warning(\"Add\",\"%s_INCLUDE not defined\", env);\n"
+       << "  else {\n"
+       << "    gSystem->AddIncludePath(Form(\"-I../%s\",val.Data()));\n"
+       << "  }\n"
+       << "}\n\n"
+       << "void LoadDep(const char* name) {\n"
+       << "  gSystem->AddDynamicPath(Form(\"../%s\",name));\n"
+       << "  char* full = gSystem->DynamicPathName(name,true);\n"
+       << "  if (!full) \n"
+       << "   full = gSystem->DynamicPathName(Form(\"lib%s\",name),true);\n"
+       << "  if (!full) \n"
+       << "   full = gSystem->DynamicPathName(Form(\"lib%s.so\",name),true);\n"
+       << "  if (!full) {\n"
+       << "    Warning(\"LoadDep\",\"Module %s not found\", name);\n"
+       << "    return;\n"
+       << "  }\n"
+       << "  gSystem->Load(full);\n"
+       << "}\n"
+       << std::endl;
+      u.close();
+
+      // Info("MakeScriptPAR", "Making utility script %s/PROOF-INF/BUILD.C", dir.Data());
+      std::ofstream cbuild(Form("%s/PROOF-INF/BUILD.C", dir.Data()));
+      if (!cbuild) 
+       throw TString::Format("Failed to open build script");
+      cbuild << "void BUILD() {\n"
+            << "  gSystem->AddIncludePath(\"-DBUILD_PAR=1\");\n"
+            << "  gROOT->LoadMacro(\"PROOF-INF/UTIL.C\");\n"
+            << "  LoadROOTLibs();\n"
+            << "  AddAliROOT();\n";
+      TObjArray*  depList = TString(deps).Tokenize(",");
+      TIter       next(depList);
+      TObject*    dep = 0;
+      while ((dep = next())) {
+       cbuild << "  AddDep(\"" << dep->GetName() << "\");\t"
+              << "  LoadDep(\"" << dep->GetName() << "\");\n";
+      }
+      cbuild << "  // gDebug = 5;\n"
+            << "  int ret = gROOT->LoadMacro(\"" 
+            << base << "." << ext << "++g\");\n"
+            << "  if (ret != 0) Fatal(\"BUILD\",\"Failed to build\");\n"
+            << "  // else Info(\"BUILD\", \"Made " << base << "\");\n"
+            << "}\n"
+            << std::endl;
+      cbuild.close();
+      
+      // Make our set-up script 
+      // Info("MakeScriptPAR", "Making setup script %s/PROOF-INF/SETUP.C", dir.Data());
+      std::ofstream setup(Form("%s/PROOF-INF/SETUP.C", dir.Data()));
+      if (!setup) 
+       throw TString::Format("Failed to open setup script");
+      setup << "void SETUP() {\n"
+           << "  gROOT->LoadMacro(\"PROOF-INF/UTIL.C\");\n"
+           << "  LoadROOTLibs();\n"
+           << "  // Info(\"SETUP\",\"Loading libraries\");\n";
+      next.Reset();
+      dep = 0;
+      while ((dep = next())) 
+       setup << "  LoadDep(\"" << dep->GetName() << "\");\n";
+      setup << "  // gDebug = 5;\n"
+           << "  // Info(\"SETUP\",\"Loading " << base << "_" << ext << ".so\");\n"
+           << "  gSystem->Load(\"" << base << "_" << ext << ".so\");\n"
+           << "  // gDebug = 0;\n"
+           << "  gROOT->ProcessLine(\".include " << base << "\");\n"
+           << "  gSystem->Setenv(\"" << base << "_INCLUDE\",\"" 
+           << base << "\");\n"
+           << "  // Info(\"SETUP\", \"Done\");\n"
+           << "}\n"
+           << std::endl;
+      setup.close();
+
+      // Info("MakeScriptPAR", "Packing up tar-archive");
+      ret = gSystem->Exec(Form("(cd %s && tar -czf %s.par %s)", 
+                              templ, base.Data(),base.Data()));
+      if (ret != 0) 
+       throw TString::Format("Failed to create PAR file %s.PAR from %s", 
+                             base.Data(), dir.Data());
+
+      // Info("MakeScriptPAR", "Moving PAR archive");
+      ret = gSystem->Exec(Form("mv -f %s/%s.par %s.par", templ, base.Data(), 
+                              base.Data()));
+      if (ret != 0) 
+       throw TString::Format("Failed to rename %s/%s.par to %s.par: %s", 
+                             templ, base.Data(), base.Data(), 
+                             gSystem->GetError());
+    }
+    catch (TString& e) { 
+      Error("MakeScriptPAR", "%s", e.Data()); 
+      retval = false;
+    }
+    // Info("MakeScriptPAR", "Removing temperary directory %s", templ);
+    gSystem->Exec(Form("rm -rf %s", templ));
+    return retval;
+  }
+  /* @} */
+
+  //__________________________________________________________________
+  /** 
+   * @{ 
+   * @name Execution implementation
+   */
+  /** 
+   * Start the analysis 
+   * 
+   * @param mgr       Analysis manager
+   * @param chain     Input data (local and proof only)
+   * @param nEvents   Number of events to analyse 
+   */
+  Long64_t StartAnalysis(AliAnalysisManager* mgr, 
+                        TChain*             chain,
+                        Int_t               nEvents)
+  {
+    // --- Run the analysis ------------------------------------------
+    TString mode = ModeString(fExecMode);
+    switch (fExecMode) { 
+    case kLocal: 
+      if (!chain) {
+       Error("StartAnalysis", "No chain defined");
+       return -1;
+      }
+      if (nEvents < 0) nEvents = chain->GetEntries();
+      return mgr->StartAnalysis(mode, chain, nEvents);
+    case kProof: 
+      if (fDataSet.IsNull()) {
+       if (!chain) { 
+         Error("StartAnalysis", "No chain defined");
+         return -1;
+       }
+       if (nEvents < 0) nEvents = chain->GetEntries();
+       return mgr->StartAnalysis(mode, chain, nEvents);
+      }
+      return mgr->StartAnalysis(mode, fDataSet);
+    case kGrid: 
+      if (nEvents < 0)
+       return mgr->StartAnalysis(mode);
+      return mgr->StartAnalysis(mode, nEvents);
+    }
+    // We should never get  here 
+    return -1;
+  }
+  //------------------------------------------------------------------
   /** 
    * Connect to external services (Proof and/or grid)
    * 
-   * @param mode Running mode 
-   * 
    * @return true on success 
    */
-  virtual Bool_t Connect(EMode mode)
+  virtual Bool_t Connect()
   {
-    if (mode == kLocal) return true;
+    if (fExecMode == kLocal) return true;
                          
     // --- Set-up connections to Proof cluster and alien -------------
-    if (mode == kProof) { 
+    if (fExecMode == kProof) { 
       Info("Connect", "Opening connection to proof server");
       // --- Find user name ------------------------------------------
       TString userName(gSystem->Getenv("alien_API_USER"));
@@ -1447,17 +1623,16 @@ protected:
     }
 
     // --- Open a connection to the grid -----------------------------
-#if 1
+
     TGrid::Connect("alien://");
     if (!gGrid || !gGrid->IsConnected()) { 
       // This is only fatal in grid mode 
       Error("Connect", "Failed to connect to AliEN");
-      if (mode == kGrid) return false; 
+      if (fExecMode == kGrid) return false; 
       return true;
     }
-    if (mode == kGrid) return true;
+    if (fExecMode == kGrid) return true;
 
-    
     // --- Set and make output directory -----------------------------
     TString name = EscapedName();
     TString homeDir(gGrid->GetHomeDirectory());
@@ -1476,116 +1651,102 @@ protected:
     // Make output directory 
     gGrid->Mkdir("proof_output");
     gGrid->Cd("proof_output");
-#endif
+
     return true;
   }      
-  //__________________________________________________________________
+  //------------------------------------------------------------------
   /** 
-   * Load common libraries 
+   * Get the output directory (local or Grid)
    * 
-   * @param mode Running mode                  
-   * @param par  If true, load as PARs 
+   * @param mode Mode of execution 
    * 
-   * @return true on success 
+   * @return Path to output directory 
    */
-  Bool_t LoadCommonLibraries(EMode mode, Bool_t par) 
+  TString GetOutputDirectory(EMode mode) const 
   {
-    if (!gSystem->Getenv("ALICE_ROOT")) { 
-      Error("LoadCommonLibraries", "Local AliROOT not available");
-      return false;
+    TString ret(fEscapedName);
+    if (mode != kGrid) return ret;
+    
+    AliAnalysisManager* am = AliAnalysisManager::GetAnalysisManager();
+    if (!am) { 
+      Warning("GetOutputDirectory", "No analysis manager defined yet");
+      return ret;
     }
-    gSystem->Load("libTree.so");
-    gSystem->Load("libGeom.so");
-    gSystem->Load("libVMC.so");
-    gSystem->Load("libPhysics.so");
-    gSystem->Load("libMinuit.so");
-    if (mode == kProof) { 
-      gProof->Exec("gSystem->Load(\"libTree.so\");");
-      gProof->Exec("gSystem->Load(\"libGeom.so\");");
-      gProof->Exec("gSystem->Load(\"libMinuit.so\");");
-      gProof->Exec("gSystem->Load(\"libVMC.so\");");
-
-      
+    AliAnalysisGrid* ag = am->GetGridHandler();
+    if (!ag) { 
+      Warning("GetOutputDirectory", "No grid handler defined yet");
+      return ret;
+    }
+    AliAnalysisAlien* aa = dynamic_cast<AliAnalysisAlien*>(ag);
+    if (!aa) { 
+      Warning("GetOutputDirectory", "Grid handler isn't for AliEn");
+      return ret;
+    }
+    ret = aa->GetGridOutputDir();
+    if (!ret.BeginsWith("/")) {
+      if (gGrid)
+       ret = Form("%s/%s/%s", gGrid->GetHomeDirectory(), 
+                  fEscapedName.Data(), aa->GetGridOutputDir());
+      else 
+       ret = Form("%s/%s", fEscapedName.Data(), aa->GetGridOutputDir());
     }
-
-    Bool_t ret   = true;
-    Bool_t basic = mode == kGrid ? false : par;
-    
-    ret &= LoadLibrary("STEERBase",     mode, basic, false);
-    ret &= LoadLibrary("ESD",           mode, basic, false);
-    ret &= LoadLibrary("AOD",           mode, basic, false);
-    ret &= LoadLibrary("ANALYSIS",      mode, basic, true);
-    ret &= LoadLibrary("OADB",          mode, basic, true);
-    ret &= LoadLibrary("ANALYSISalice", mode, basic, true);
-
     return ret;
   }
+  /* @} */
+
   //__________________________________________________________________
   /** 
-   * Load a library 
-   * 
-   * @param what What library to load
-   * @param mode Mode (local, proof, grid)
-   * @param par  If true, load as PAR
-   * @param rec  If true, also load on slaves
+   * @{ 
+   * @name Setup 
+   */
+  /** 
+   * Make our working directory if so requested 
    * 
-   * @return true on success 
+   * @return true on success
    */
-  Bool_t LoadLibrary(const char* what, EMode mode, Bool_t par, Bool_t rec=false)
+  Bool_t SetupWorkingDirectory()
   {
-    if (!what || what[0] == '\0') return true;
-    
-    TString module(what);
-    TString libName(what);
-    if (!libName.BeginsWith("lib")) libName = Form("lib%s", libName.Data());
-    if (!libName.EndsWith(".so"))   libName.Append(".so");
+    TString nam = EscapedName();
+    //Info("Init","Current dir=%s, escaped name=%s",cwd.Data(),nam.Data());
+    Bool_t exists = gSystem->AccessPathName(nam.Data()) == 0;
+    if (fExecOper == kTerminate && !exists) {
+      Error("SetupWorkingDirectory", "File/directory %s does not exists", 
+           nam.Data());
+      return false;
+    }
 
-    Int_t ret = 0;
+       
+    if (!fAllowOverwrite && exists) {
+      Error("SetupWorkingDirectory", "File/directory %s already exists", 
+           nam.Data());
+      return false;
+    }
 
-    switch (mode) { 
-    case kLocal: // Just load and exit 
-      gSystem->Load(libName.Data());
-      break;
-    case kGrid: 
-      if (par) { 
-       ret = SetupPAR(what) ? 0 : -1;
-       if (rec) fListOfPARs.Add(new TObjString(what));
-      } else  {
-       ret = gSystem->Load(libName.Data());
-       if (rec) fListOfLibraries.Add(new TObjString(libName));
-      }
-      break;
-    case kProof: 
-      Info("LoadLibrary", "Uploading %s", what);
-      ret = gProof->UploadPackage(what, TProof::kRemoveOld);
-      if (ret < 0)  {  
-         ret = gProof->UploadPackage(gSystem->ExpandPathName(Form("../%s.par",
-                                                                  what)));
-       if (ret < 0) {  
-         ret = 
-           gProof->UploadPackage(gSystem
-                                 ->ExpandPathName(Form("$ALICE_ROOT/%s.par", 
-                                                       what)));
-         if (ret < 0) {
-           Error("LoadLibrary", 
-                 "Could not find module %s.par in current directory nor "
-                 "in $ALICE_ROOT", module.Data());
-           return false;
-         }
-       }
+    if (!exists) {
+      if (gSystem->MakeDirectory(nam.Data())) {
+       Error("SetupWorkingDirectory", "Failed to make directory '%s'", 
+             nam.Data());
+       return false;
       }
-      Info("LoadLibrary", "Enabling package %s", what);
-      ret = gProof->EnablePackage(what);
-      break;
     }
-    if (ret < 0) { 
-      Error("LoadLibrary", "Couldn't load %s", what);
+      
+    if (!gSystem->ChangeDirectory(nam.Data())) { 
+      Error("SetupWorkingDirectory", "Failed to change directory to %s", 
+           nam.Data());
       return false;
     }
+    Info("SetupWorkingDirectory", "Made subdirectory %s, and cd'ed there", 
+        nam.Data());
     return true;
   }
-          
-  //__________________________________________________________________
+  //------------------------------------------------------------------
+  /** 
+   * Set-up a PAR file 
+   * 
+   * @param what PAR file 
+   * 
+   * @return true on success
+   */
   Bool_t SetupPAR(const char* what)
   {
     if (!what || what[0] == '\0') return -1;
@@ -1631,14 +1792,19 @@ protected:
     
     // Check for setup script
     if (!gSystem->AccessPathName("PROOF-INF/SETUP.C")) {
-      Info("SetupPAR", "Setting up for PAR %s", what);
+      // Info("SetupPAR", "Setting up for PAR %s", what);
       gROOT->Macro("PROOF-INF/SETUP.C");
     }
     if (!gSystem->ChangeDirectory(cwd.Data())) return false;
 
     return true;
   }
-  //__________________________________________________________________
+  //------------------------------------------------------------------
+  /** 
+   * Set-up extra sources. 
+   * 
+   * @return true on success
+   */
   TString SetupExtras()
   {
     TString ret;
@@ -1660,7 +1826,13 @@ protected:
     ret = ret.Strip();
     return ret;
   }
-  //__________________________________________________________________
+  //------------------------------------------------------------------
+  /** 
+   * Set-up sources for upload 
+   * 
+   * 
+   * @return String of sources 
+   */
   TString SetupSources()
   {
     TString nam = EscapedName();
@@ -1683,7 +1855,12 @@ protected:
     ret = ret.Strip();
     return ret;
   }
-  //__________________________________________________________________
+  //------------------------------------------------------------------
+  /** 
+   * Set-up extra libraries to upload 
+   * 
+   * @return String of libraries 
+   */
   TString SetupLibraries()
   {
     TString ret;
@@ -1698,26 +1875,31 @@ protected:
     ret = ret.Strip();
     return ret;
   }
+  /* @} */
+
   //__________________________________________________________________
+  /** 
+   * @{ 
+   * @name Chain building 
+   */
   /** 
    * Scan directory @a dir (possibly recursive) for tree files to add
    * to the chain.    This does not follow sym-links
    * 
    * @param dir        Directory to scan
    * @param chain      Chain to add to
-   * @param type       Type of tree (ESD or AOD)
    * @param recursive  Whether to scan recursively 
-   * @param mc         Look also for MC files if true 
    *
    * @return true if any files where added 
    */
   Bool_t ScanDirectory(TSystemDirectory* dir, TChain* chain, 
-                      EType type, bool recursive, bool mc)
+                      bool recursive)
   {
     TString fnPattern;
-    switch (type) { 
+    switch (fExecType) { 
     case kESD:  fnPattern = "AliESD"; break;
     case kAOD:  fnPattern = "AliAOD"; break;
+    case kUser: fnPattern = "";       break;
     }
 
     // Assume failure 
@@ -1734,9 +1916,9 @@ protected:
 
     TList toAdd;
     toAdd.SetOwner();
-    Bool_t hasGAlice = (!mc ? true : false);
-    Bool_t hasKine   = (!mc ? true : false);
-    Bool_t hasTrRef  = (!mc ? true : false);
+    Bool_t hasGAlice = (!fMC ? true : false);
+    Bool_t hasKine   = (!fMC ? true : false);
+    Bool_t hasTrRef  = (!fMC ? true : false);
     
     // Sort list of files and check if we should add it 
     files->Sort();
@@ -1765,7 +1947,7 @@ protected:
          // if (title[0] == '/') 
          TSystemDirectory* d = new TSystemDirectory(file->GetName(),
                                                     full.Data());
-          if (ScanDirectory(d,chain,type,recursive,mc))
+          if (ScanDirectory(d,chain,recursive))
            ret = true;
          delete d;
        }
@@ -1779,7 +1961,7 @@ protected:
       if (!name.Contains(fnPattern)) { 
        // Info("ScanDirectory", "%s does not match pattern %s", 
        //      name.Data(), fnPattern.Data());
-       if (mc) { 
+       if (fMC) { 
          if (name.CompareTo("galice.root") == 0)     hasGAlice = true;
          if (name.CompareTo("Kinematics.root") == 0) hasKine   = true;
          if (name.CompareTo("TrackRefs.root")  == 0) hasTrRef = true;
@@ -1792,7 +1974,7 @@ protected:
       toAdd.Add(new TObjString(full));
     }
 
-    if (mc && toAdd.GetEntries() > 0 && 
+    if (fMC && toAdd.GetEntries() > 0 && 
        (!hasGAlice || !hasKine || !hasTrRef)) { 
       Warning("ScanDirectory", 
              "one or more of {galice,Kinematics,TrackRefs}.root missing from "
@@ -1812,7 +1994,7 @@ protected:
     gSystem->ChangeDirectory(oldDir);
     return ret;
   }
-  //__________________________________________________________________
+  //------------------------------------------------------------------
   /** 
    * Create a chain from an XML containing an collection
    * 
@@ -1837,26 +2019,23 @@ protected:
     
     return chain;
   }
-  //__________________________________________________________________
+  //------------------------------------------------------------------
   /** 
    * Create a chain of data 
-   * 
-   * @param type Type of data
-   * @param mode Operation mode 
-   * @param mc   Assume MC input if true
    *
    * @return TChain of data 
    */    
-  TChain* CreateChain(EType type, EMode mode, EOper /* oper */, Bool_t mc)
+  TChain* CreateChain()
   {
     TString treeName;
-    switch (type) { 
+    switch (fExecType) { 
     case kESD:  treeName = "esdTree"; break;
     case kAOD:  treeName = "aodTree"; break;
+    case kUser: treeName = "";        break;
     }
 
     TChain* chain = 0;
-    switch (mode) { 
+    switch (fExecMode) { 
     case kProof: 
       if (!fDataSet.IsNull()) break; 
       // Otherwise fall through
@@ -1868,7 +2047,7 @@ protected:
        if (!dir.BeginsWith("/")) dir = Form("../%s", dir.Data());
        TString savdir(gSystem->WorkingDirectory());
        TSystemDirectory d(gSystem->BaseName(dir.Data()), dir.Data());
-       if (!ScanDirectory(&d, chain, type, true, mc)) { 
+       if (!ScanDirectory(&d, chain, true)) { 
          delete chain;
          chain = 0;
        }
@@ -1886,138 +2065,587 @@ protected:
     }
     return chain;
   }
-  //__________________________________________________________________
-  TString GetOutputDirectory(EMode mode) const 
+  /* @} */
+
+public:
+  //====================================================================
+  /**
+   * Option class 
+   * 
+   */
+  struct Option
   {
-    TString ret(fEscapedName);
-    if (mode != kGrid) return ret;
+    /** 
+     * Constructor 
+     * 
+     * @param name Option name
+     * @param desc Option description 
+     * @param arg  Option argument, if any
+     */
+    Option(const char* name, const char* desc, const char* arg="")
+      : fName(name),
+       fDesc(desc),
+       fArg(arg),
+       fIsSet(false),
+       fValue("")
+    {}
+    /** 
+     * Process an option string. 
+     * 
+     * @param opt String to process
+     * 
+     * @return true, if this handled the option, false otherwise
+     */
+    Bool_t Process(const TString& opt)
+    {
+      // Info("Option::Process", "Option %s processing %s",
+      //      fName.Data(), opt.Data());
+      if (!opt.BeginsWith(fName, TString::kIgnoreCase)) return false;
+
+      // We've got a value 
+      fIsSet = true;
     
-    AliAnalysisManager* am = AliAnalysisManager::GetAnalysisManager();
-    if (!am) { 
-      Warning("GetOutputDirectory", "No analysis manager defined yet");
-      return ret;
+      // No argument options shouldn't set a value 
+      if (fArg.IsNull()) return true;
+
+      // Parse out value 
+      Int_t eq = opt.Index("=");
+
+      // Empty string is an OK value 
+      if (eq == kNPOS) return true;
+
+      TString tmp = opt(eq+1,opt.Length()-eq-1);
+      fValue = tmp.Strip();
+    
+      return true;
     }
-    AliAnalysisGrid* ag = am->GetGridHandler();
-    if (!ag) { 
-      Warning("GetOutputDirectory", "No grid handler defined yet");
-      return ret;
+    /** 
+     * Get option value as a string 
+     * 
+     * @return Option value
+     */
+    const TString& AsString() const { return fValue; } 
+    /** 
+     * Get option value as a double
+     * 
+     * @return Option value
+     */
+    Double_t AsDouble() const { return fValue.Atof(); }
+    /** 
+     * Get option value as an integer 
+     * 
+     * @return Option value
+     */
+    Int_t AsInt() const { return fValue.Atoi(); } 
+    /** 
+     * Get option value as a boolean
+     * 
+     * @return Option value
+     */
+    Bool_t   AsBool() const { return fIsSet; }
+    /** 
+     * Test if the option has been set.
+     * 
+     * @return True if the option was given
+     */
+    Bool_t   IsSet() const { return fIsSet; }
+    /** 
+     * Print help. 
+     * 
+     * @param o Stream to write on
+     * @param prefix Prefix
+     */
+    void PrintHelp(std::ostream& o, const char* prefix) const 
+    {
+      TString arg(fName);
+      if (!fArg.IsNull()) arg.Append(Form("=%s", fArg.Data()));
+      o << "  " << (prefix ? prefix : "") 
+       << std::left << std::setw(30) << arg 
+       << " " << fDesc << std::endl;
     }
-    AliAnalysisAlien* aa = dynamic_cast<AliAnalysisAlien*>(ag);
-    if (!aa) { 
-      Warning("GetOutputDirectory", "Grid handler isn't for AliEn");
-      return ret;
+    /** 
+     * Print the setting 
+     * 
+     * @param o Stream to write on
+     */
+    void PrintSettings(std::ostream& o) const 
+    {
+      o << "  " << std::left << std::setw(30) << fName << ": ";
+      if (fArg.IsNull()) o << (IsSet() ? "true" : "false");
+      else               o << fValue;
+      o << std::endl;
     }
-    ret = aa->GetGridOutputDir();
-    if (!ret.BeginsWith("/")) {
-      if (gGrid)
-       ret = Form("%s/%s/%s", gGrid->GetHomeDirectory(), 
-                  fEscapedName.Data(), aa->GetGridOutputDir());
-      else 
-       ret = Form("%s/%s", fEscapedName.Data(), aa->GetGridOutputDir());
+    /** 
+     * Save the setting 
+     * 
+     * @param str  object nmae 
+     * @param val  Value
+     * @param o Stream to write on
+     */
+    void Save(std::ostream& o, const char* str, bool val)
+    {
+      if (!val) return;
+      if (str[0] == '-') {
+       o << "  " << str << fName << " \\" << std::endl;
+       return;
+      }
+      o << "  " << str << ".Append(\"" << fName <<  ",\");" << std::endl;
     }
-    return ret;
-  }
-      
-  //__________________________________________________________________
-  virtual void WriteConstruction(std::ostream& o, const char* obj) const
+    /** 
+     * Save the setting 
+     * 
+     * @param str  object nmae 
+     * @param val  Value
+     * @param o Stream to write on
+     */
+    void Save(std::ostream& o, const char* str, Int_t val)
+    {
+      if (str[0] == '-') { 
+       o << "  " << str << fName << "=" << val << " \\" << std::endl;
+       return;
+      }
+      o << "  " << str << ".Append(\"" << fName <<  "=" << val 
+       << ",\");" << std::endl;
+    }
+    /** 
+     * Save the setting 
+     * 
+     * @param str  object nmae 
+     * @param val  Value
+     * @param o Stream to write on
+     */
+    void Save(std::ostream& o, const char* str, Double_t val)
+    {
+      if (str[0] == '-') { 
+       o << "  " << str << fName << "=" << val << "  \\" << std::endl;
+       return;
+      }
+      o << "  " << str << ".Append(\"" << fName <<  "=" << val 
+       << ",\");" << std::endl;
+    }
+    /** 
+     * Save the setting 
+     * 
+     * @param str  object nmae 
+     * @param val  Value
+     * @param o Stream to write on
+     */
+    void Save(std::ostream& o, const char* str, const char* val)
+    {
+      if (str[0] == '-') { 
+       TString sval(val);
+       sval.ReplaceAll(" ", "\\ ");
+       o << "  " << str << fName << "=" << sval << " \\" << std::endl;
+       return;
+      }
+      o << "  " << str << ".Append(\"" << fName <<  "=" << val 
+       << ",\");" << std::endl;
+    }
+
+    TString fName;  // Name of the option 
+    TString fDesc;  // Decription 
+    TString fArg;   // Argument, if any
+    Bool_t  fIsSet; // Whether the option has been set.
+    TString fValue; // Value of the option. 
+  };
+  //====================================================================
+  /**
+   * Run a train setup
+   * 
+   */
+  struct Runner 
   {
-    o << "  " << ClassName() << " " 
-      << obj << "(\"" << fName << "\");" << std::endl;
-  }
+    /** 
+     * Constructor 
+     * 
+     * @param train Train to run 
+     * @param max   Maximum number of options
+     */
+    Runner(TrainSetup& train, UShort_t max=30)
+      : fTrain(&train), fOptions(0), fN(0), fMax(max)
+    {
+      fOptions = new Option*[fMax];
+      for (Int_t i = 0; i < fMax; i++) fOptions[i] = 0;
+    }
+    /** 
+     * Add an option 
+     * 
+     * @param opt Option to add 
+     */
+    void Add(Option* opt)
+    {
+      if (fN >= fMax) {
+       Warning("AddOption", "No room for option %s", opt->fName.Data());
+       return;
+      }
+      fOptions[fN++] = opt;
+    }
+    /** 
+     * Remove an option
+     * 
+     * @param name 
+     */
+    void Remove(const TString& name)
+    {
+      Option** ptr = fOptions;
+      Option** tmp = 0;
+      while (*ptr) { 
+       if (name.EqualTo((*ptr)->fName)) {
+         tmp = ptr;
+         break;
+       }
+       ptr++;
+      }
+      if (!tmp) // nothing found, returning 
+       return;
+      
+      ptr = tmp;
+      delete *tmp;
+      tmp++;
+      fN--;
+      while (*tmp) { 
+       *ptr = *tmp;
+       ptr++;
+       tmp++;
+      }
+      *ptr = 0;
+    }
+
+    /** 
+     * Parse option string 
+     * 
+     * @param options Option string. 
+     * @param delim   Delimiters 
+     * 
+     * @return true on success. 
+     */
+    Bool_t Parse(const TString& options, const char* delim=",;")
+    {
+      TObjArray* a = options.Tokenize(delim);
+      return Parse(*a);
+    }
+    /** 
+     * Parse options 
+     * 
+     * @param options 
+     * 
+     * @return true on success
+     */
+    Bool_t Parse(TObjArray& options) 
+    {
+      TIter next(&options);
+      TObjString* os = 0;
+      while ((os = static_cast<TObjString*>(next()))) {
+       TString s(os->String());
+       // Info("Runner::Parse", "Processing option %s", s.Data());
+       if (s.IsNull()) continue;
+
+       Bool_t   ok  = false;
+       Option** ptr = fOptions;
+       while (*ptr && !ok) { 
+         Option* o = *ptr;
+         if (o->Process(s)) ok = true;
+         ptr++;
+       }
+       
+       if (!ok) 
+         Warning("Parse", "Unknown option %s", s.Data());
+      }
+      return true;
+    }
+    /** 
+     * Check if we asked for help 
+     * 
+     * 
+     * @return 
+     */
+    Bool_t IsHelpAsked() const 
+    {
+      Option* help = FindOption("help");
+      return (help && help->IsSet());
+    }
+    /** 
+     * Print help
+     * 
+     * @param out Stream to write on  
+     * @param prefix Prefix
+     */
+    void PrintHelp(std::ostream& out, const char* prefix="") const
+    {
+      Option** ptr = fOptions;
+      while (*ptr) { 
+       (*ptr)->PrintHelp(out, prefix);
+       ptr++;
+      }
+    }
+    /** 
+     * Print the settings 
+     * 
+     * @param out Stream to write on. 
+     */
+    void PrintSettings(std::ostream& out) const
+    {
+      Option** ptr = fOptions;
+      while (*ptr) { 
+       (*ptr)->PrintSettings(out);
+       ptr++;
+      }
+    }
+    /** 
+     * Find an option by name 
+     * 
+     * @param name Name of option to find
+     * 
+     * @return Pointer to option, or null
+     */
+    Option* FindOption(const TString& name) const
+    {
+      Option** ptr = fOptions;
+      while (*ptr) { 
+       if (name.EqualTo((*ptr)->fName)) return *ptr;
+       ptr++;
+      }
+      return 0;
+    }
+    /** 
+     * Initialize the train
+     * 
+     * @param options  Execution options 
+     * 
+     * @return true on success
+     */
+    Bool_t Init(const TString& options)
+    {
+      fTrain->MakeOptions(*this);
+      if (!Parse(options)) return false;
+      return true;
+    }
+    /** 
+     * Run the train
+     * 
+     * @param runs     Run numbers 
+     * @param nEvents  Number of events
+     * @param asShell  Save set-up as shell script 
+     * 
+     * @return 
+     */
+    Bool_t Run(const TString& runs, Int_t nEvents, Bool_t asShell=false)
+    {
+      PrintSettings(std::cout);
+
+      fTrain->SetOptions(*this);
+      fTrain->SetRuns(runs);
+      // fTrain->SaveSetup(*this, nEvents, asShell);
+      
+      fTrain->Run(nEvents, this, asShell);
+      return true;
+    }
+      
+    TrainSetup* fTrain;
+    Option** fOptions;  // Our options 
+    UShort_t fN;        // Current number of options 
+    UShort_t fMax;      // Maximum number of options
+  };
+protected:
   //__________________________________________________________________
-  virtual void WriteSettings(std::ostream& o, const char* obj) const
+  /** 
+   * @{ 
+   * @name Options 
+   */
+  /** 
+   * Class name of this train setup.  Sub-classes must define this. 
+   * 
+   * @return Class name of this setup 
+   */
+  virtual const char* ClassName() const = 0;
+  //------------------------------------------------------------------
+  /** 
+   * Make the options for this train.  Sub-classes can overload this
+   * to define new options, or append to the set of default option.
+   */    
+  virtual void MakeOptions(Runner& r)
   {
-    o << "  " << obj << ".SetDateTime(" << fDatime.GetYear() << ',' 
-      << fDatime.GetMonth() << ',' 
-      << fDatime.GetDay() << ',' 
-      << fDatime.GetHour() << ',' 
-      << fDatime.GetMinute() << ");\n"
-      << "  " << obj << ".SetROOTVersion(\"" << fRootVersion << "\");\n"
-      << "  " << obj << ".SetAliROOTVersion(\"" << fAliRootVersion << "\");\n"
-      << "  " << obj << ".SetAliEnAPIVersion(\"" << fAliEnAPIVersion << "\");\n"
-      << "  " << obj << ".SetProofServer(\"" << fProofServer << "\");\n"
-      << "  " << obj << ".SetDataDir(\"" << fDataDir << "\");\n"
-      << "  " << obj << ".SetDataSet(\"" << fDataSet << "\");\n"
-      << "  " << obj << ".SetXML(\"" << fXML << "\");\n"
-      << "  " << obj << ".SetNReplica(" << fNReplica << ");\n"
-      << "  " << obj << ".SetESDPass(" << fESDPass << ");\n"
-      << "  " << obj << ".SetPassPostfix(\"" << fPassPostfix << "\");\n"
-      << "  " << obj << ".SetAllowOverwrite(" << fAllowOverwrite << ");\n"
-      << "  " << obj << ".SetUseGDB(" << fUseGDB << ");\n"
-      << "  " << obj << ".SetMaxSplit(" << fMaxSplit << ");\n"
-      << std::endl;
+    r.Add(new Option("help",   "Show this help"));
+    r.Add(new Option("par",    "Use PAR files (PROOF and Grid)"));
+    r.Add(new Option("mc",     "Assume simulation input"));
+    r.Add(new Option("debug",  "Execute in debugger"));
+    r.Add(new Option("type",   "Type of train",    "AOD|ESD"));
+    r.Add(new Option("mode",   "Execution mode",   "LOCAL|PROOF|GRID"));
+    r.Add(new Option("oper",   "Operation mode",   "TEST|TERMINATE|FULL|INIT"));
+    r.Add(new Option("date",   "Set date string",  "YYYY-MM-DD HH:MM:SS"));
+    r.Add(new Option("cluster","PROOF cluster",         "HOST"));
+    r.Add(new Option("dataSet","Data set (PROOF only)", "NAME"));
+    r.Add(new Option("dataDir","Data directory",        "DIRECTORY"));
+    r.Add(new Option("pattern","Data pattern (grid only)", "GLOB")); 
+    r.Add(new Option("verb",   "Verbosity",             "NUMBER")); 
+    r.Add(new Option("root",   "ROOT version (Grid)",   "TAG")); 
+    r.Add(new Option("aliroot","AliROOT version (Grid)","TAG")); 
+    r.Add(new Option("alien",  "AliEn API version (Grid)","TAG")); 
+    r.Add(new Option("overwrite", "Allow overwrite"));
+    r.Add(new Option("per-run", "Per run merge"));
   } 
-  //__________________________________________________________________
-  virtual void WriteRun(std::ostream& o, 
-                       const char* obj, 
-                       const char* type, 
-                       const char* mode, 
-                       const char* oper, 
-                       Bool_t      mc, 
-                       Bool_t      usePar, 
-                       Int_t       dbg) const
+  //------------------------------------------------------------------
+  /** 
+   * Set the option values on the train.  Sub-classes can overload 
+   * this to set custom options on the train. 
+   */
+  virtual void SetOptions(Runner& r)
   {
-    o << "  " << obj << ".Run(" << type << "," << mode 
-      << "," << oper << "," << mc << "," << usePar << "," 
-      << dbg << ");" << std::endl;
+    Option* debug      = r.FindOption("debug");
+    Option* date       = r.FindOption("date");
+    Option* cluster    = r.FindOption("cluster");
+    Option* dataSet    = r.FindOption("dataSet");
+    Option* dataDir    = r.FindOption("dataDir");
+    Option* pattern    = r.FindOption("pattern");
+    Option* par         = r.FindOption("par");
+    Option* type        = r.FindOption("type");
+    Option* mode        = r.FindOption("mode");
+    Option* oper        = r.FindOption("oper");
+    Option* mc          = r.FindOption("mc");
+    Option* verb        = r.FindOption("verb");
+    Option* root        = r.FindOption("root");
+    Option* aliroot     = r.FindOption("aliroot");
+    Option* alien       = r.FindOption("alien");
+    Option* overwrite   = r.FindOption("overwrite");
+    Option* run_merge   = r.FindOption("per-run");
+    
+    if (date && date->IsSet()) SetDateTime(date->AsString());
+    if (cluster)               SetProofServer(cluster->AsString());
+    if (dataSet)               SetDataSet(dataSet->AsString());
+    if (dataDir)               SetDataDir(dataDir->AsString());
+    if (pattern)               SetDataPattern(pattern->AsString());
+    if (debug)                 SetUseGDB(debug->AsBool());
+    if (type && type->IsSet()) SetType(type->AsString());
+    if (mode && mode->IsSet()) SetMode(mode->AsString());
+    if (oper && oper->IsSet()) SetOperation(oper->AsString());
+    if (par)                   SetUsePar(par->AsBool());
+    if (mc)                    SetMC(mc->AsBool());
+    if (verb)                  SetVerbose(verb->AsInt());
+    if (root)                  SetROOTVersion(root->AsString());
+    if (aliroot)               SetAliROOTVersion(aliroot->AsString());
+    if (alien)                 SetAliEnAPIVersion(alien->AsString());
+    if (overwrite)             SetAllowOverwrite(overwrite->AsBool());
+    if (run_merge)             SetPerRunMerge(run_merge->AsBool());
   }
-  //__________________________________________________________________
-  virtual const char* ClassName() const
+  //------------------------------------------------------------------
+  /** 
+   * Set the option values on the train.  Sub-classes can overload 
+   * this to set custom options on the train. 
+   */
+  virtual void SaveOptions(std::ostream& o, const char* str, Runner& r)
   {
-    return "TrainSetup";
+    Option* debug      = r.FindOption("debug");
+    Option* date       = r.FindOption("date");
+    Option* cluster    = r.FindOption("cluster");
+    Option* dataSet    = r.FindOption("dataSet");
+    Option* dataDir    = r.FindOption("dataDir");
+    Option* pattern    = r.FindOption("pattern");
+    Option* par         = r.FindOption("par");
+    Option* type        = r.FindOption("type");
+    Option* mode        = r.FindOption("mode");
+    Option* oper        = r.FindOption("oper");
+    Option* mc          = r.FindOption("mc");
+    Option* verb        = r.FindOption("verb");
+    Option* root        = r.FindOption("root");
+    Option* aliroot     = r.FindOption("aliroot");
+    Option* alien       = r.FindOption("alien");
+    Option* overwrite   = r.FindOption("overwrite");
+    Option* run_merge   = r.FindOption("per-run");
+    
+    if (date) date->Save(o, str, 
+                        Form("%04d-%02d-%02d %02d:%02d:00",
+                             fDatime.GetYear(), 
+                             fDatime.GetMonth(), 
+                             fDatime.GetDay(), 
+                             fDatime.GetHour(),
+                             fDatime.GetMinute()));
+    if (cluster)  cluster->Save(o, str, fProofServer);
+    if (dataSet)  dataSet->Save(o, str, fDataSet);
+    if (dataDir)  dataDir->Save(o, str, fDataDir);
+    if (pattern)  pattern->Save(o, str, fDataPattern);
+    if (debug)    debug->Save(o, str, fUseGDB);
+    if (type)     type->Save(o, str, TypeString(fExecType));
+    if (mode)     mode->Save(o, str, ModeString(fExecMode));
+    if (oper)     oper->Save(o, str, OperString(fExecOper));
+    if (par)      par->Save(o, str, fUsePar);
+    if (mc)       mc->Save(o, str, fMC);
+    if (verb)     verb->Save(o, str, fVerbose);
+    if (root)     root->Save(o, str, fRootVersion);
+    if (aliroot)  aliroot->Save(o, str, fAliRootVersion);
+    if (alien)    alien->Save(o, str, fAliEnAPIVersion);
+    if (overwrite)overwrite->Save(o, str, fAllowOverwrite);
+    if (run_merge)run_merge->Save(o, str, fPerRunMerge);
   }
-  //__________________________________________________________________
-  virtual void WriteBuild(std::ostream& o, const char* cls) const
+  /** 
+   * Save the setup to file for later re-execution 
+   * 
+   * @param r         Runner object 
+   * @param nEvents   Number of events 
+   * @param asShell   If true, save as shell script - otherwise ROOT script
+   */
+  virtual void SaveSetup(Runner& r, Int_t nEvents, Bool_t asShell=false)
   {
-    o << "  const char* builder = \n"
-      << "    \"$(ALICE_ROOT)/PWGLF/FORWARD/analysis2/trains/BuildTrain.C\";\n"
-      << "  gROOT->LoadMacro(builder);\n"
-      << "  BuildTrain(\"" << cls << "\");\n" << std::endl;
+    if (asShell) SaveSetupShell(r, nEvents); 
+    /* else */   SaveSetupROOT(r, nEvents);
   }
-  //__________________________________________________________________
-  virtual void WriteRuns(std::ostream& o, const char* obj) const
+  /** 
+   * Save the setup to shell script for later re-execution 
+   * 
+   * @param r         Runner object 
+   * @param nEvents   Number of events 
+   */
+  virtual void SaveSetupShell(Runner& r, Int_t nEvents)
   {
+    std::ofstream o("rerun.sh");
+    o << "#!/bin/bash\n\n"
+      << "oper=$1\n"
+      << "if test x$oper = x ; then oper=full ; fi \n\n"
+      << "class=\"" << ClassName() << "\"\n"
+      << "name=\"" << fName << "\"\n"
+      << "nev=" << nEvents << "\n\n"
+      << "opts=(--class=$class \\\n"
+      << "  --name=$name \\\n"
+      << "  --events=$nev \\" << std::endl;
     for (Int_t i = 0; i < fRunNumbers.GetSize(); i++) 
-      o << "  " << obj << ".AddRun(" << fRunNumbers.At(i) << ");\n";
-    o << std::endl;
+      o << "  --run=" << fRunNumbers.At(i) << " \\\n";
+    SaveOptions(o, "--", r);
+    o << "  --oper=$oper)\n\n"
+      << "echo \"Running runTrain ${opts[@]}\"\n"
+      << "runTrain \"${opts[@]}\"\n\n"
+      << "#EOF\n" 
+      << std::endl;
+    o.close();
+    gSystem->Exec("chmod a+x rerun.sh");
   }
-  //__________________________________________________________________
-  virtual void CreateSetupScript(EType  type, 
-                                EMode  mode, 
-                                Bool_t mc, 
-                                Bool_t usePar, 
-                                Int_t  dbg) const
+  /** 
+   * Save the setup to shell script for later re-execution 
+   * 
+   * @param r         Runner object 
+   * @param nEvents   Number of events 
+   */
+  virtual void SaveSetupROOT(Runner& r, Int_t nEvents) 
   {
-    std::ofstream o(Form("setup_%s.C", fEscapedName.Data()));
-    if (!o) { 
-      Error("CreateSetupScript", "Failed to generate setup_%s.C", 
-           fEscapedName.Data());
-      return;
-    }
-    const char* cls = ClassName();
-    o << std::boolalpha 
-      << "// Script to set-up the analysis chain\n"
-      << "// Automatically generated by TrainSetup\n"
-      << "// Run with argument to true, to do Terminate processing\n"
-      << "void setup_" << fEscapedName << "(bool terminate)\n"
-      << "{\n";
-    WriteBuild(o, cls);
-    WriteConstruction(o, "t");
-    WriteSettings(o, "t");
-    WriteRuns(o, "t");
-
-    const char* ctype = (type == kESD ? "\"ESD\"" : "\"AOD\"");
-    const char* cmode = (mode == kLocal ? "\"LOCAL\"" : 
-                        mode == kProof ? "\"PROOF\"" : "\"GRID\"");
-    WriteRun(o, "t", ctype, cmode, "(terminate ? \"TERMINATE\" : \"FULL\")",
-            mc, usePar, dbg);
-            
-    
-    o << "\n}\n// EOF\n" << std::endl;
-       
-    
+    std::ofstream o("rerun.C");
+    o << "void rerun(bool terminate=false)\n"
+      << "{\n" 
+      << "  TString opts;" << std::endl;
+    SaveOptions(o, "opts", r);
+      
+    o << "  if (terminate) opts.Append(\"mode=terminate;\");\n\n"
+      << "  TString runs(\"";
+    for (Int_t i = 0; i < fRunNumbers.GetSize(); i++) 
+      o << (i == 0 ? "" : ", ") << fRunNumbers.At(i);
+    o << "\");\n\n"
+      << "  Int_t   nEvents = " << nEvents << ";\n\n"
+      << "  gROOT->LoadMacro(\"$ALICE_ROOT/PWGLF/FORWARD/analysis2/trains/RunTrain.C\");\n"
+      << "  RunTrain(\"" << ClassName() << "\",\"" 
+      << fName << "\",opts,runs,nEvents);\n"
+      << "}\n"
+      << "// EOF" << std::endl;
     o.close();
   }
+  /* @} */
+
   //__________________________________________________________________
   TString fName;             // Name of analysis
   TString fEscapedName;      // Name escaped for special chars
@@ -2026,11 +2654,10 @@ protected:
   TString fAliEnAPIVersion;  // AliEn API version to use 
   TString fProofServer;      // Name of proof server
   TString fDataDir;          // Grid Input directory 
+  TString fDataPattern;      // Data directory pattern
   TString fDataSet;          // Proof data set name 
   TString fXML;              // XML collection for local/proof mode
   Int_t   fNReplica;         // Storage replication
-  Int_t   fESDPass;          // ESD pass number 
-  TString fPassPostfix;      // Possible pass postfix
   Bool_t  fAllowOverwrite;   // Allow overwriting output dir
   Bool_t  fUseGDB;           // Wrap PROOF slaves in GDB 
   Int_t   fMaxSplit;         // Maximum number of files per split
@@ -2039,9 +2666,15 @@ protected:
   TList   fListOfSources;    // List of sources to upload and AcLIC
   TList   fListOfLibraries;  // List of libraries to load
   TList   fListOfExtras;     // List of extra files to upload
-  TDatime fDatime;
+  TDatime fDatime;           // Date and time 
+  EType   fExecType;         // Execution type (ESD, AOD)
+  EMode   fExecMode;         // Execution mode (PROOF, local, Grid)
+  EOper   fExecOper;         // Execution operation (full, terminate, ...)
+  Bool_t  fUsePar;           // Wether to use PAR files 
+  Bool_t  fMC;               // Whether to assume MC input 
+  Bool_t  fPerRunMerge;      // Whether to merge per run or over-all
+  Int_t   fVerbose;          // Verbosity level 
 };
-
   
 //____________________________________________________________________
 //
diff --git a/PWGLF/FORWARD/analysis2/trains/runMain.cxx b/PWGLF/FORWARD/analysis2/trains/runMain.cxx
new file mode 100644 (file)
index 0000000..0f5d468
--- /dev/null
@@ -0,0 +1,332 @@
+/**
+ * @file   runMain.cxx
+ * @author Christian Holm Christensen <cholm@master.hehi.nbi.dk>
+ * @date   Fri Jun  1 13:56:29 2012
+ * 
+ * @brief  
+ * 
+ * @ingroup pwglf_forward_trains
+ * 
+ */
+/** 
+ * @defgroup pwglf_forward_trains_run Execute train
+ *
+ * Code for program to run trains 
+ *
+ * @ingroup pwglf_forward_trains
+ */
+#include "FORWARD/analysis2/trains/TrainSetup.C"
+#include <TSystem.h>
+#include <TROOT.h>
+#include <TString.h>
+
+/** 
+ * Build the train setup script 
+ * 
+ * @param script Script name 
+ * @param useTmp Whether to use temporary directory
+ * @param useDbg Build class with debug symbols
+ * 
+ * @return true on success
+ * 
+ * @ingroup pwglf_forward_trains_run
+ */
+Bool_t BuildTrain(const char* script, 
+                 Bool_t useTmp=false,
+                 Bool_t useDbg=false)
+{
+  // --- Load needed libraries ---------------------------------------
+  gROOT->LoadClass("TAlien",               "libRAliEn");
+  gROOT->LoadClass("TVirtualMC",           "libVMC");
+  gROOT->LoadClass("AliVEvent",            "libSTEERBase");
+  gROOT->LoadClass("AliESDEvent",          "libESD");
+  gROOT->LoadClass("AliAODEvent",          "libAOD");
+  gROOT->LoadClass("AliAnalysisManager",   "libANALYSIS");
+  gROOT->LoadClass("AliAnalysisTaskSE",    "libANALYSISalice");
+
+  // --- Setup script path -------------------------------------------
+  const char* aliPath   = gSystem->ExpandPathName("$ALICE_ROOT");
+  const char* fwd2Path  = 
+    gSystem->ExpandPathName("$ALICE_ROOT/PWGLF/FORWARD/analysis2");
+  const char* macroPath = gROOT->GetMacroPath();
+  gROOT->SetMacroPath(Form(".:%s:%s/trains:%s/scripts",
+                          macroPath,fwd2Path,fwd2Path));
+  
+  // --- Setup include path ------------------------------------------
+  gSystem->AddIncludePath(Form("-I%s", fwd2Path));
+  gSystem->AddIncludePath(Form("-I%s/trains", fwd2Path));
+  gSystem->AddIncludePath(Form("-I%s", aliPath));
+  gSystem->AddIncludePath(Form("-I%s/include", aliPath));
+
+  // --- Check that we can find the script ---------------------------
+  TString path = gSystem->Which(gROOT->GetMacroPath(), script);
+  if (path.IsNull()) { 
+    path = gSystem->Which(gROOT->GetMacroPath(), Form("%s.C", script));
+    if (path.IsNull()) { 
+      Error("BuildTrain", "Cannot find script %s or %s.C in %s", 
+           script, script, gROOT->GetMacroPath());
+      return false;
+    }
+  }
+  // --- Possibly make a temporary copy ------------------------------
+  if (useTmp) { 
+    TString tmp("Train");
+    FILE*   fp = gSystem->TempFileName(tmp, ".");
+    fclose(fp);
+    gSystem->Unlink(tmp);
+    tmp.Append(".C");
+    
+    gSystem->CopyFile(path, tmp);
+    path = tmp;
+  }
+
+  // --- Now compile the thing ---------------------------------------
+  // Info("BuildTrain", "Building macro %s (ACLiC mode: +%s)", path.Data(),
+  //      useDbg ? "+g" : "");
+  Int_t ret = gROOT->LoadMacro(Form("%s+%s", path.Data(), useDbg ? "+g" : ""));
+
+  // --- If we did a temporary file, remove stuff --------------------
+  if (useTmp) {
+    gSystem->Unlink(path);
+    path.ReplaceAll(".C",   "_C.d");  gSystem->Unlink(path);
+    path.ReplaceAll("_C.d", "_C.so"); gSystem->Unlink(path);
+  }
+
+  // --- Warning in case of problems ---------------------------------
+  if (ret != 0) 
+    Warning("BuildTrain", "Failed to build %s (%s)", path.Data(), script);
+
+  return ret == 0;  
+}
+/** 
+ * Make the train setup object 
+ * 
+ * @param trainClass Class-name of the train setup 
+ * @param trainName  Name of the train. 
+ * 
+ * @return Newly allocated object or null
+ * 
+ * @ingroup pwglf_forward_trains_run
+ */
+TrainSetup* MakeTrain(const char* trainClass, const char* trainName)
+{
+  // Info("MakeTrain", "Making an object of class %s named '%s'", 
+  //      trainClass, trainName);
+  Long_t ret = gROOT->ProcessLine(Form("new %s(\"%s\")",trainClass,trainName));
+  if (!ret) 
+    Warning("MakeTrain", "Failed to make object of class %s", trainClass);
+
+  return reinterpret_cast<TrainSetup*>(ret);
+}
+
+/** 
+ * Append an element to a list 
+ * 
+ * @param str String to append to 
+ * @param val Value to append
+ * @param sep Separator
+ * 
+ * @ingroup pwglf_forward_trains_run
+ */
+void AppendTo(TString& str, const TString& val, const char* sep=",")
+{
+  if (!str.IsNull()) str.Append(sep);
+  // Info("", "Appending %s to %s", val.Data(), str.Data());
+  str.Append(val);
+}
+/** 
+ * Append directory to header and script search path
+ * 
+ * @param dir Directory
+ * 
+ * @ingroup pwglf_forward_trains_run
+ */
+void AppendPath(const char* dir)
+{
+  gROOT->SetMacroPath(Form("%s:%s",gROOT->GetMacroPath(), dir));
+  gSystem->AddIncludePath(Form("-I%s", dir));
+}
+/** 
+ * Print a fake option description.  Used for options specific to this
+ * program.
+ * 
+ * @param o    Output stream 
+ * @param opt  Option (including meta argument)
+ * @param desc Option description.
+ * 
+ * @ingroup pwglf_forward_trains_run
+ */
+void PrintFakeOption(std::ostream& o, const char* opt, const char* desc)
+{
+  o << "  --" << std::left << std::setw(30) << opt << " " << desc << std::endl;
+}
+
+/** 
+ * Print usage information 
+ * 
+ * @param progname Program name 
+ * @param o        Output stream
+ * @param r        Optional runner. 
+ * 
+ * @ingroup pwglf_forward_trains_run
+ */
+void Usage(const char* progname, std::ostream& o, TrainSetup::Runner* r)
+{
+  o << "Usage: " << progname << " --class=CLASS --name=NAME [OPTIONS]\n\n"
+    << "PROGRAM OPTIONS:\n";
+  PrintFakeOption(o, "class=CLASS", "Train class");
+  PrintFakeOption(o, "name=NAME",   "Name of train");
+  PrintFakeOption(o, "events=NUMBER", "Max number of events to analyse");
+  PrintFakeOption(o, "run=RUN",       "Comma separated list of runs");
+  PrintFakeOption(o, "tmp",           "Copy code to temporary directory");
+  PrintFakeOption(o, "debug",         "Create debugging symbols");
+  PrintFakeOption(o, "include=DIRECTORY", "Append dir to macro/header path");
+  if (!r) { 
+    o << "\n"
+      << "Additional options may be defined by the specific train setup\n"
+      << std::endl;
+    return;
+  }
+  o << "\nTRAIN OPTIONS:" << std::endl;
+  r->PrintHelp(o, "--");
+  o << "\n"
+    << "The options --run and --include may be passed multiple times\n"
+    << "Options --debug and --tmp toggle, so pass only once\n"
+    << "For any other option, the last value passed is used\n"
+    << std::endl;
+}    
+
+/** 
+ * Run a given analysis train 
+ * 
+ * @verbatim
+Usage: runTrain --class=CLASS --name=NAME [OPTIONS]
+
+OPTIONS:
+  --class=CLASS                    Train class
+  --name=NAME                      Name of train
+  --run=RUN                        Comma separated list of runs
+  --tmp                            Copy class script to temporary directory
+  --help                           Show this help
+  --par                            Use PAR files (PROOF and Grid)
+  --mc                             Assume simulation input
+  --debug                          Execute in debugger
+  --type=AOD|ESD                   Type of train
+  --mode=LOCAL|PROOF|GRID          Execution mode
+  --oper=TEST|TERMINATE|FULL|INIT  Operation mode
+  --date=YYYY-MM-DD HH:MM:SS       Set date string
+  --cluster=HOST                   PROOF cluster
+  --dataSet=NAME                   Data set (PROOF only)
+  --dataDir=DIRECTORY              Data directory
+  --pass=NUMBER                    ESD Pass (grid only)
+  --verb=NUMBER                    Verbosity
+  --root=TAG                       ROOT version (Grid)
+  --aliroot=TAG                    AliROOT version (Grid)
+  --alien=TAG                      AliEn API version (Grid)
+  --overwrite                      Allow overwrite
+  --include=DIRECTORY              Append dir to macro/header path
+  @endverbatim
+ * 
+ * Individual classes derived from TrainSetup may define additional
+ * (or less) options.  Pass the option @b --help to see the list of
+ * available options
+ *
+ * Usually, the train defines the execution mode (ESD or AOD) and the
+ * option @b --type should not be given
+ *
+ * If a date is set (option @b --date) either to a string of the form 
+ * @c YYYY-MM-DD HH:MM:SS or to the string @c now, then the date will be 
+ * appended to the job name. 
+ * 
+ * A sub-directory named according to the name passed will be made,
+ * and relevant files will copied there.
+ * 
+ * @param argc Count of command line arguments, including program name
+ * @param argv Vector of command line arguments, including program name
+ *  
+ * @return 0 on success, 1 otherwise 
+ * 
+ * @ingroup pwglf_forward_trains_run
+ */
+int main(int argc, char** argv)
+{
+  TString trainOpts;
+  TString trainClass;
+  TString trainName; 
+  TString trainRuns; 
+  Int_t   trainEvents = -1;
+  Bool_t  trainTmp = false;
+  Bool_t  trainDbg = false;
+  Bool_t  progHelp = false;
+
+  for (int i = 1; i < argc; i++) { 
+    // std::cout << "Arg # " << i << ": \"" << argv[i] << "\"" << std::endl;
+    if (argv[i][0] == '-') { 
+      if (argv[i][1] == '-') { // Long options 
+       TString arg(argv[i]);
+       arg.ReplaceAll("\"'", "");
+       Int_t   eq = arg.Index("=");
+       TString val;
+       if (eq != kNPOS) val = arg(eq+1,arg.Length()-eq-1);
+       if      (arg.BeginsWith("--class"))   trainClass  = val;
+       else if (arg.BeginsWith("--name"))    trainName   = val;
+       else if (arg.BeginsWith("--events"))  trainEvents = val.Atoi();
+       else if (arg.BeginsWith("--run"))     AppendTo(trainRuns, val);
+       else if (arg.BeginsWith("--tmp"))     trainTmp = !trainTmp;
+       else if (arg.BeginsWith("--debug"))   trainDbg = !trainDbg;
+       else if (arg.BeginsWith("--include")) AppendPath(val);
+       else if (arg.BeginsWith("--help"))    progHelp=true; 
+       else    AppendTo(trainOpts, arg(2,arg.Length()-2)); 
+      }
+      else {
+       switch (argv[i][1]) { 
+       case 'h': progHelp    = true; break;
+       case 'c': trainClass  = argv[++i]; break;
+       case 'n': trainName   = argv[++i]; break;
+       case 'N': trainEvents = strtol(argv[++i],  NULL, 0); break;
+       case 't': trainTmp    = !trainTmp; break;
+       case 'd': trainDbg    = !trainDbg; break;
+       case 'r': AppendTo(trainRuns, argv[++i]); break;
+       case 'I': AppendPath(argv[++i]); break;
+       default: 
+         Error("runMain", "Unknown option %s", argv[i]);
+         return 1;
+       } // switch 
+      } // Long options 
+    } // Options 
+  }
+
+  if (trainClass.IsNull() || trainName.IsNull()) { 
+    if (progHelp) {
+      Usage(argv[0], std::cout, 0);
+      return 0;
+    }
+    Error(argv[0], "No train-setup class name or train name given");
+    return 1;
+  }
+  if (trainDbg) AppendTo(trainOpts, "debug");
+  if (progHelp) AppendTo(trainOpts, "help");
+
+  // Build the code 
+  if (!BuildTrain(trainClass, trainTmp, trainDbg)) return 1;
+  
+  // Make our object 
+  TrainSetup* trainSetup = MakeTrain(trainClass, trainName);
+  if (!trainSetup) return 1;
+
+  TrainSetup::Runner r(*trainSetup);
+  if (!r.Init(trainOpts)) return 1;
+  if (r.IsHelpAsked()) { 
+    Usage(argv[0], std::cout, &r);
+    return 0;
+  }
+
+  return r.Run(trainRuns, trainEvents, true) ? 0 : 1;
+}
+//
+// EOF
+//
+
+  
+  
+