ROOT logo
/**
 * @defgroup pwglf_forward_trains Trains.
 * 
 * Train specifications. 
 * See also @ref train_setup_doc
 */
/**
 * @file   TrainSetup.C
 * @author Christian Holm Christensen <cholm@master.hehi.nbi.dk>
 * @date   Tue Oct 16 17:56:57 2012
 * 
 * @brief  Base classs for train specifications 
 * 
 * @ingroup pwglf_forward_trains
 */
#ifndef TRAINSETUP_C
#define TRAINSETUP_C
#ifndef __CINT__
# include "Railway.C"
# include "Option.C"
# include <TDatime.h>
# include <TUrl.h>
# include <TString.h>
# include <TApplication.h>
# include <TStopwatch.h>
# include <AliAnalysisManager.h>
# include <AliVEventHandler.h>
# include <AliPhysicsSelection.h>
# include <AliPhysicsSelectionTask.h>
# include <AliCentralitySelectionTask.h>
# include <AliESDInputHandler.h>
# include <AliAODInputHandler.h>
# include <AliAODHandler.h>
# include <AliMCEventHandler.h>
# include <ctime>
#else 
struct Railway;
struct OptionList;
class TDatime;
class TUrl;
class TString;
class TStopwatch;
class AliVEventHandler;
class AliAnalysisManager;
class AliInputEventHandler;
#endif

//====================================================================
/** 
 * Generic set-up of an analysis train 
 *
 * See also @ref train_setup_doc
 *
 * @ingroup pwglf_forward_trains
 * 
 */
struct TrainSetup
{
  /** 
   * Constructor 
   * 
   * @param name Name of the train
   */
  TrainSetup(const TString& name)
    : fName(name), 
      fEscapedName(name),
      fDatimeString(""),
      fOptions(),
      fRailway(0),
      fMonitored("")
  {
    fOptions.Add("help", "Show help", false);
    fOptions.Add("date", "YYYY-MM-DD HH:MM", "Set date", "now");
    fOptions.Add("bare-ps", "Use bare physics selection w/o task", false);
    fOptions.Add("verbose", "LEVEL", "Set verbosity level", 0);
    fOptions.Add("url", "URL", "Job location & input URL", "");
    fOptions.Add("overwrite", "Allow overwrite", false);
    fOptions.Add("events", "N", "Number of events to analyse", -1);
    fOptions.Add("type", "ESD|AOD|USER", "Input data stype", "");
    fOptions.Add("setup", "Only do the setup", false);
    fOptions.Add("branches", "Load only requested branches", false);
    fDatimeString = "";
    fEscapedName  = EscapeName(fName, fDatimeString);
  }
  /** 
   * Copy constructor 
   * 
   * @param o Object to copy from 
   */
  TrainSetup(const TrainSetup& o) 
    : fName(o.fName), 
      fEscapedName(o.fEscapedName), 
      fDatimeString(o.fDatimeString),
      fOptions(o.fOptions), 
      fRailway(o.fRailway),
      fMonitored(o.fMonitored)
  {}
  /** 
   * Assignment operator
   * 
   * @param o Object to assign from 
   * 
   * @return Reference to this object
   */
  TrainSetup& operator=(const TrainSetup& o) 
  {
    if (&o == this) return *this;
    fName         = o.fName;
    fEscapedName  = o.fEscapedName;
    fDatimeString = o.fDatimeString;
    fOptions      = o.fOptions;
    fRailway       = o.fRailway;
    fMonitored    = o.fMonitored;
    return *this;
  }
  
  /** 
   * Destructor
   */
  virtual ~TrainSetup() {}
  /* @} */
  //__________________________________________________________________
  /** 
   * @{ 
   * @name Execution 
   */
  /** 
   * Initialize 
   * 
   * @return true on success 
   */
  Bool_t Init()
  {
    // --- Create the helper -----------------------------------------
    TString  url     = fOptions.Get("url");
    Int_t    verbose = fOptions.AsInt("verbose");

    fRailway = Railway::Create(url.Data(), verbose);
    if (!fRailway) { 
      Error("Init", "Failed to make the worker for URL %s", url.Data());
      return false;
    }

    // --- Check the type, if possible -------------------------------
    UShort_t type    = fRailway->InputType();
    Bool_t   mc      = fRailway->IsMC();
    if (fOptions.Has("type")) { 
      const TString& it = fOptions.Get("type");
      if      (it.EqualTo("ESD",TString::kIgnoreCase)) type = Railway::kESD;
      else if (it.EqualTo("AOD",TString::kIgnoreCase)) type = Railway::kAOD;
      else if (it.EqualTo("user",TString::kIgnoreCase)) 
	type = Railway::kUser;
    }

    // --- Rewrite the escpaed name ----------------------------------
    if (fOptions.Has("date")) { 
      fDatimeString = fOptions.Get("date");
      fEscapedName  = EscapeName(fName, fDatimeString);
    }
    
    // --- Get current directory and set-up sub-directory ------------
    TString cwd = gSystem->WorkingDirectory();
    if (!SetupWorkingDirectory()) return false;

    // --- Do initial helper setup -----------------------------------
    if (!fRailway->PreSetup()) return false;

    // --- Load ROOT libraries ---------------------------------------
    if (!fRailway->LoadROOT()) return false;
    
    // --- Load AliROOT libraries ------------------------------------
    if (!fRailway->LoadAliROOT()) return false;

    // --- Create analysis manager -----------------------------------
    AliAnalysisManager *mgr  = CreateAnalysisManager(fEscapedName);

    // In test mode, collect system information on every event 
    // if (oper == kTest)  mgr->SetNSysInfo(1); 
    if (verbose  >  0)      mgr->SetDebugLevel(verbose);
    mgr->SetAutoBranchLoading(!fOptions.Has("branches"));
    if (fRailway->Mode() == Railway::kLocal) 
      mgr->SetUseProgressBar(kTRUE, 100);
   
    // --- ESD input handler ------------------------------------------
    AliVEventHandler*  inputHandler = CreateInputHandler(type);
    if (inputHandler) mgr->SetInputEventHandler(inputHandler);
    
    // --- Monte-Carlo ------------------------------------------------
    AliVEventHandler*  mcHandler = CreateMCHandler(type,mc);
    if (mcHandler) mgr->SetMCtruthEventHandler(mcHandler);
    
    // --- AOD output handler -----------------------------------------
    AliVEventHandler*  outputHandler = CreateOutputHandler(type);
    if (outputHandler) mgr->SetOutputEventHandler(outputHandler);

    // --- Include analysis macro path in search path ----------------
    gROOT->SetMacroPath(Form("%s:%s:$ALICE_ROOT/ANALYSIS/macros",
			     cwd.Data(), gROOT->GetMacroPath()));

    // --- Physics selction - only for ESD ---------------------------
    if (type == Railway::kESD) CreatePhysicsSelection(mc, mgr);
    
    // --- Create centrality task ------------------------------------
    CreateCentralitySelection(mc);

    // --- Create tasks ----------------------------------------------
    CreateTasks(mgr);

    // --- Create monitor objects ------------------------------------
    CreateMonitors();

    // --- Post set-up initialization of helper ----------------------
    if (!fRailway->PostSetup()) return false;

    // --- Set debug level on defined tasks --------------------------
    if (verbose > 0) {
      TIter next(mgr->GetTasks());
      AliAnalysisTask* sub = 0;
      while ((sub = static_cast<AliAnalysisTask*>(next()))) { 
	AliAnalysisTaskSE* se = dynamic_cast<AliAnalysisTaskSE*>(sub);
	if (!se) continue;
	se->SetDebugLevel(verbose);
      }
    }

    // --- Print this setup ------------------------------------------
    Print();

    // --- Initialise the train --------------------------------------
    if (!mgr->InitAnalysis())  {
      gSystem->ChangeDirectory(cwd.Data());
      Error("Init","Failed to initialise train");
      return false;
    }

    // --- Enable progress bar ---------------------------------------
    if (fRailway->Mode() != Railway::kGrid) 
      mgr->SetUseProgressBar(true, 100);

    // --- Save setup to disk ----------------------------------------
    SaveSetup(true);

    // --- Some information ------------------------------------------
    mgr->PrintStatus();
    if (fRailway->Mode() != Railway::kLocal) {
      TIter next(mgr->GetTasks());
      AliAnalysisTask* sub = 0;
      while ((sub = static_cast<AliAnalysisTask*>(next()))) { 
	sub->Print();
      }
    }
    return true;
  }
  /** 
   * Print timer information
   * 
   * @param timer The timer
   * @param where Where this was called from 
   */
  void PrintTimer(TStopwatch& timer, const char* where)
  {
    timer.Stop();
    Double_t t = timer.RealTime();
    Int_t    h = Int_t(t / 3600); t -= h * 3600;
    Int_t    m = Int_t(t /   60); t -= m *   60;
    if (t < 0) t = 0;
    Info(where, "took %4d:%02d:%06.3f", h, m, t);
  }
  /** 
   * Run this train 
   * 
   * @return true on success 
   */    
  Bool_t Run()
  {
    TString cwd = gSystem->WorkingDirectory();
    Bool_t status = false;
    TStopwatch timer;
    timer.Start();
    try {
      if (!Init()) throw TString("Failed to intialize the train");
      PrintTimer(timer, "Initialization");
      timer.Continue();
      
      // Check if we're asked to only do the setup 
      if (fOptions.Has("setup")) {
	status = true;
	throw TString("Only did setup, no running");
      }

      // if (r) SaveSetup(*r, nEvents, asShell);
      
      Long64_t nEvents = fOptions.AsLong("events", -1);
      Long64_t ret     = fRailway->Run(nEvents);
      PrintTimer(timer, "Processing");
      timer.Continue();
      
      // Make sure we go back 
      gSystem->ChangeDirectory(cwd.Data());
      
      // Return. 
      if (ret < 0) throw TString("Analysis failed");

      status = true;
    }
    catch (TString& e) {
      if (status) Warning("Run", "%s", e.Data());
      else    	  Error("Run", "%s", e.Data());
    }
    if (fOptions.Has("date")) {
      TString tmp     = "";
      TString escaped = EscapeName(fName, tmp);
      gSystem->Exec(Form("rm -f last_%s", escaped.Data()));
      gSystem->Exec(Form("ln -sf %s last_%s", 
			 fEscapedName.Data(), escaped.Data()));
    }
    PrintTimer(timer, "Finish");
    timer.Continue();
    return status;
  }
  /** 
   * Get the options 
   * 
   * 
   * @return Reference ot the options 
   */
  OptionList& Options() { return fOptions; }
  /** 
   * Print information to standard output 
   * 
   */
  void Print(Option_t* ="") const
  {
    std::cout << "Train: " << fName << " (" << fEscapedName << ")" 
	      << std::endl;
    fOptions.Show(std::cout);
    if (fRailway) fRailway->Print();
  }
  /** 
   * Show the help 
   * 
   * @param o      Output stream
   * @param asProg If true, output as program options 
   * 
   * @return 
   */
  Bool_t Help(std::ostream& o=std::cout, bool asProg=false)
  {
    if (!fOptions.Has("help")) return true;

    if (!asProg) 
      o << "Usage: RunTrain(NAME, CLASS, OPTIONS)";
    
    o << "\n\nTrain Options:\n";
    fOptions.Help(o, asProg ? "  --" : "  ");
    o << "\n";

    if (!fRailway && fOptions.Has("url")) {
      TString url = fOptions.Get("url");
      fRailway = Railway::Create(url.Data());
    }
    if (fRailway) { 
      o << fRailway->Desc() << " URL form:\n\n"
	<< "    " << fRailway->UrlHelp() << "\n\n"
	<< "Options:\n";
      fRailway->Options().Help(o, "    ");
      o << "\n";
    }
    else { 
      o << "Possible URL forms:\n\n";
      Railway::ShowUrlHelp("LocalRailway");
      Railway::ShowUrlHelp("ProofRailway");
      Railway::ShowUrlHelp("LiteRailway");
      Railway::ShowUrlHelp("AAFRailway");
      Railway::ShowUrlHelp("AAFPluginRailway");
      Railway::ShowUrlHelp("GridRailway");
      o << "\n";
    }
    return false;
  }
  /** 
   * Run train.  This will AcLic compile the setup script, create
   * an object of that type with the given name, and then pass the 
   * options to it.  Then, it will run the setup.
   * 
   * @param name   Train name 
   * @param cls    Class name 
   * @param opts   Comma seperated list of options
   * @param asProg Run as program 
   * @param spawn  Spawn ROOT shell after execution 
   * 
   * @return true on success
   */
  static Bool_t Main(const TString& name, const TString& cls, 
		     const TCollection* opts, 
		     Bool_t asProg=true,
		     Bool_t spawn=false)
  {
    Bool_t ret = false;
    try {
      if (cls.IsNull()) 
	throw TString("No class name specified");
      if (name.IsNull()) 
	throw TString("No train name specified");

      gROOT->ProcessLine("gSystem->RedirectOutput(\"build.log\",\"w\");");
      Int_t error = 0;
      Int_t r1 = gROOT->LoadMacro(Form("%s.C+g", cls.Data()), &error);
      gROOT->ProcessLine("gSystem->RedirectOutput(0);");
      if (r1 < 0 || error) 
	throw TString::Format("Failed to load setup %s: %d - see build.log", 
			      cls.Data(), error);

      // Make our object using the interpreter 
      TString create = TString::Format("new %s(\"%s\")", 
				       cls.Data(), name.Data());
      gROOT->ProcessLine("gSystem->RedirectOutput(\"build.log\",\"a\");");
      Long_t retP = gROOT->ProcessLine(create, &error);
      gROOT->ProcessLine("gSystem->RedirectOutput(0);");
      if (!retP || error) 
	throw TString::Format("Failed to make object of class %s "
			      "(see build.log): 0x%08lx/%d\n\t%s", 
			      cls.Data(), retP, error, create.Data());

      TrainSetup* train = reinterpret_cast<TrainSetup*>(retP);
    
      // Now parse the options 
      if (!train->Options().Parse(opts)) 
	throw TString("Failed to parse options");

      // Info("", "URL=%s", train->Options().Get("url").Data());

      // Check if we got a help request
      if (train->Options().Has("help")) { 
	train->Help(std::cout, asProg);
	ret = true;
	throw TString("");
      }

      // return train->Init();
      ret = train->Run();
    }
    catch (TString& e) { 
      if (!e.IsNull()) Error("Main", "%s", e.Data());
    }
    // Info("Main", "End of main loop (app=%p, asProg=%s, spawn=%s)",
    //	 gApplication, asProg ? "true" : "false", spawn ? "true" : "false");
    if (gApplication && asProg) {
      if (!spawn) {
	gSystem->Sleep(3);
	gApplication->Terminate(ret ? 0 : 1);
      }
    }
    return ret;
  }
protected:
  //__________________________________________________________________
  /** 
   * @{ 
   * @name Overloadable behaviour 
   */
  //------------------------------------------------------------------
  /** 
   * Create the analysis manager 
   * 
   * @param name Name of the analysis 
   * 
   * @return Created analysis manager 
   */
  virtual AliAnalysisManager* CreateAnalysisManager(const char* name)
  {
    return new AliAnalysisManager(name,"Analysis Train");
  }
  //------------------------------------------------------------------
  /** 
   * Create input handler 
   * 
   * @param type 
   * 
   * @return 
   */
  virtual AliVEventHandler* CreateInputHandler(UShort_t type)
  {
    switch (type) {
    case Railway::kESD:  return new AliESDInputHandler(); 
    case Railway::kAOD:  return new AliAODInputHandler(); 
    case Railway::kUser: return 0;
    }
    return 0;
  }
  //------------------------------------------------------------------
  /** 
   * Create MC input handler 
   * 
   * @param mc    Assume monte-carlo input 
   * 
   * @return 
   */
  virtual AliVEventHandler* CreateMCHandler(UShort_t /*type*/, bool mc)
  {
    if (!mc) return 0;
    AliMCEventHandler* mcHandler = new AliMCEventHandler();
    mcHandler->SetReadTR(true); 
    return mcHandler;
  }
  //------------------------------------------------------------------
  /** 
   * Create output event handler 
   * 
   * @param type 
   * 
   * @return 
   */
  virtual AliVEventHandler* CreateOutputHandler(UShort_t type)
  {
    AliAODHandler* ret = new AliAODHandler();
    switch (type) { 
    case Railway::kESD: 
      ret->SetOutputFileName("AliAOD.root");
      break;
    case Railway::kAOD: 
      ret->SetOutputFileName("AliAOD.pass2.root");
      break;
    case Railway::kUser: 
      break;
    }
    
    return ret;
  }
  //------------------------------------------------------------------
  /** 
   * Create physics selection, and add to manager
   * 
   * @param mc Whether this is for MC 
   * @param mgr Manager
   */
  virtual void CreatePhysicsSelection(Bool_t mc, AliAnalysisManager* mgr)
  {
    if (fOptions.Has("bare-ps")) {
      AliInputEventHandler* input = 
	dynamic_cast<AliInputEventHandler*> (mgr->GetInputEventHandler());
      if (!input) return;

      AliPhysicsSelection* ps = new AliPhysicsSelection();
      if (mc) ps->SetAnalyzeMC();

      input->SetEventSelection(ps);

      return;
    }
    CoupleCar("AddTaskPhysicsSelection.C", Form("%d", mc));
    mgr->RegisterExtraFile("event_stat.root");
    mgr->AddStatisticsTask(AliVEvent::kAny);
  }
  //------------------------------------------------------------------
  /** 
   * Create centrality selection, and add to manager
   * 
   * @param mc Whether this is for MC 
   * @param mgr Manager
   */
  virtual void CreateCentralitySelection(Bool_t mc)
  {
    AliAnalysisTask* task = CoupleCar("AddTaskCentrality.C","true");
    AliCentralitySelectionTask* ctask = 
      dynamic_cast<AliCentralitySelectionTask*>(task);
    if (!ctask) return;
    if (mc) ctask->SetMCInput();
  }
  //------------------------------------------------------------------
  /** 
   * Create analysis tasks.  Must be overloaded by sub-class
   * 
   * @param mgr  Manager
   */
  virtual void CreateTasks(AliAnalysisManager* mgr)=0;
  /** 
   * Add a task using a script and possibly some arguments 
   * 
   * @param macro Script to execute 
   * @param args  Optional arguments to the script 
   * 
   * @return Created task or null
   */
  virtual AliAnalysisTask* CoupleCar(const TString& macro, 
				     const TString& args)
  {
    TString p = gSystem->Which(gROOT->GetMacroPath(), macro.Data());
    if (p.IsNull()) { 
      Error("CoupleCar", "Macro %s not found", macro.Data());
      return 0;
    }
    TString cmd(p);
    if (!args.IsNull()) 
      cmd.Append(TString::Format("(%s)", args.Data()));
    
    Int_t err;
    Long_t ret = gROOT->Macro(cmd.Data(), &err, false);
    if (!ret) { 
      Error("CoupleCar", "Failed to execute %s (%ld)", cmd.Data(), ret);
      return 0;
    }
    return reinterpret_cast<AliAnalysisTask*>(ret);
  }
  /** 
   * Add a task to the train with no arguments passed to the script 
   * 
   * @param macro The <b>AddTask</b> macro. 
   * 
   * @return The added task, if any
   */
  virtual AliAnalysisTask* CoupleCar(const TString& macro)
  {
    TString args;
    return CoupleCar(macro, args);
  }
  /** 
   * Add a single event analysis task to the train, passing the
   * specified arguments to the macro.
   * 
   * @param macro The <b>AddTask</b> macro 
   * @param args  Arguments to pass the macro 
   * 
   * @return The added task, if any 
   */
  virtual AliAnalysisTaskSE* CoupleSECar(const TString& macro, 
				       const TString& args)
  {
    return dynamic_cast<AliAnalysisTaskSE*>(CoupleCar(macro, args));
  }
  /** 
   * Add a single event task to the train with no arguments passed to
   * the script
   * 
   * @param macro The <b>AddTask</b> macro. 
   * 
   * @return The added task, if any
   */
  virtual AliAnalysisTaskSE* CoupleSECar(const TString& macro)
  {
    TString args;
    return CoupleSECar(macro, args);
  }
  /** 
   * Find an already added task 
   * 
   * @param name    Name of the task 
   * @param verbose If true, 
   * 
   * @return 
   */
  virtual AliAnalysisTask* FindCar(const TString& name, 
				    Bool_t verbose=true) const
  {
    AliAnalysisManager* mgr = AliAnalysisManager::GetAnalysisManager();
    if (!mgr) {
      ::Warning("FindCar", "No manager defined");
      return 0;
    }
    AliAnalysisTask* task = mgr->GetTask(name);
    if (!task && verbose)
      ::Warning("FindCar", "Task \"%s\" not found in train", 
		name.Data());
    return task;
  }
  /** 
   * Check if we have an MC handler attached 
   * 
   * @return True if MC handler is found in a valid manager.  False if
   * manager is not defined, or has no MC handler.
   */
  virtual Bool_t HasMCHandler() const 
  {
    AliAnalysisManager* mgr = AliAnalysisManager::GetAnalysisManager();
    if (!mgr) return false;
    return mgr->GetMCtruthEventHandler() != 0;
  }
  /** 
   * Set the name of the train - should be name of the class.  Must be
   * overloaded.
   * 
   * @return Class name as a constant C string 
   */
  virtual const Char_t* ClassName() const = 0;
  /* @} */
  //__________________________________________________________________
  virtual void AddMonitor(const TString& name)
  {
    if (!fMonitored.IsNull()) fMonitored.Append(":");
    fMonitored.Append(name);
  }
  virtual void CreateMonitors() 
  {
    if (fMonitored.IsNull()) return;
    if (fRailway->Mode() != Railway::kProof) return;

    TObjArray* tokens = fMonitored.Tokenize(":");
    TObject*   token  = 0;
    TIter      next(tokens);
    while ((token = next())) {
      gROOT->ProcessLine(Form("gProof->AddFeedback(\"%s\");", 
			      token->GetName()));
      
    }
    tokens->Delete();
  }
  //__________________________________________________________________
  /** 
   * @{ 
   * @name Utility functions 
   */
  /** 
   * Escape bad elements of the name 
   * 
   * @param name      Name to escape 
   * @param datimeStr Date and Time string 
   * 
   * @return escaped name 
   */  
  static TString EscapeName(const char* name, TString& datimeStr)
  {
    TString escaped = name;
    char  c[] = { ' ', '/', '@', 0 };
    char* p   = c;
    while (*p) { 
      char tmp[] = { *p, '\0' };
      escaped.ReplaceAll(tmp, "_");
      p++;
    }
    if (!datimeStr.IsNull() && 
	!datimeStr.EqualTo("none", TString::kIgnoreCase)) {
      TDatime datime;
      if (datimeStr.EqualTo("now", TString::kIgnoreCase)) 
	datime.Set();
      else {
	// Try various formats 
	struct tm t;
	const char* formats[] = { "%Ec", // Locale 
				  "%c", // Locale 
				  "%Ex EX", // Locale 
				  "%x %X", // Locale 
				  "%Y%m%d_%H%M", // YYYYMMDD_HHMM
				  "%F %R", // ISO standard, no seconds 
				  0 };
	const char** f = formats;
	Bool_t found = false;
	while (*f && !found) { 
	  // Reset needed fields 
	  t.tm_year  = 0;
	  t.tm_mon   = 0;
	  t.tm_mday  = 0;
	  t.tm_hour  = 0;
	  t.tm_min   = 0;
	  // Stop processing on first match 
	  if (strptime(datimeStr.Data(), *f, &t) != 0) found = true;
	  f++;
	}
	if (found) {
	  t.tm_mon += 1; // Return 0-based month
	  datime.Set(t.tm_year, t.tm_mon, t.tm_mday, t.tm_hour, t.tm_min, 0); 
	}
      }
      if (datime.GetYear() <= 1995 ||
	  datime.GetMonth() == 0 || 
	  datime.GetDay() == 0) return escaped;
      datimeStr = Form("%04d%02d%02d_%02d%02d", 
		       datime.GetYear(), 
		       datime.GetMonth(), 
		       datime.GetDay(), 
		       datime.GetHour(), 
		       datime.GetMinute());
      escaped.Append(Form("_%s", datimeStr.Data()));
    }
    return escaped;
  }    
  /** 
   * Make our working directory if so requested 
   * 
   * @return true on success
   */
  Bool_t SetupWorkingDirectory()
  {
    // Get the name of the target directory 
    TString& nam = fEscapedName;

    // Check if the directory exists already 
    Bool_t exists = gSystem->AccessPathName(nam.Data()) == 0;
    if (fRailway->Operation() == Railway::kTerminate && !exists) {
      Error("SetupWorkingDirectory", "File/directory %s does not exists", 
	    nam.Data());
      return false;
    }

    Bool_t overwrite = fOptions.Has("overwrite");
    // If we're not allowed to overwrite, then complain
    if (!overwrite && exists) {
      Error("SetupWorkingDirectory", "File/directory %s already exists", 
	    nam.Data());
      return false;
    }

    // Make the target directory if it doesn't exists 
    if (!exists) {
      if (gSystem->MakeDirectory(nam.Data())) {
	Error("SetupWorkingDirectory", "Failed to make directory '%s'", 
	      nam.Data());
	return false;
      }
    }
      
    // Change directory to target directory 
    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;
  }
  /** 
   * Save the setup as a ROOT script and possibly also a shell script
   * 
   * @param asShellScript If true, also save as shell script
   */
  virtual void SaveSetup(Bool_t asShellScript)
  {
    OptionList tmp(fOptions);
    const OptionList* uopts = (fRailway ? &fRailway->Options() : 0);
    if (tmp.Find("overwrite")) tmp.Set("overwrite");
    if (tmp.Find("date") && fEscapedName.Length() > fName.Length()+1) {
      Int_t n = fName.Length()+1;
      tmp.Set("date", fEscapedName(n, fEscapedName.Length()-n));
    }
    if (asShellScript) 
      SaveSetupShell("rerun", ClassName(), fName, tmp, uopts);
    SaveSetupROOT("ReRun", ClassName(), fName, tmp, uopts);
    if (fRailway) fRailway->AuxSave(fEscapedName, asShellScript);
    SavePostShellScript();
  }
  /** 
   * Save a setup as a shell script 
   * 
   * @param out   Output name of shell script 
   * @param cls   Class of the train 
   * @param name  Name of the train
   * @param opts  Option list
   * @param uopts Url options 
   */
  static void SaveSetupShell(const TString& out, const TString& cls,
			     const TString& name, const OptionList& opts,
			     const OptionList* uopts)
  {
    std::ofstream o(Form("%s.sh", out.Data()));
    o << "#!/bin/bash\n\n"
      << "class=\"" << cls << "\"\n"
      << "name=\"" << name << "\"\n\n"
      << "# Available options\n"
      << "# \n";
    opts.Help(o, "#    --");
    if (uopts) {
      o << "#\n"
	<< "# Available URI options\n"
	<< "# \n";
      uopts->Help(o, "#      ");
    }
    o << "#\n"
      << "opts=(--class=$class \\\n"
      << "  --name=$name";
    opts.Store(o, " \\\n  --", "", true);
    o << ")\n\n"
      << "echo \"Running runTrain ${opts[@]} $@\"\n"
      << "runTrain \"${opts[@]}\" $@\n\n"
      << "# EOF" << std::endl;
    o.close();
    gSystem->Exec(Form("chmod a+x %s.sh", out.Data()));
  }
  /** 
   * Save a setup as a ROOT script 
   * 
   * @param out   Output name of shell script 
   * @param cls   Class of the train 
   * @param name  Name of the train
   * @param opts  Option list
   * @param uopts Url options 
   */
  static void SaveSetupROOT(const TString& out, const TString& cls,
			    const TString& name, const OptionList& opts,
			    const OptionList* uopts)
  {
    OptionList tmp(opts);
    tmp.Remove("url");

    std::ofstream o(Form("%s.C", out.Data()));
    o << "// Available options:\n"
      << "// \n";
    tmp.Help(o, "//     ");
    if (uopts) {
      o << "// \n"
	<< "// Available URI options\n";
      uopts->Help(o, "//      ");
    }
    o << "//\n"
      << "Bool_t " << out << "()\n" 
      << "{\n"
      << "  TString name(\"" << name << "\");\n"
      << "  TString cls(\"" << cls << "\");\n"
      << "  TUrl    uri(\"" << opts.Get("url") << "\");\n"
      << "  \n"
      << "  TString opts(";
    tmp.Store(o, "\"", ",\"\n               ", false);
    o << ");\n\n"
      << "  TString path(";
    TString     path(gROOT->GetMacroPath());
    TObjArray*  elements = path.Tokenize(":");
    TObjString* element = 0;
    TIter       next(elements);
    while ((element = static_cast<TObjString*>(next()))) {
      if (element->String().IsNull()) continue;
      o << "\n               \"" << element->GetName() << ":\"";
    }
    elements->Delete();
    o << ");\n"
      << "  path.Append(\"$ALICE_ROOT/PWGLF/FORWARD/trains\");\n"
      << "  gROOT->SetMacroPath(path);\n\n"
      << "  gROOT->LoadMacro(\"RunTrain.C\");\n\n"
      << "  return RunTrain(name, cls, uri, opts);\n"
      << "}\n" 
      << "//\n"
      << "// EOF\n" 
      << "//" << std::endl;
    o.close();
  }    
  /** 
   * Write shell code to do post processing after terminate.  This
   * code should deal with a single run (or run range).  The following
   * shell variables are available to the code:
   *
   * - @c $prefix  Relative path to job directory or empty 
   * - @c $dest    Destination for output to be stored
   * 
   * Note, the code is injected into a shell function, and should
   * therefor not define new functions or the like.
   * 
   * @param o The output stream.  
   */
  virtual void PostShellCode(std::ostream& o)
  {
    o << "  echo \"Nothing to do for " << ClassName() 
      << " train\"" << std::endl;
  }
  /** 
   * Save a script to do post processing after terminate on each run
   * or run-range. 
   * 
   * The shell script will execute the train defined code (in
   * PostShellCode) for each run or run-range.  The train defined code
   * and call drawing and summarizing macros or the like.
   *
   * In case of Grid analysis, this script will download and extract
   * the appropriate ZIP files to separate directories, and then
   * change directory to these directories and execute the train
   * defined shell code there.  In this case, the script defines the
   * shell variable @c $prefix as the relative path to the job
   * directory.
   * 
   */
  void SavePostShellScript()
  {
    std::ofstream f("post.sh");
    if (!f) { 
      Error("SavePostAll", "Failed to open post.sh script");
      return;
    }
    f << "#!/bin/bash\n"
      << "# Generated by " << ClassName() << "\n"
      << "set -e\n"
      << "\n"
      << "dest=$1\n"
      << "prefix=\n"
      << "\n"
      << "doall() {"
      << std::endl;
    PostShellCode(f);
    f << "}\n"
      << "\n"
      << "if test ! -f Download.C ;then\n"
      << "  doall\n"
      << "  exit\n"
      << "fi\n"
      << "\n"
      << "if test ! -f .download ; then\n"
      << "  aliroot -l -b -q Download.C\\(1\\)\n"
      << "  touch .download\n"
      << "fi\n"
      << "prefix=../\n"
      << "\n"
      << "for i in root_archive_*.zip ; do\n"
      << "  d=`basename $i .zip` \n"
      << "  if test ! -d $d ; then\n"
      << "    echo \"Directory $d missing\"\n"
      << "    continue\n"
      << "  fi\n"
      << "  \n"
      << "  (cd $d && doall)\n"
      << "done\n"
      << "# EOF"
      << std::endl;
    f.close();
    gSystem->Exec("chmod a+x post.sh");
  }
    
  /* @} */
  TString      fName;
  TString      fEscapedName;
  TString      fDatimeString;
  OptionList   fOptions;
  Railway*      fRailway;
  TString      fMonitored;
};
#endif
 TrainSetup.C:1
 TrainSetup.C:2
 TrainSetup.C:3
 TrainSetup.C:4
 TrainSetup.C:5
 TrainSetup.C:6
 TrainSetup.C:7
 TrainSetup.C:8
 TrainSetup.C:9
 TrainSetup.C:10
 TrainSetup.C:11
 TrainSetup.C:12
 TrainSetup.C:13
 TrainSetup.C:14
 TrainSetup.C:15
 TrainSetup.C:16
 TrainSetup.C:17
 TrainSetup.C:18
 TrainSetup.C:19
 TrainSetup.C:20
 TrainSetup.C:21
 TrainSetup.C:22
 TrainSetup.C:23
 TrainSetup.C:24
 TrainSetup.C:25
 TrainSetup.C:26
 TrainSetup.C:27
 TrainSetup.C:28
 TrainSetup.C:29
 TrainSetup.C:30
 TrainSetup.C:31
 TrainSetup.C:32
 TrainSetup.C:33
 TrainSetup.C:34
 TrainSetup.C:35
 TrainSetup.C:36
 TrainSetup.C:37
 TrainSetup.C:38
 TrainSetup.C:39
 TrainSetup.C:40
 TrainSetup.C:41
 TrainSetup.C:42
 TrainSetup.C:43
 TrainSetup.C:44
 TrainSetup.C:45
 TrainSetup.C:46
 TrainSetup.C:47
 TrainSetup.C:48
 TrainSetup.C:49
 TrainSetup.C:50
 TrainSetup.C:51
 TrainSetup.C:52
 TrainSetup.C:53
 TrainSetup.C:54
 TrainSetup.C:55
 TrainSetup.C:56
 TrainSetup.C:57
 TrainSetup.C:58
 TrainSetup.C:59
 TrainSetup.C:60
 TrainSetup.C:61
 TrainSetup.C:62
 TrainSetup.C:63
 TrainSetup.C:64
 TrainSetup.C:65
 TrainSetup.C:66
 TrainSetup.C:67
 TrainSetup.C:68
 TrainSetup.C:69
 TrainSetup.C:70
 TrainSetup.C:71
 TrainSetup.C:72
 TrainSetup.C:73
 TrainSetup.C:74
 TrainSetup.C:75
 TrainSetup.C:76
 TrainSetup.C:77
 TrainSetup.C:78
 TrainSetup.C:79
 TrainSetup.C:80
 TrainSetup.C:81
 TrainSetup.C:82
 TrainSetup.C:83
 TrainSetup.C:84
 TrainSetup.C:85
 TrainSetup.C:86
 TrainSetup.C:87
 TrainSetup.C:88
 TrainSetup.C:89
 TrainSetup.C:90
 TrainSetup.C:91
 TrainSetup.C:92
 TrainSetup.C:93
 TrainSetup.C:94
 TrainSetup.C:95
 TrainSetup.C:96
 TrainSetup.C:97
 TrainSetup.C:98
 TrainSetup.C:99
 TrainSetup.C:100
 TrainSetup.C:101
 TrainSetup.C:102
 TrainSetup.C:103
 TrainSetup.C:104
 TrainSetup.C:105
 TrainSetup.C:106
 TrainSetup.C:107
 TrainSetup.C:108
 TrainSetup.C:109
 TrainSetup.C:110
 TrainSetup.C:111
 TrainSetup.C:112
 TrainSetup.C:113
 TrainSetup.C:114
 TrainSetup.C:115
 TrainSetup.C:116
 TrainSetup.C:117
 TrainSetup.C:118
 TrainSetup.C:119
 TrainSetup.C:120
 TrainSetup.C:121
 TrainSetup.C:122
 TrainSetup.C:123
 TrainSetup.C:124
 TrainSetup.C:125
 TrainSetup.C:126
 TrainSetup.C:127
 TrainSetup.C:128
 TrainSetup.C:129
 TrainSetup.C:130
 TrainSetup.C:131
 TrainSetup.C:132
 TrainSetup.C:133
 TrainSetup.C:134
 TrainSetup.C:135
 TrainSetup.C:136
 TrainSetup.C:137
 TrainSetup.C:138
 TrainSetup.C:139
 TrainSetup.C:140
 TrainSetup.C:141
 TrainSetup.C:142
 TrainSetup.C:143
 TrainSetup.C:144
 TrainSetup.C:145
 TrainSetup.C:146
 TrainSetup.C:147
 TrainSetup.C:148
 TrainSetup.C:149
 TrainSetup.C:150
 TrainSetup.C:151
 TrainSetup.C:152
 TrainSetup.C:153
 TrainSetup.C:154
 TrainSetup.C:155
 TrainSetup.C:156
 TrainSetup.C:157
 TrainSetup.C:158
 TrainSetup.C:159
 TrainSetup.C:160
 TrainSetup.C:161
 TrainSetup.C:162
 TrainSetup.C:163
 TrainSetup.C:164
 TrainSetup.C:165
 TrainSetup.C:166
 TrainSetup.C:167
 TrainSetup.C:168
 TrainSetup.C:169
 TrainSetup.C:170
 TrainSetup.C:171
 TrainSetup.C:172
 TrainSetup.C:173
 TrainSetup.C:174
 TrainSetup.C:175
 TrainSetup.C:176
 TrainSetup.C:177
 TrainSetup.C:178
 TrainSetup.C:179
 TrainSetup.C:180
 TrainSetup.C:181
 TrainSetup.C:182
 TrainSetup.C:183
 TrainSetup.C:184
 TrainSetup.C:185
 TrainSetup.C:186
 TrainSetup.C:187
 TrainSetup.C:188
 TrainSetup.C:189
 TrainSetup.C:190
 TrainSetup.C:191
 TrainSetup.C:192
 TrainSetup.C:193
 TrainSetup.C:194
 TrainSetup.C:195
 TrainSetup.C:196
 TrainSetup.C:197
 TrainSetup.C:198
 TrainSetup.C:199
 TrainSetup.C:200
 TrainSetup.C:201
 TrainSetup.C:202
 TrainSetup.C:203
 TrainSetup.C:204
 TrainSetup.C:205
 TrainSetup.C:206
 TrainSetup.C:207
 TrainSetup.C:208
 TrainSetup.C:209
 TrainSetup.C:210
 TrainSetup.C:211
 TrainSetup.C:212
 TrainSetup.C:213
 TrainSetup.C:214
 TrainSetup.C:215
 TrainSetup.C:216
 TrainSetup.C:217
 TrainSetup.C:218
 TrainSetup.C:219
 TrainSetup.C:220
 TrainSetup.C:221
 TrainSetup.C:222
 TrainSetup.C:223
 TrainSetup.C:224
 TrainSetup.C:225
 TrainSetup.C:226
 TrainSetup.C:227
 TrainSetup.C:228
 TrainSetup.C:229
 TrainSetup.C:230
 TrainSetup.C:231
 TrainSetup.C:232
 TrainSetup.C:233
 TrainSetup.C:234
 TrainSetup.C:235
 TrainSetup.C:236
 TrainSetup.C:237
 TrainSetup.C:238
 TrainSetup.C:239
 TrainSetup.C:240
 TrainSetup.C:241
 TrainSetup.C:242
 TrainSetup.C:243
 TrainSetup.C:244
 TrainSetup.C:245
 TrainSetup.C:246
 TrainSetup.C:247
 TrainSetup.C:248
 TrainSetup.C:249
 TrainSetup.C:250
 TrainSetup.C:251
 TrainSetup.C:252
 TrainSetup.C:253
 TrainSetup.C:254
 TrainSetup.C:255
 TrainSetup.C:256
 TrainSetup.C:257
 TrainSetup.C:258
 TrainSetup.C:259
 TrainSetup.C:260
 TrainSetup.C:261
 TrainSetup.C:262
 TrainSetup.C:263
 TrainSetup.C:264
 TrainSetup.C:265
 TrainSetup.C:266
 TrainSetup.C:267
 TrainSetup.C:268
 TrainSetup.C:269
 TrainSetup.C:270
 TrainSetup.C:271
 TrainSetup.C:272
 TrainSetup.C:273
 TrainSetup.C:274
 TrainSetup.C:275
 TrainSetup.C:276
 TrainSetup.C:277
 TrainSetup.C:278
 TrainSetup.C:279
 TrainSetup.C:280
 TrainSetup.C:281
 TrainSetup.C:282
 TrainSetup.C:283
 TrainSetup.C:284
 TrainSetup.C:285
 TrainSetup.C:286
 TrainSetup.C:287
 TrainSetup.C:288
 TrainSetup.C:289
 TrainSetup.C:290
 TrainSetup.C:291
 TrainSetup.C:292
 TrainSetup.C:293
 TrainSetup.C:294
 TrainSetup.C:295
 TrainSetup.C:296
 TrainSetup.C:297
 TrainSetup.C:298
 TrainSetup.C:299
 TrainSetup.C:300
 TrainSetup.C:301
 TrainSetup.C:302
 TrainSetup.C:303
 TrainSetup.C:304
 TrainSetup.C:305
 TrainSetup.C:306
 TrainSetup.C:307
 TrainSetup.C:308
 TrainSetup.C:309
 TrainSetup.C:310
 TrainSetup.C:311
 TrainSetup.C:312
 TrainSetup.C:313
 TrainSetup.C:314
 TrainSetup.C:315
 TrainSetup.C:316
 TrainSetup.C:317
 TrainSetup.C:318
 TrainSetup.C:319
 TrainSetup.C:320
 TrainSetup.C:321
 TrainSetup.C:322
 TrainSetup.C:323
 TrainSetup.C:324
 TrainSetup.C:325
 TrainSetup.C:326
 TrainSetup.C:327
 TrainSetup.C:328
 TrainSetup.C:329
 TrainSetup.C:330
 TrainSetup.C:331
 TrainSetup.C:332
 TrainSetup.C:333
 TrainSetup.C:334
 TrainSetup.C:335
 TrainSetup.C:336
 TrainSetup.C:337
 TrainSetup.C:338
 TrainSetup.C:339
 TrainSetup.C:340
 TrainSetup.C:341
 TrainSetup.C:342
 TrainSetup.C:343
 TrainSetup.C:344
 TrainSetup.C:345
 TrainSetup.C:346
 TrainSetup.C:347
 TrainSetup.C:348
 TrainSetup.C:349
 TrainSetup.C:350
 TrainSetup.C:351
 TrainSetup.C:352
 TrainSetup.C:353
 TrainSetup.C:354
 TrainSetup.C:355
 TrainSetup.C:356
 TrainSetup.C:357
 TrainSetup.C:358
 TrainSetup.C:359
 TrainSetup.C:360
 TrainSetup.C:361
 TrainSetup.C:362
 TrainSetup.C:363
 TrainSetup.C:364
 TrainSetup.C:365
 TrainSetup.C:366
 TrainSetup.C:367
 TrainSetup.C:368
 TrainSetup.C:369
 TrainSetup.C:370
 TrainSetup.C:371
 TrainSetup.C:372
 TrainSetup.C:373
 TrainSetup.C:374
 TrainSetup.C:375
 TrainSetup.C:376
 TrainSetup.C:377
 TrainSetup.C:378
 TrainSetup.C:379
 TrainSetup.C:380
 TrainSetup.C:381
 TrainSetup.C:382
 TrainSetup.C:383
 TrainSetup.C:384
 TrainSetup.C:385
 TrainSetup.C:386
 TrainSetup.C:387
 TrainSetup.C:388
 TrainSetup.C:389
 TrainSetup.C:390
 TrainSetup.C:391
 TrainSetup.C:392
 TrainSetup.C:393
 TrainSetup.C:394
 TrainSetup.C:395
 TrainSetup.C:396
 TrainSetup.C:397
 TrainSetup.C:398
 TrainSetup.C:399
 TrainSetup.C:400
 TrainSetup.C:401
 TrainSetup.C:402
 TrainSetup.C:403
 TrainSetup.C:404
 TrainSetup.C:405
 TrainSetup.C:406
 TrainSetup.C:407
 TrainSetup.C:408
 TrainSetup.C:409
 TrainSetup.C:410
 TrainSetup.C:411
 TrainSetup.C:412
 TrainSetup.C:413
 TrainSetup.C:414
 TrainSetup.C:415
 TrainSetup.C:416
 TrainSetup.C:417
 TrainSetup.C:418
 TrainSetup.C:419
 TrainSetup.C:420
 TrainSetup.C:421
 TrainSetup.C:422
 TrainSetup.C:423
 TrainSetup.C:424
 TrainSetup.C:425
 TrainSetup.C:426
 TrainSetup.C:427
 TrainSetup.C:428
 TrainSetup.C:429
 TrainSetup.C:430
 TrainSetup.C:431
 TrainSetup.C:432
 TrainSetup.C:433
 TrainSetup.C:434
 TrainSetup.C:435
 TrainSetup.C:436
 TrainSetup.C:437
 TrainSetup.C:438
 TrainSetup.C:439
 TrainSetup.C:440
 TrainSetup.C:441
 TrainSetup.C:442
 TrainSetup.C:443
 TrainSetup.C:444
 TrainSetup.C:445
 TrainSetup.C:446
 TrainSetup.C:447
 TrainSetup.C:448
 TrainSetup.C:449
 TrainSetup.C:450
 TrainSetup.C:451
 TrainSetup.C:452
 TrainSetup.C:453
 TrainSetup.C:454
 TrainSetup.C:455
 TrainSetup.C:456
 TrainSetup.C:457
 TrainSetup.C:458
 TrainSetup.C:459
 TrainSetup.C:460
 TrainSetup.C:461
 TrainSetup.C:462
 TrainSetup.C:463
 TrainSetup.C:464
 TrainSetup.C:465
 TrainSetup.C:466
 TrainSetup.C:467
 TrainSetup.C:468
 TrainSetup.C:469
 TrainSetup.C:470
 TrainSetup.C:471
 TrainSetup.C:472
 TrainSetup.C:473
 TrainSetup.C:474
 TrainSetup.C:475
 TrainSetup.C:476
 TrainSetup.C:477
 TrainSetup.C:478
 TrainSetup.C:479
 TrainSetup.C:480
 TrainSetup.C:481
 TrainSetup.C:482
 TrainSetup.C:483
 TrainSetup.C:484
 TrainSetup.C:485
 TrainSetup.C:486
 TrainSetup.C:487
 TrainSetup.C:488
 TrainSetup.C:489
 TrainSetup.C:490
 TrainSetup.C:491
 TrainSetup.C:492
 TrainSetup.C:493
 TrainSetup.C:494
 TrainSetup.C:495
 TrainSetup.C:496
 TrainSetup.C:497
 TrainSetup.C:498
 TrainSetup.C:499
 TrainSetup.C:500
 TrainSetup.C:501
 TrainSetup.C:502
 TrainSetup.C:503
 TrainSetup.C:504
 TrainSetup.C:505
 TrainSetup.C:506
 TrainSetup.C:507
 TrainSetup.C:508
 TrainSetup.C:509
 TrainSetup.C:510
 TrainSetup.C:511
 TrainSetup.C:512
 TrainSetup.C:513
 TrainSetup.C:514
 TrainSetup.C:515
 TrainSetup.C:516
 TrainSetup.C:517
 TrainSetup.C:518
 TrainSetup.C:519
 TrainSetup.C:520
 TrainSetup.C:521
 TrainSetup.C:522
 TrainSetup.C:523
 TrainSetup.C:524
 TrainSetup.C:525
 TrainSetup.C:526
 TrainSetup.C:527
 TrainSetup.C:528
 TrainSetup.C:529
 TrainSetup.C:530
 TrainSetup.C:531
 TrainSetup.C:532
 TrainSetup.C:533
 TrainSetup.C:534
 TrainSetup.C:535
 TrainSetup.C:536
 TrainSetup.C:537
 TrainSetup.C:538
 TrainSetup.C:539
 TrainSetup.C:540
 TrainSetup.C:541
 TrainSetup.C:542
 TrainSetup.C:543
 TrainSetup.C:544
 TrainSetup.C:545
 TrainSetup.C:546
 TrainSetup.C:547
 TrainSetup.C:548
 TrainSetup.C:549
 TrainSetup.C:550
 TrainSetup.C:551
 TrainSetup.C:552
 TrainSetup.C:553
 TrainSetup.C:554
 TrainSetup.C:555
 TrainSetup.C:556
 TrainSetup.C:557
 TrainSetup.C:558
 TrainSetup.C:559
 TrainSetup.C:560
 TrainSetup.C:561
 TrainSetup.C:562
 TrainSetup.C:563
 TrainSetup.C:564
 TrainSetup.C:565
 TrainSetup.C:566
 TrainSetup.C:567
 TrainSetup.C:568
 TrainSetup.C:569
 TrainSetup.C:570
 TrainSetup.C:571
 TrainSetup.C:572
 TrainSetup.C:573
 TrainSetup.C:574
 TrainSetup.C:575
 TrainSetup.C:576
 TrainSetup.C:577
 TrainSetup.C:578
 TrainSetup.C:579
 TrainSetup.C:580
 TrainSetup.C:581
 TrainSetup.C:582
 TrainSetup.C:583
 TrainSetup.C:584
 TrainSetup.C:585
 TrainSetup.C:586
 TrainSetup.C:587
 TrainSetup.C:588
 TrainSetup.C:589
 TrainSetup.C:590
 TrainSetup.C:591
 TrainSetup.C:592
 TrainSetup.C:593
 TrainSetup.C:594
 TrainSetup.C:595
 TrainSetup.C:596
 TrainSetup.C:597
 TrainSetup.C:598
 TrainSetup.C:599
 TrainSetup.C:600
 TrainSetup.C:601
 TrainSetup.C:602
 TrainSetup.C:603
 TrainSetup.C:604
 TrainSetup.C:605
 TrainSetup.C:606
 TrainSetup.C:607
 TrainSetup.C:608
 TrainSetup.C:609
 TrainSetup.C:610
 TrainSetup.C:611
 TrainSetup.C:612
 TrainSetup.C:613
 TrainSetup.C:614
 TrainSetup.C:615
 TrainSetup.C:616
 TrainSetup.C:617
 TrainSetup.C:618
 TrainSetup.C:619
 TrainSetup.C:620
 TrainSetup.C:621
 TrainSetup.C:622
 TrainSetup.C:623
 TrainSetup.C:624
 TrainSetup.C:625
 TrainSetup.C:626
 TrainSetup.C:627
 TrainSetup.C:628
 TrainSetup.C:629
 TrainSetup.C:630
 TrainSetup.C:631
 TrainSetup.C:632
 TrainSetup.C:633
 TrainSetup.C:634
 TrainSetup.C:635
 TrainSetup.C:636
 TrainSetup.C:637
 TrainSetup.C:638
 TrainSetup.C:639
 TrainSetup.C:640
 TrainSetup.C:641
 TrainSetup.C:642
 TrainSetup.C:643
 TrainSetup.C:644
 TrainSetup.C:645
 TrainSetup.C:646
 TrainSetup.C:647
 TrainSetup.C:648
 TrainSetup.C:649
 TrainSetup.C:650
 TrainSetup.C:651
 TrainSetup.C:652
 TrainSetup.C:653
 TrainSetup.C:654
 TrainSetup.C:655
 TrainSetup.C:656
 TrainSetup.C:657
 TrainSetup.C:658
 TrainSetup.C:659
 TrainSetup.C:660
 TrainSetup.C:661
 TrainSetup.C:662
 TrainSetup.C:663
 TrainSetup.C:664
 TrainSetup.C:665
 TrainSetup.C:666
 TrainSetup.C:667
 TrainSetup.C:668
 TrainSetup.C:669
 TrainSetup.C:670
 TrainSetup.C:671
 TrainSetup.C:672
 TrainSetup.C:673
 TrainSetup.C:674
 TrainSetup.C:675
 TrainSetup.C:676
 TrainSetup.C:677
 TrainSetup.C:678
 TrainSetup.C:679
 TrainSetup.C:680
 TrainSetup.C:681
 TrainSetup.C:682
 TrainSetup.C:683
 TrainSetup.C:684
 TrainSetup.C:685
 TrainSetup.C:686
 TrainSetup.C:687
 TrainSetup.C:688
 TrainSetup.C:689
 TrainSetup.C:690
 TrainSetup.C:691
 TrainSetup.C:692
 TrainSetup.C:693
 TrainSetup.C:694
 TrainSetup.C:695
 TrainSetup.C:696
 TrainSetup.C:697
 TrainSetup.C:698
 TrainSetup.C:699
 TrainSetup.C:700
 TrainSetup.C:701
 TrainSetup.C:702
 TrainSetup.C:703
 TrainSetup.C:704
 TrainSetup.C:705
 TrainSetup.C:706
 TrainSetup.C:707
 TrainSetup.C:708
 TrainSetup.C:709
 TrainSetup.C:710
 TrainSetup.C:711
 TrainSetup.C:712
 TrainSetup.C:713
 TrainSetup.C:714
 TrainSetup.C:715
 TrainSetup.C:716
 TrainSetup.C:717
 TrainSetup.C:718
 TrainSetup.C:719
 TrainSetup.C:720
 TrainSetup.C:721
 TrainSetup.C:722
 TrainSetup.C:723
 TrainSetup.C:724
 TrainSetup.C:725
 TrainSetup.C:726
 TrainSetup.C:727
 TrainSetup.C:728
 TrainSetup.C:729
 TrainSetup.C:730
 TrainSetup.C:731
 TrainSetup.C:732
 TrainSetup.C:733
 TrainSetup.C:734
 TrainSetup.C:735
 TrainSetup.C:736
 TrainSetup.C:737
 TrainSetup.C:738
 TrainSetup.C:739
 TrainSetup.C:740
 TrainSetup.C:741
 TrainSetup.C:742
 TrainSetup.C:743
 TrainSetup.C:744
 TrainSetup.C:745
 TrainSetup.C:746
 TrainSetup.C:747
 TrainSetup.C:748
 TrainSetup.C:749
 TrainSetup.C:750
 TrainSetup.C:751
 TrainSetup.C:752
 TrainSetup.C:753
 TrainSetup.C:754
 TrainSetup.C:755
 TrainSetup.C:756
 TrainSetup.C:757
 TrainSetup.C:758
 TrainSetup.C:759
 TrainSetup.C:760
 TrainSetup.C:761
 TrainSetup.C:762
 TrainSetup.C:763
 TrainSetup.C:764
 TrainSetup.C:765
 TrainSetup.C:766
 TrainSetup.C:767
 TrainSetup.C:768
 TrainSetup.C:769
 TrainSetup.C:770
 TrainSetup.C:771
 TrainSetup.C:772
 TrainSetup.C:773
 TrainSetup.C:774
 TrainSetup.C:775
 TrainSetup.C:776
 TrainSetup.C:777
 TrainSetup.C:778
 TrainSetup.C:779
 TrainSetup.C:780
 TrainSetup.C:781
 TrainSetup.C:782
 TrainSetup.C:783
 TrainSetup.C:784
 TrainSetup.C:785
 TrainSetup.C:786
 TrainSetup.C:787
 TrainSetup.C:788
 TrainSetup.C:789
 TrainSetup.C:790
 TrainSetup.C:791
 TrainSetup.C:792
 TrainSetup.C:793
 TrainSetup.C:794
 TrainSetup.C:795
 TrainSetup.C:796
 TrainSetup.C:797
 TrainSetup.C:798
 TrainSetup.C:799
 TrainSetup.C:800
 TrainSetup.C:801
 TrainSetup.C:802
 TrainSetup.C:803
 TrainSetup.C:804
 TrainSetup.C:805
 TrainSetup.C:806
 TrainSetup.C:807
 TrainSetup.C:808
 TrainSetup.C:809
 TrainSetup.C:810
 TrainSetup.C:811
 TrainSetup.C:812
 TrainSetup.C:813
 TrainSetup.C:814
 TrainSetup.C:815
 TrainSetup.C:816
 TrainSetup.C:817
 TrainSetup.C:818
 TrainSetup.C:819
 TrainSetup.C:820
 TrainSetup.C:821
 TrainSetup.C:822
 TrainSetup.C:823
 TrainSetup.C:824
 TrainSetup.C:825
 TrainSetup.C:826
 TrainSetup.C:827
 TrainSetup.C:828
 TrainSetup.C:829
 TrainSetup.C:830
 TrainSetup.C:831
 TrainSetup.C:832
 TrainSetup.C:833
 TrainSetup.C:834
 TrainSetup.C:835
 TrainSetup.C:836
 TrainSetup.C:837
 TrainSetup.C:838
 TrainSetup.C:839
 TrainSetup.C:840
 TrainSetup.C:841
 TrainSetup.C:842
 TrainSetup.C:843
 TrainSetup.C:844
 TrainSetup.C:845
 TrainSetup.C:846
 TrainSetup.C:847
 TrainSetup.C:848
 TrainSetup.C:849
 TrainSetup.C:850
 TrainSetup.C:851
 TrainSetup.C:852
 TrainSetup.C:853
 TrainSetup.C:854
 TrainSetup.C:855
 TrainSetup.C:856
 TrainSetup.C:857
 TrainSetup.C:858
 TrainSetup.C:859
 TrainSetup.C:860
 TrainSetup.C:861
 TrainSetup.C:862
 TrainSetup.C:863
 TrainSetup.C:864
 TrainSetup.C:865
 TrainSetup.C:866
 TrainSetup.C:867
 TrainSetup.C:868
 TrainSetup.C:869
 TrainSetup.C:870
 TrainSetup.C:871
 TrainSetup.C:872
 TrainSetup.C:873
 TrainSetup.C:874
 TrainSetup.C:875
 TrainSetup.C:876
 TrainSetup.C:877
 TrainSetup.C:878
 TrainSetup.C:879
 TrainSetup.C:880
 TrainSetup.C:881
 TrainSetup.C:882
 TrainSetup.C:883
 TrainSetup.C:884
 TrainSetup.C:885
 TrainSetup.C:886
 TrainSetup.C:887
 TrainSetup.C:888
 TrainSetup.C:889
 TrainSetup.C:890
 TrainSetup.C:891
 TrainSetup.C:892
 TrainSetup.C:893
 TrainSetup.C:894
 TrainSetup.C:895
 TrainSetup.C:896
 TrainSetup.C:897
 TrainSetup.C:898
 TrainSetup.C:899
 TrainSetup.C:900
 TrainSetup.C:901
 TrainSetup.C:902
 TrainSetup.C:903
 TrainSetup.C:904
 TrainSetup.C:905
 TrainSetup.C:906
 TrainSetup.C:907
 TrainSetup.C:908
 TrainSetup.C:909
 TrainSetup.C:910
 TrainSetup.C:911
 TrainSetup.C:912
 TrainSetup.C:913
 TrainSetup.C:914
 TrainSetup.C:915
 TrainSetup.C:916
 TrainSetup.C:917
 TrainSetup.C:918
 TrainSetup.C:919
 TrainSetup.C:920
 TrainSetup.C:921
 TrainSetup.C:922
 TrainSetup.C:923
 TrainSetup.C:924
 TrainSetup.C:925
 TrainSetup.C:926
 TrainSetup.C:927
 TrainSetup.C:928
 TrainSetup.C:929
 TrainSetup.C:930
 TrainSetup.C:931
 TrainSetup.C:932
 TrainSetup.C:933
 TrainSetup.C:934
 TrainSetup.C:935
 TrainSetup.C:936
 TrainSetup.C:937
 TrainSetup.C:938
 TrainSetup.C:939
 TrainSetup.C:940
 TrainSetup.C:941
 TrainSetup.C:942
 TrainSetup.C:943
 TrainSetup.C:944
 TrainSetup.C:945
 TrainSetup.C:946
 TrainSetup.C:947
 TrainSetup.C:948
 TrainSetup.C:949
 TrainSetup.C:950
 TrainSetup.C:951
 TrainSetup.C:952
 TrainSetup.C:953
 TrainSetup.C:954
 TrainSetup.C:955
 TrainSetup.C:956
 TrainSetup.C:957
 TrainSetup.C:958
 TrainSetup.C:959
 TrainSetup.C:960
 TrainSetup.C:961
 TrainSetup.C:962
 TrainSetup.C:963
 TrainSetup.C:964
 TrainSetup.C:965
 TrainSetup.C:966
 TrainSetup.C:967
 TrainSetup.C:968
 TrainSetup.C:969
 TrainSetup.C:970
 TrainSetup.C:971
 TrainSetup.C:972
 TrainSetup.C:973
 TrainSetup.C:974
 TrainSetup.C:975
 TrainSetup.C:976
 TrainSetup.C:977
 TrainSetup.C:978
 TrainSetup.C:979
 TrainSetup.C:980
 TrainSetup.C:981
 TrainSetup.C:982
 TrainSetup.C:983
 TrainSetup.C:984
 TrainSetup.C:985
 TrainSetup.C:986
 TrainSetup.C:987
 TrainSetup.C:988
 TrainSetup.C:989
 TrainSetup.C:990
 TrainSetup.C:991
 TrainSetup.C:992
 TrainSetup.C:993
 TrainSetup.C:994
 TrainSetup.C:995
 TrainSetup.C:996
 TrainSetup.C:997
 TrainSetup.C:998
 TrainSetup.C:999
 TrainSetup.C:1000
 TrainSetup.C:1001
 TrainSetup.C:1002
 TrainSetup.C:1003
 TrainSetup.C:1004
 TrainSetup.C:1005
 TrainSetup.C:1006
 TrainSetup.C:1007
 TrainSetup.C:1008
 TrainSetup.C:1009
 TrainSetup.C:1010
 TrainSetup.C:1011
 TrainSetup.C:1012
 TrainSetup.C:1013
 TrainSetup.C:1014
 TrainSetup.C:1015
 TrainSetup.C:1016
 TrainSetup.C:1017
 TrainSetup.C:1018
 TrainSetup.C:1019
 TrainSetup.C:1020
 TrainSetup.C:1021
 TrainSetup.C:1022