]> git.uio.no Git - u/mrichter/AliRoot.git/blob - PWGHF/centraltrain/AnalysisTrainPWG3AOD.C
Merge branch 'feature-movesplit'
[u/mrichter/AliRoot.git] / PWGHF / centraltrain / AnalysisTrainPWG3AOD.C
1 //===================== ANALYSIS TRAIN =========================================
2 // To use: copy this macro to your work directory, modify the global part to match
3 // your needs, then run root.
4 //    root[0] .L AnalysisTrain.C
5 // Grid full mode as below (other modes: test, offline, submit, terminate)
6 //    root[1] AnalysisTrainNew("grid", "full")
7 // CAF mode (requires root v5-23-02 + aliroot v4-16-Rev08)
8 //    root[2] AnalysisTrainNew("proof")
9 // Local mode requires AliESds.root or AliAOD.root in ./data directory
10 //    root[3] AnalysisTrainNew("local")
11 // In proof and grid modes, a token is needed and sourcing the produced environment file.
12 //
13 // If 'saveTrain' flag is set, the train will generate a directory name and run
14 // in this directory. A configuration file 'ConfigTrain.C' will be generated. 
15 // One can replay at any time the train via:
16 //    root[1] AnalysisTrainNew(ana_mode, plugin_mode, "train_default_<date>/ConfigTrain.C")
17
18 //==================   TRAIN NAME   ============================================
19 TString     train_name         = "PWG3AOD"; // local folder name
20 TString     train_tag          = "pass1";        // Train special tag appended to 
21                                             // visible name. ("data", "sim", "pp", "highmult", ...)
22                // Name in train page (DON'T CHANGE)
23 TString     visible_name       = Form("PWG3AOD%s$2_$3", train_tag.Data()); //# FIXED #
24                // Add train composition and other comments
25 TString     job_comment        = "PWG3 tasks on AODs (di)muon/vertexing/dielectrons";
26 TString     job_tag            = Form("%s: %s", visible_name.Data(), job_comment.Data());
27 //==============================================================================
28
29 // ### Settings that make sense in PROOF only
30 //==============================================================================
31 TString     proof_cluster      = "alice-caf.cern.ch";
32 Bool_t      useAFPAR           = kFALSE;  // use AF special par file
33 TString     AFversion          = "AF-v4-17";
34 // Change CAF dataset here
35 TString     proof_dataset      = "/COMMON/COMMON/LHC09a4_run8100X#/esdTree";
36 TString     proof_outdir       = "";
37
38 // ### Settings that make sense when using the Alien plugin
39 //==============================================================================
40 Int_t       runOnData          = 0;       // Set to 1 if processing real data
41 Int_t       iCollision         = 0;       // 0=pp, 1=Pb-Pb
42 Bool_t      usePLUGIN          = kTRUE;   // do not change
43 Bool_t      useProductionMode  = kTRUE;   // use the plugin in production mode
44 // Usage of par files ONLY in grid mode and ONLY if the code is not available
45 // in the deployed AliRoot versions. Par file search path: local dir, if not there $ALICE_ROOT.
46 // To refresh par files, remove the ones in the workdir, then do "make <target.par>" in 
47 // AliRoot.
48 Bool_t      usePAR             = kFALSE;  // use par files for extra libs
49 Bool_t      useCPAR            = kFALSE;  // use par files for common libs
50 TString     root_version       = "v5-27-06b";  // *CHANGE ME IF MORE RECENT IN GRID*
51 TString     aliroot_version    = "v4-21-05-AN";  // *CHANGE ME IF MORE RECENT IN GRID*                                          
52 // Change production base directory here (test mode)
53 TString     alien_datadir      = "/alice/data/2010/LHC10h";
54                // Work directory in GRID (DON'T CHANGE)
55 TString     grid_workdir       = "/alice/cern.ch/user/a/alidaq/AOD/AOD$2";
56                // Data pattern - change as needed for test mode
57 TString     data_pattern       = "*ESDs/pass2/*AOD.root";
58 // Set the run range
59 Int_t run_numbers[10] = {137230}; // **********************!!!!!!!
60 //Int_t       run_range[2]       =  {114786, 114949};  // LHC09a7   *CHANGE ME*
61 // AliEn output directory. If blank will become output_<train_name>
62                // Output directory (DON'T CHANGE)
63 TString     alien_outdir       = "$1/AOD$2";
64                // Input collection (production mode)
65 TString     data_collection    = "$1/qa1.xml";
66 // Output folder to write delta AOD's. Considered if not null.
67 TString     outputSingleFolder = "";
68 //TString     outputSingleFolder = "deltas";
69 // Number of files merged in a chunk
70 Int_t       maxMergeFiles      = 20;
71 // Files that should not be merged
72 TString     mergeExclude       = "AliAOD.root AliAOD.VertexingHF.root AliAOD.Jets.root deltaAODPartCorr.root AliAOD.Muons.root AliAOD.Dimuons.root AliAOD.Dielectron.root AliAODCentrality.root";
73 // Make replicas on the storages below
74 TString     outputStorages      = "disk=4";
75 // Number of runs per master job
76 Int_t       nRunsPerMaster     = 10;
77 // Maximum number of files per job (gives size of AOD)
78 Int_t       nFilesPerJob       = 20;
79 // Int_t       nFilesPerJob       = 1; (AOD->delta AOD production case)
80 // ### Settings that make sense only for local analysis
81 //==============================================================================
82 // Change local xml dataset for local interactive analysis
83 TString     local_xmldataset   = "";
84
85 // ### Other flags to steer the analysis
86 //==============================================================================
87 Bool_t      usePhysicsSelection = kFALSE; // use physics selection
88 Bool_t      useBKrejection      = kFALSE; // use BK rejection
89 Bool_t      useCentrality       = kTRUE; // centrality delta AOD
90 Bool_t      useTender           = kFALSE; // use tender wagon
91 Bool_t      useV0tender         = kFALSE;  // use V0 correction in tender
92 Bool_t      useMergeViaJDL      = kTRUE;  // merge via JDL
93 Bool_t      useFastReadOption   = kTRUE;  // use xrootd tweaks
94 Bool_t      useOverwriteMode    = kTRUE;  // overwrite existing collections
95 Bool_t      useDATE             = kFALSE; // use date in train name
96 Bool_t      useDBG              = kFALSE;  // activate debugging
97 Bool_t      useMC               = kFALSE;  // use MC info
98 Bool_t      useTAGS             = kFALSE;  // use ESD tags for selection
99 Bool_t      useKFILTER          = kFALSE;  // use Kinematics filter
100 Bool_t      useTR               = kFALSE;  // use track references
101 Bool_t      useCORRFW           = kTRUE; // do not change
102 Bool_t      useAODTAGS          = kFALSE; // use AOD tags
103 Bool_t      saveTrain           = kTRUE;  // save train configuration as: 
104 Bool_t      saveCanvases        = kFALSE;  // save canvases created in Terminate
105 Bool_t      saveProofToAlien    = kFALSE; // save proof outputs in AliEn
106
107 // ### Analysis modules to be included. Some may not be yet fully implemented.
108 //==============================================================================
109 Int_t       iAODanalysis       = 1;      // Analysis on input AOD's
110 Int_t       iAODhandler        = 0;      // Analysis produces an AOD or dAOD's
111
112 Int_t       iPWG3hfe           = 0;      // Electrons analysis (PWG3)
113 Int_t       iPWG3JPSIfilter    = 0;      // JPSI filtering (PWG3)
114 Int_t       iPWG3JPSI          = 1;      // JPSI analysis (PWG3)
115 Int_t       iPWG3d2h           = 1;      // D0->2 hadrons (PWG3)
116 Int_t       iPWG3MuonTrain     = 1;      // Muon analysis train
117
118
119 // Temporaries.
120 TString anaPars = "";
121 TString anaLibs = "";
122 // Function signatures
123 class AliAnalysisAlien;
124
125 //______________________________________________________________________________
126 void AnalysisTrainPWG3AOD(const char *analysis_mode="local", 
127                           const char *plugin_mode="full",
128                           const char *config_file="")
129 {
130 // Main analysis train macro. If a configuration file is provided, all parameters
131 // are taken from there but may be altered by CheckModuleFlags.
132    if (strlen(config_file) && !LoadConfig(config_file)) return;
133    TString smode(analysis_mode);
134    smode.ToUpper();
135    TString spmode(plugin_mode);
136    spmode.ToLower();
137    if (spmode == "test") useProductionMode = kFALSE;
138    // Check compatibility of selected modules
139    CheckModuleFlags(smode);
140    if (saveTrain)              WriteConfig();
141
142    printf("==================================================================\n");
143    printf("===========    RUNNING ANALYSIS TRAIN %s IN %s MODE   ==========\n", train_name.Data(),smode.Data());
144    printf("==================================================================\n");
145    printf("=  Configuring analysis train for:                               =\n");
146    if (iAODanalysis) printf("=  AOD analysis                                                  =\n");
147    else              printf("=  ESD analysis                                                  =\n");
148    if (usePhysicsSelection)   printf("=  Physics selection                                                =\n");
149    if (useTender)    printf("=  TENDER                                                        =\n");
150    if (iPWG3hfe)       printf("=  PWG3 electrons                                                =\n");
151    if (iPWG3JPSIfilter) printf("=  PWG3 j/psi filter                                             =\n");
152    if (iPWG3JPSI)      printf("=  PWG3 j/psi                                                    =\n");
153    if (iPWG3d2h)     printf("=  PWG3 D -> hadrons tasks                                      =\n");
154    if (iPWG3MuonTrain) printf("=  PWG3 muon train                                               =\n");
155    printf("==================================================================\n");
156    printf(":: use physics selection: %d\n", (UInt_t)usePhysicsSelection);
157    printf(":: use xrootd tweaks:     %d\n", (UInt_t)useFastReadOption);
158    printf(":: use overwrite xml    : %d\n", (UInt_t)useOverwriteMode);
159    printf(":: use merge via JDL:     %d\n", (UInt_t)useMergeViaJDL);
160    printf(":: use MC truth:          %d\n", (UInt_t)useMC);
161    printf(":: use KINE filter:       %d\n", (UInt_t)useKFILTER);
162    printf(":: use track references:  %d\n", (UInt_t)useTR);
163    printf(":: use tags:              %d\n", (UInt_t)useTAGS);
164    printf(":: use AOD tags:          %d\n", (UInt_t)useAODTAGS);
165    printf(":: use debugging:         %d\n", (UInt_t)useDBG);
166    printf(":: use PAR files:         %d\n", (UInt_t)usePAR);
167    printf(":: use AliEn plugin:      %d\n", (UInt_t)usePLUGIN);
168
169    //==========================================================================
170    // Connect to back-end system
171 //   if (!Connect(smode)) {
172 //      ::Error("AnalysisTrain", "Could not connect to %s back-end", analysis_mode);
173 //      return;
174 //   }   
175
176    // Load common libraries and set include path
177    if (!LoadCommonLibraries(smode)) {
178       ::Error("AnalysisTrain", "Could not load common libraries");
179       return;
180    }
181     
182    // Make the analysis manager and connect event handlers
183    AliAnalysisManager *mgr  = new AliAnalysisManager("Analysis Train", "Production train");
184    if (saveProofToAlien) mgr->SetSpecialOutputLocation(proof_outdir);
185    if (!strcmp(plugin_mode, "test")) mgr->SetNSysInfo(1);
186    // Load analysis specific libraries
187    if (!LoadAnalysisLibraries(smode)) {
188       ::Error("AnalysisTrain", "Could not load analysis libraries");
189       return;
190    }   
191
192    // Create input handler (input container created automatically)
193    if (iAODanalysis) {
194    // AOD input handler
195       AliAODInputHandler *aodH = new AliAODInputHandler();
196       if (iPWG3d2h) aodH->AddFriend("AliAOD.VertexingHF.root");
197       mgr->SetInputEventHandler(aodH);
198    } else {   
199    // ESD input handler
200       AliESDInputHandler *esdHandler = new AliESDInputHandler();
201       if (useTAGS) esdHandler->SetReadTags();
202       mgr->SetInputEventHandler(esdHandler);       
203    }
204    // Monte Carlo handler
205    if (useMC && !iAODanalysis) {
206       AliMCEventHandler* mcHandler = new AliMCEventHandler();
207       mgr->SetMCtruthEventHandler(mcHandler);
208       mcHandler->SetReadTR(useTR); 
209    }   
210    // AOD output container, created automatically when setting an AOD handler
211    if (iAODhandler) {
212       // AOD output handler
213       AliAODHandler* aodHandler   = new AliAODHandler();
214       aodHandler->SetOutputFileName("AliAOD.root");
215       mgr->SetOutputEventHandler(aodHandler);
216       if (iAODanalysis) {
217          aodHandler->SetFillAOD(kFALSE);
218          aodHandler->SetCreateNonStandardAOD();
219 //         if (iPWG3vertexing) aodHandler->SetOutputFileName("AliAOD.VertexingHF.root");
220       } 
221    }
222    // Debugging if needed
223    if (useDBG) mgr->SetDebugLevel(3);
224    if (saveCanvases) mgr->SetSaveCanvases(kTRUE);
225
226    //==========================================================================
227    // Create the chain. In this example it is created only from ALIEN files but
228    // can be done to work in batch or grid mode as well.
229    TChain *chain = CreateChain(smode, plugin_mode);
230         
231    //==========================================================================
232    // Load the tasks configuration macros for all wagons. These files are supposed now to be
233    // in the current workdir, but in AliEn they will be in the file catalog, 
234    // mapped from AliRoot and pecified in the jdl input list.
235     
236    // For now connection to top input container and common AOD output container
237    // is done in this macro, but in future these containers will be connected
238    // from each task configuration macro.
239                                                                                                                                            
240    AddAnalysisTasks();                                                                                                                     
241                                                                                                                                            
242    // Run the analysis                                                                                                                     
243    //                                                                                                                                      
244    if (usePLUGIN) {                                                                                                                        
245       AliAnalysisGrid *alienHandler = CreateAlienHandler(plugin_mode);                                                                     
246       AliAnalysisManager::GetAnalysisManager()->SetGridHandler(alienHandler);                                                              
247    }                                                                                                                                       
248                                                                                                                                            
249    if (mgr->InitAnalysis()) {                                                                                                              
250       mgr->PrintStatus();                                                                                                                  
251       if (saveTrain || strlen(config_file)) gSystem->ChangeDirectory(train_name);                                                          
252       StartAnalysis(smode, chain);                                                                                                         
253    }                                                                                                                                       
254 }                                                                                                                                          
255                                                                                                                                             
256 //______________________________________________________________________________                                                           
257 void AddAnalysisTasks()                                                                                                                    
258 {                                                                                                                                          
259 // Add all analysis task wagons to the train                                                                                               
260    AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();                                                                     
261
262   //
263   // Tender and supplies. Needs to be called for every event.
264   //
265    if (useTender) {
266       gROOT->LoadMacro("$ALICE_ROOT/TENDER/TenderSupplies/AddTaskTender.C");
267       // IF V0 tender needed, put kTRUE below
268       AliAnalysisTaskSE *tender = AddTaskTender(useV0tender);
269 //      tender->SetDebugLevel(2);
270    }
271
272    if (usePhysicsSelection) {
273    // Physics selection task
274       gROOT->LoadMacro("$ALICE_ROOT/OADB/macros/AddTaskPhysicsSelection.C");
275       mgr->RegisterExtraFile("event_stat.root");
276       AliPhysicsSelectionTask *physSelTask = AddTaskPhysicsSelection(useMC,useBKrejection);
277    }
278    
279    // AOD tags
280    if (useAODTAGS) {
281       AliAnalysisTaskTagCreator* tagTask = new AliAnalysisTaskTagCreator("AOD Tag Creator");
282       mgr->AddTask(tagTask);
283       AliAnalysisDataContainer *coutTags = mgr->CreateContainer("cTag",  TTree::Class(), 
284                                            AliAnalysisManager::kOutputContainer, "AOD.tag.root");
285       mgr->ConnectInput (tagTask, 0, mgr->GetCommonInputContainer());
286       mgr->ConnectOutput(tagTask, 1, coutTags);
287    }   
288     
289
290 // ********** PWG3 wagons ******************************************************
291    AliAnalysisManager::SetCommonFileName("PWG3histograms.root");
292            
293    // PWG3 electrons
294    if (iPWG3hfe) {
295       gROOT->LoadMacro("$ALICE_ROOT/PWG3/hfe/AddTaskHFE.C");
296       AliAnalysisTaskHFE *taskHFE = AddTaskHFE();
297       if (!taskHFE) ::Warning("AnalysisTrainNew", "AliAnalysisTaskHFE cannot run for this train conditions - EXCLUDED");
298    }   
299
300    // PWG3 JPSI filtering
301    if (iPWG3JPSIfilter) {
302       gROOT->LoadMacro("$ALICE_ROOT/PWG3/dielectron/macros/AddTaskJPSIFilter.C");
303       AliAnalysisTask *taskJPSIfilter = AddTaskJPSIFilter();
304       if (!taskJPSIfilter) ::Warning("AnalysisTrainNew", "AliAnalysisTaskDielectronFilter cannot run for this train conditions - EXCLUDED");
305       else mgr->RegisterExtraFile("AliAOD.Dielectron.root");
306    }   
307
308    // PWG3 JPSI
309    if (iPWG3JPSI) {
310       gROOT->LoadMacro("$ALICE_ROOT/PWG3/dielectron/macros/AddTaskJPSI.C");
311       AliAnalysisTask *taskJPSI = AddTaskJPSI();
312       if (!taskJPSI) ::Warning("AnalysisTrainNew", "AliAnalysisTaskMultiDielectron cannot run for this train conditions - EXCLUDED");
313    }   
314
315    // PWG3 D2h
316    if (iPWG3d2h) {
317       gROOT->LoadMacro("$ALICE_ROOT/PWG3/vertexingHF/AddD2HTrain.C");
318       Bool_t readMC = (runOnData!=0 ? kFALSE : kTRUE);
319       AddD2HTrain(readMC);                                 
320    }   
321
322    // PWG3 muon
323    if (iPWG3MuonTrain) {
324       gROOT->LoadMacro("$ALICE_ROOT/PWG3/muon/AddPWG3MuonTrain.C");
325       // iESDAnalysis, iAODAnalysis -> flags to select if the train is AOD or ESD based
326       // iMuonDistributions, iSingleMuonANAlysis -> flags to switch on/off analysis wagons
327       Int_t isESDAnalysis = (iAODanalysis)?0:1;
328       Int_t isAODAnalysis = (iAODanalysis)?1:0;
329       Int_t addMuonDistributions = 1;
330       Int_t addSingleMuonAnalysis = 1;
331       Int_t addMuonHFAnalysis = 1;
332       Int_t ntaskmuon = AddPWG3MuonTrain(isESDAnalysis,isAODAnalysis,addMuonDistributions,addSingleMuonAnalysis,addMuonHFAnalysis);
333       printf("Added %d muon tasks\n", ntaskmuon);
334    }   
335       
336 }
337
338 //______________________________________________________________________________
339 void StartAnalysis(const char *mode, TChain *chain) {
340 // Start analysis.
341    Int_t imode = -1;
342    AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
343    if (!strcmp(mode, "LOCAL")) imode = 0;
344    if (!strcmp(mode, "PROOF")) imode = 1;
345    if (!strcmp(mode, "GRID"))  imode = 2;
346    switch (imode) {
347       case 0:
348          if (!chain) {
349             ::Error("AnalysisTrainNew.C::StartAnalysis", "Cannot create the chain");
350             return;
351          }   
352          mgr->StartAnalysis(mode, chain);
353          return;
354       case 1:
355          if (!proof_dataset.Length()) {
356             ::Error("AnalysisTrainNew.C::StartAnalysis", "proof_dataset is empty");
357             return;
358          }   
359          mgr->StartAnalysis(mode, proof_dataset, 1000);
360          return;
361       case 2:
362          if (usePLUGIN) {
363             if (!mgr->GetGridHandler()) {
364                ::Error("AnalysisTrainNew.C::StartAnalysis", "Grid plugin not initialized");
365                return;
366             }   
367             mgr->StartAnalysis("grid");
368          } else {
369             if (!chain) {
370                ::Error("AnalysisTrainNew.C::StartAnalysis", "Cannot create the chain");
371                return;
372             }   
373             mgr->StartAnalysis(mode, chain);
374          }   
375          return;
376    }      
377 }          
378     
379 //______________________________________________________________________________
380 void CheckModuleFlags(const char *mode) {
381 // Checks selected modules and insure compatibility
382    Int_t imode = -1;
383    if (!strcmp(mode, "LOCAL")) imode = 0;
384    if (!strcmp(mode, "PROOF")) imode = 1;
385    if (!strcmp(mode, "GRID"))  imode = 2;
386    if (imode==1) {
387       if (!usePAR) {
388          ::Info("AnalysisTrainNew.C::CheckModuleFlags", "PAR files enabled due to PROOF analysis");
389          usePAR = kTRUE;
390       }   
391    }  
392    if (imode != 2) {
393       ::Info("AnalysisTrainNew.C::CheckModuleFlags", "AliEn plugin disabled since not in GRID mode");
394       usePLUGIN = kFALSE; 
395    }   
396    if (iAODanalysis) {
397    // AOD analysis
398       if (useMC)
399          ::Info("AnalysisTrainNew.C::CheckModuleFlags", "MC usage disabled in analysis on AOD's");
400       if (useAODTAGS)
401          ::Info("AnalysisTrainNew.C::CheckModuleFlags", "AOD tags usage disabled in analysis on AOD's");
402       useMC = kFALSE;
403       useTR = kFALSE;
404       useAODTAGS = kFALSE;
405    } else {   
406    // ESD analysis
407       if (!useMC) useTR = kFALSE;
408       if (!useTR) {
409          ::Info("AnalysisTrainNew.C::CheckModuleFlags", "iPWG2evchar disabled if not reading track references");
410          iPWG2evchar = 0;
411       }   
412    }
413    if (useKFILTER && !useMC) useKFILTER = kFALSE;
414    if (useAODTAGS && !iAODhandler) useAODTAGS = kFALSE;
415 }
416
417 //______________________________________________________________________________
418 Bool_t Connect(const char *mode) {
419 // Connect <username> to the back-end system.
420    Int_t imode = -1;
421    if (!strcmp(mode, "LOCAL")) imode = 0;
422    if (!strcmp(mode, "PROOF")) imode = 1;
423    if (!strcmp(mode, "GRID"))  imode = 2;
424    TString username = gSystem->Getenv("alien_API_USER");
425    switch (imode) {
426       case 0:
427          break;
428       case 1:
429          if  (!username.Length()) {
430             ::Error(Form("AnalysisTrainNew.C::Connect <%s>", mode), "Make sure you:\n \
431                            1. Have called: alien-token-init <username>\n \
432                            2. Have called: >source /tmp/gclient_env_$UID");
433             return kFALSE;
434          }
435          ::Info("AnalysisTrainNew.C::Connect", "Connecting user <%s> to PROOF cluster <%s>", 
436                 username.Data(), proof_cluster.Data());
437          gEnv->SetValue("XSec.GSI.DelegProxy", "2");
438 //         TProof::Open(Form("%s@%s:31093", username.Data(), proof_cluster.Data()));       
439          TProof::Open(Form("%s@%s", username.Data(), proof_cluster.Data()));       
440          if (!gProof) {
441             if (strcmp(gSystem->Getenv("XrdSecGSISRVNAMES"), "lxfsrd0506.cern.ch"))
442                ::Error(Form("AnalysisTrainNew.C::Connect <%s>", mode), "Environment XrdSecGSISRVNAMES different from lxfsrd0506.cern.ch");
443             return kFALSE;
444          }
445          TGrid::Connect("alien://");
446          if (gGrid) {
447             TString homedir = gGrid->GetHomeDirectory();
448             TString workdir = homedir + train_name;
449             if (!gGrid->Cd(workdir)) {
450                gGrid->Cd(homedir);
451                if (gGrid->Mkdir(workdir)) {
452                   gGrid->Cd(train_name);
453                   ::Info("AnalysisTrainNew::Connect()", "Directory %s created", gGrid->Pwd());
454                }
455             }
456             gGrid->Mkdir("proof_output");
457             gGrid->Cd("proof_output");
458             proof_outdir = Form("alien://%s", gGrid->Pwd());
459          }   
460          break;
461       case 2:      
462          if (usePLUGIN && !gSystem->Getenv("alien_CLOSE_SE")) {
463             ::Error(Form("AnalysisTrainNew.C::Connect <%s>", mode), 
464                            "When using the AliEn plugin it is preferable to define the \
465                            variable alien_CLOSE_SE in your environment.");
466             return kFALSE;
467          }
468          ::Info("AnalysisTrainNew.C::Connect", "Connecting user <%s> to AliEn ...", 
469                 username.Data());
470          TGrid::Connect("alien://");
471          if (!gGrid || !gGrid->IsConnected()) return kFALSE;
472          break;
473       default:
474          ::Error("AnalysisTrainNew.C::Connect", "Unknown run mode: %s", mode);
475          return kFALSE;
476    }
477    ::Info("AnalysisTrainNew.C::Connect","Connected in %s mode", mode);
478    return kTRUE;
479 }
480
481 //______________________________________________________________________________
482 Bool_t LoadCommonLibraries(const char *mode)
483 {
484 // Load common analysis libraries.
485    Int_t imode = -1;
486    if (!strcmp(mode, "LOCAL")) imode = 0;
487    if (!strcmp(mode, "PROOF")) imode = 1;
488    if (!strcmp(mode, "GRID"))  imode = 2;
489    if (!gSystem->Getenv("ALICE_ROOT")) {
490       ::Error("AnalysisTrainNew.C::LoadCommonLibraries", "Analysis train requires that analysis libraries are compiled with a local AliRoot"); 
491       return kFALSE;
492    }   
493    Bool_t success = kTRUE;
494    // ROOT libraries
495    gSystem->Load("libTree");
496    gSystem->Load("libGeom");
497    gSystem->Load("libVMC");
498    gSystem->Load("libPhysics");
499    gSystem->Load("libMinuit");
500    
501    // Load framework classes. Par option ignored here.
502    switch (imode) {
503       case 0:
504       case 2:
505          if (useCPAR) {
506             success &= LoadLibrary("STEERBase", mode, kTRUE);
507             success &= LoadLibrary("ESD", mode, kTRUE);
508             success &= LoadLibrary("AOD", mode, kTRUE);
509             success &= LoadLibrary("ANALYSIS", mode, kTRUE);
510             success &= LoadLibrary("ANALYSISalice", mode, kTRUE);
511             if (useCORRFW) success &= LoadLibrary("CORRFW", mode, kTRUE);
512          } else {   
513             success &= LoadLibrary("libSTEERBase.so", mode);
514             success &= LoadLibrary("libESD.so", mode);
515             success &= LoadLibrary("libAOD.so", mode);
516             success &= LoadLibrary("libANALYSIS.so", mode);
517             success &= LoadLibrary("libANALYSISalice.so", mode);
518             if (useCORRFW) success &= LoadLibrary("libCORRFW.so", mode);
519             gROOT->ProcessLine(".include $ALICE_ROOT/include");
520          }   
521          break;
522       case 1:
523          Int_t ires = -1;
524          if (useAFPAR && !gSystem->AccessPathName(AFversion)) ires = gProof->UploadPackage(AFversion);
525          if (ires < 0) {
526             success &= LoadLibrary("STEERBase", mode);
527             success &= LoadLibrary("ESD", mode);
528             success &= LoadLibrary("AOD", mode);
529             success &= LoadLibrary("ANALYSIS", mode);
530             success &= LoadLibrary("ANALYSISalice", mode);
531             if (useCORRFW) success &= LoadLibrary("CORRFW", mode);
532          } else { 
533             ires = gProof->EnablePackage(AFversion);
534             if (ires<0) success = kFALSE;
535             if (useCORRFW) success &= LoadLibrary("CORRFW", mode);
536          }
537          break;         
538       default:
539          ::Error("AnalysisTrainNew.C::LoadCommonLibraries", "Unknown run mode: %s", mode);
540          return kFALSE;
541    }
542    if (success) {
543       ::Info("AnalysisTrainNew.C::LoadCommodLibraries", "Load common libraries:    SUCCESS");
544       ::Info("AnalysisTrainNew.C::LoadCommodLibraries", "Include path for Aclic compilation:\n%s",
545               gSystem->GetIncludePath());
546    } else {           
547       ::Info("AnalysisTrainNew.C::LoadCommodLibraries", "Load common libraries:    FAILED");
548    }   
549       
550    return success;
551 }
552
553 //______________________________________________________________________________
554 Bool_t LoadAnalysisLibraries(const char *mode)
555 {
556 // Load common analysis libraries.
557    Bool_t success = kTRUE;
558    if (useTender) {
559       if (!LoadLibrary("TENDER", mode, kTRUE) ||
560           !LoadLibrary("TENDERSupplies", mode, kTRUE)) return kFALSE;
561    }       
562    if (iPWG3MuonTrain) {
563       if (!LoadLibrary("PWG3base", mode, kTRUE) ||
564           !LoadLibrary("PWG3muon", mode, kTRUE)) return kFALSE;
565    }   
566    // PWG3 Vertexing HF
567    if (iPWG3d2h) {
568       if (!LoadLibrary("PWG3base", mode, kTRUE) ||
569           !LoadLibrary("PWG3vertexingHF", mode, kTRUE)) return kFALSE;
570    }   
571    // PWG3 hfe
572    if (iPWG3hfe) {
573       if (!LoadLibrary("PWG3hfe", mode, kTRUE)) return kFALSE;
574    }   
575    // PWG3 dielectron
576    if (iPWG3JPSIfilter || iPWG3JPSI) {
577       if (!LoadLibrary("PWG3dielectron", mode, kTRUE)) return kFALSE;
578    }   
579    
580    ::Info("AnalysisTrainNew.C::LoadAnalysisLibraries", "Load other libraries:   SUCCESS");
581    return kTRUE;
582 }
583
584 //______________________________________________________________________________
585 Bool_t LoadLibrary(const char *module, const char *mode, Bool_t rec=kFALSE)
586 {
587 // Load a module library in a given mode. Reports success.
588    Int_t imode = -1;
589    Int_t result;
590    TString smodule(module);
591    if (!strcmp(mode, "LOCAL")) imode = 0;
592    if (!strcmp(mode, "PROOF")) imode = 1;
593    if (!strcmp(mode, "GRID"))  imode = 2;
594    TString mod(module);
595    if (!mod.Length()) {
596       ::Error("AnalysisTrainNew.C::LoadLibrary", "Empty module name");
597       return kFALSE;
598    }   
599    // If a library is specified, just load it
600    if (smodule.EndsWith(".so")) {
601       mod.Remove(mod.Index(".so"));
602       result = gSystem->Load(mod);
603       if (result < 0) {
604          ::Error("AnalysisTrainNew.C::LoadLibrary", "Could not load library %s", module);
605          return kFALSE;
606       }
607       if (rec) anaLibs += Form("%s.so ",mod.Data()); 
608       return kTRUE;
609    } 
610    // Check if the library is already loaded
611    if (strlen(gSystem->GetLibraries(module, "", kFALSE)) > 0)
612       return kTRUE;    
613    switch (imode) {
614       case 0:
615       case 2:
616          if (usePAR) {
617             result = SetupPar(module);
618             if (rec) anaPars += Form("%s.par ", module);
619          } else {
620             result = gSystem->Load(Form("lib%s", module));
621             if (rec) anaLibs += Form("lib%s.so ", module);
622          }   
623          break;
624       case 1:
625          result = gProof->UploadPackage(module);
626          if (result<0) {
627             result = gProof->UploadPackage(gSystem->ExpandPathName(Form("$ALICE_ROOT/%s.par", module)));
628             if (result<0) {
629                ::Error("AnalysisTrainNew.C::LoadLibrary", "Could not find module %s.par in current directory nor in $ALICE_ROOT", module);
630                return kFALSE;
631             }
632          }   
633          result = gProof->EnablePackage(module);
634          break;
635       default:
636          return kFALSE;
637    }         
638    if (result < 0) {
639       ::Error("AnalysisTrainNew.C::LoadLibrary", "Could not load module %s", module);
640       return kFALSE;
641    }
642    return kTRUE;
643 }           
644
645
646 //______________________________________________________________________________
647 TChain *CreateChain(const char *mode, const char *plugin_mode)
648 {
649 // Create the input chain
650    Int_t imode = -1;
651    if (!strcmp(mode, "LOCAL")) imode = 0;
652    if (!strcmp(mode, "PROOF")) imode = 1;
653    if (!strcmp(mode, "GRID"))  imode = 2;
654    TChain *chain = NULL;
655    // Local chain
656    switch (imode) {
657       case 0:
658          if (iAODanalysis) {
659             if (!local_xmldataset.Length()) {
660                // Local AOD
661                chain = new TChain("aodTree");
662                if (gSystem->AccessPathName("data/AliAOD.root")) 
663                   ::Error("AnalysisTrainNew.C::CreateChain", "File: AliAOD.root not in ./data dir");
664                else {
665                   if (!saveTrain) chain->Add("data/AliAOD.root");
666                   else            chain->Add("../data/AliAOD.root");
667                }   
668             } else {
669                // Interactive AOD
670                chain = CreateChainSingle(local_xmldataset, "aodTree");
671             }
672          } else {      
673             if (!local_xmldataset.Length()) {
674                // Local ESD
675                chain = new TChain("esdTree");
676                if (gSystem->AccessPathName("data/AliESDs.root")) 
677                   ::Error("AnalysisTrainNew.C::CreateChain", "File: AliESDs.root not in ./data dir");
678                else {
679                   if (!saveTrain) chain->Add("data/AliESDs.root");
680                   else            chain->Add("../data/AliESDs.root");
681                }   
682             } else {
683                // Interactive ESD
684                chain = CreateChainSingle(local_xmldataset, "esdTree");
685             }   
686          }
687          break;
688       case 1:
689          break;
690       case 2:
691          if (usePLUGIN) {
692 //            AliAnalysisGrid *alienHandler = CreateAlienHandler(plugin_mode);
693 //            AliAnalysisManager::GetAnalysisManager()->SetGridHandler(alienHandler);
694          } else {
695             TString           treeName = "esdTree";
696             if (iAODanalysis) treeName = "aodTree";
697             chain = CreateChainSingle("wn.xml", treeName);
698          }
699          break;      
700       default:   
701    }
702    if (chain && chain->GetNtrees()) return chain;
703    return NULL;
704 }   
705
706 //______________________________________________________________________________
707 TChain* CreateChainSingle(const char* xmlfile, const char *treeName)
708 {
709    printf("*******************************\n");
710    printf("*** Getting the ESD Chain   ***\n");
711    printf("*******************************\n");
712    TAlienCollection * myCollection  = TAlienCollection::Open(xmlfile);
713
714    if (!myCollection) {
715       ::Error("AnalysisTrainNew.C::CreateChainSingle", "Cannot create an AliEn collection from %s", xmlfile) ;
716       return NULL ;
717    }
718
719    TChain* chain = new TChain(treeName);
720    myCollection->Reset() ;
721    while ( myCollection->Next() ) chain->Add(myCollection->GetTURL("")) ;
722    chain->ls();
723    return chain;
724 }
725
726 //______________________________________________________________________________
727 Int_t SetupPar(char* pararchivename)
728 {
729    if (!pararchivename || !strlen(pararchivename)) return -1;
730    char processline[1024];
731    if (gSystem->AccessPathName(Form("%s.par", pararchivename))) {
732       if (!gSystem->AccessPathName(Form("%s/%s.par", gSystem->Getenv("ALICE_ROOT"),pararchivename))) {
733          ::Info("AnalysisTrainNew.C::SetupPar", "Getting %s.par from $ALICE_ROOT", pararchivename);
734          TFile::Cp(gSystem->ExpandPathName(Form("$ALICE_ROOT/%s.par", pararchivename)), 
735                    Form("%s.par",pararchivename));
736       } else {
737          ::Error("AnalysisTrainNew.C::SetupPar", "Cannot find %s.par", pararchivename);
738          return -1;
739       }   
740    }
741    if (usePLUGIN && saveTrain) gSystem->Exec(Form("ln -s ../%s.par %s",pararchivename, train_name.Data()));
742    gSystem->Exec(Form("tar xvzf %s.par", pararchivename));
743
744    TString ocwd = gSystem->WorkingDirectory();
745    if (!gSystem->ChangeDirectory(pararchivename)) return -1;
746         
747    // check for BUILD.sh and execute
748    if (!gSystem->AccessPathName("PROOF-INF/BUILD.sh")) {
749       printf("*******************************\n");
750       printf("*** Building PAR archive    ***\n");
751       printf("*******************************\n");          
752       if (gSystem->Exec("PROOF-INF/BUILD.sh")) {
753          Error("runProcess","Cannot Build the PAR Archive! - Abort!");
754          return -1;
755       }
756    }
757
758         // check for SETUP.C and execute
759         if (!gSystem->AccessPathName("PROOF-INF/SETUP.C")) {
760             printf("*******************************\n");
761             printf("*** Setup PAR archive       ***\n");
762             printf("*******************************\n");
763             gROOT->Macro("PROOF-INF/SETUP.C");
764         }       
765         if (!gSystem->ChangeDirectory(ocwd.Data())) return -1;
766    return 0;
767 }
768
769 //______________________________________________________________________________
770 AliAnalysisAlien* CreateAlienHandler(const char *plugin_mode)
771 {
772 // Check if user has a valid token, otherwise make one. This has limitations.
773 // One can always follow the standard procedure of calling alien-token-init then
774    AliAnalysisAlien *plugin = new AliAnalysisAlien();
775 // Set the run mode (can be "full", "test", "offline", "submit" or "terminate")
776    plugin->SetRunMode(plugin_mode);
777    if (useProductionMode) {
778       plugin->SetProductionMode();
779       plugin->AddDataFile(data_collection);
780    }   
781       
782    if (!outputSingleFolder.IsNull()) {
783       plugin->SetOutputSingleFolder(outputSingleFolder);
784       plugin->SetOutputToRunNo();
785    }   
786    plugin->SetJobTag(job_tag);
787    plugin->SetNtestFiles(2);
788    plugin->SetCheckCopy(kFALSE);
789    plugin->SetOneStageMerging(kTRUE);
790 // Set versions of used packages
791    plugin->SetAPIVersion("V1.1x");
792    plugin->SetROOTVersion(root_version);
793    plugin->SetAliROOTVersion(aliroot_version);
794 // Declare input data to be processed.
795 // Method 1: Create automatically XML collections using alien 'find' command.
796 // Define production directory LFN
797    plugin->SetGridDataDir(alien_datadir);
798 // Set data search pattern
799    plugin->SetDataPattern(data_pattern);
800    if (!useProductionMode) {
801       if (runOnData) {
802          plugin->SetRunPrefix("000");
803       }   
804 //   if (!iAODanalysis) plugin->SetRunRange(run_range[0], run_range[1]);
805       for (Int_t i=0; i<10; i++) {
806          if (run_numbers[i]==0) break;
807          plugin->AddRunNumber(run_numbers[i]);
808       }   
809    }   
810 // Define alien work directory where all files will be copied. Relative to alien $HOME.
811    plugin->SetGridWorkingDir(grid_workdir);
812 // Declare alien output directory. Relative to working directory.
813    if (alien_outdir.IsNull()) alien_outdir = Form("output_%s",train_name.Data());
814    plugin->SetGridOutputDir(alien_outdir);
815
816    TString ana_sources = "";
817    TString ana_add = "";
818    if (usePAR && anaPars.Length()) {
819       printf("%s\n", anaPars.Data());
820       TObjArray *arr;
821       TObjString *objstr;
822       arr = anaPars.Tokenize(" ");
823       TIter next(arr);
824       while ((objstr=(TObjString*)next())) plugin->EnablePackage(objstr->GetString());
825       delete arr;
826    } 
827    
828 // Declare the analysis source files names separated by blancs. To be compiled runtime
829 // using ACLiC on the worker nodes.
830    ana_sources = ana_sources.Strip();
831 // Declare all libraries (other than the default ones for the framework. These will be
832 // loaded by the generated analysis macro. Add all extra files (task .cxx/.h) here.
833    anaLibs     = anaLibs.Strip();   
834    if (ana_sources.Length()) plugin->SetAnalysisSource(ana_sources);
835    if (anaLibs.Length())     plugin->SetAdditionalLibs(anaLibs);
836      
837 // Declare the output file names separated by blancs.
838 // (can be like: file.root or file.root@ALICE::Niham::File)
839    plugin->SetDefaultOutputs();
840    plugin->SetMergeExcludes(mergeExclude);
841    plugin->SetMaxMergeFiles(maxMergeFiles);
842    plugin->SetNrunsPerMaster(nRunsPerMaster);
843 // Optionally define the files to be archived.
844 //   plugin->SetOutputArchive("log_archive.zip:stdout,stderr@ALICE::NIHAM::File root_archive.zip:AliAOD.root,AOD.tag.root@ALICE::NIHAM::File");
845    
846    
847    // Put default output files to archive
848    TString listhists = "";
849    TString listaods  = "";
850    AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
851    TIter next(mgr->GetOutputs());
852    AliAnalysisDataContainer *output;
853    while ((output=(AliAnalysisDataContainer*)next())) {
854       const char *filename = output->GetFileName();
855       if (!(strcmp(filename, "default"))) {
856          if (!mgr->GetOutputEventHandler()) continue;
857          filename = mgr->GetOutputEventHandler()->GetOutputFileName();
858          if (listaods.Length()) listaods += ",";
859          listaods += filename;
860          listaods += ",";
861          listaods += "pyxsec_hists.root";
862       } else {
863          if (!strcmp(filename, "pyxsec_hists.root")) continue;
864          if (listhists.Contains(filename)) continue;
865          if (listhists.Length()) listhists += ",";
866          listhists += filename;
867       }
868    }
869    if (mgr->GetExtraFiles().Length()) {
870       if (listaods.Length()) listaods += ",";
871       listaods += mgr->GetExtraFiles();
872       listaods.ReplaceAll(" ", ",");
873    }
874    if (listhists.Length()) listhists = Form("hist_archive.zip:%s@%s", listhists.Data(), outputStorages.Data());
875    if (listaods.Length())  listaods  = Form("aod_archive.zip:%s@%s", listaods.Data(), outputStorages.Data());
876    if (!listhists.Length() && !listaods.Length()) {
877       ::Fatal("AnalysisTrainNew", "No task output !");
878    }
879    TString outputArchive = Form("log_archive.zip:stderr@%s", outputStorages.Data());
880    if (listaods.Length()) {
881       outputArchive += " ";
882       outputArchive += listaods;
883    }   
884    if (listhists.Length()) {
885       outputArchive += " ";
886       outputArchive += listhists;
887    }   
888 // Set friends
889 //   if (iAODanalysis && iPWG3d2h) 
890 //      plugin->SetFriendChainName("AliAOD.VertexingHF.root");
891 //   plugin->SetOutputArchive(outputArchive);
892 // Optionally set a name for the generated analysis macro (default MyAnalysis.C)
893    plugin->SetAnalysisMacro(Form("%s.C", train_name.Data()));
894 // Optionally set a name for the generated validation script
895    plugin->SetValidationScript("FILTERvalidation.sh");
896 // Optionally set maximum number of input files/subjob (default 100, put 0 to ignore)
897    plugin->SetSplitMaxInputFileNumber(nFilesPerJob);
898 // Optionally set number of failed jobs that will trigger killing waiting sub-jobs.
899 //   plugin->SetMaxInitFailed(5);
900 // Optionally modify the number of replicas
901    plugin->SetNumberOfReplicas(4);
902 // Optionally resubmit threshold.
903 //   plugin->SetMasterResubmitThreshold(90);
904 // Optionally set time to live (default 30000 sec)
905    plugin->SetTTL(70000);
906 // Optionally set input format (default xml-single)
907    plugin->SetInputFormat("xml-single");
908 // Optionally modify the name of the generated JDL (default analysis.jdl)
909    plugin->SetJDLName(Form("%s.jdl", train_name.Data()));
910 // Optionally modify the executable name (default analysis.sh)
911    plugin->SetExecutable(Form("%s.sh", train_name.Data()));
912 // Optionally modify job price (default 1)
913    plugin->SetPrice(1);      
914 // Merge via JDL
915    plugin->SetMergeViaJDL(useMergeViaJDL);
916 // Use fastread option
917    plugin->SetFastReadOption(useFastReadOption);
918 // UseOverwrite mode
919    plugin->SetOverwriteMode(useOverwriteMode);   
920    plugin->SetExecutableCommand("aliroot -b -q");
921 // Optionally modify split mode (default 'se')    
922    plugin->SetSplitMode("se");
923    return plugin;
924 }
925
926 //______________________________________________________________________________
927 void WriteConfig()
928 {
929 // Write train configuration in a file. The file name has the format:
930 // train_[trainName]_ddMonthyyyy_time.C
931    if (useDATE) {
932       gSystem->Exec("date +%d%b%Y_%Hh%M > date.tmp");
933       ifstream fdate("date.tmp");
934       if (!fdate.is_open()) {
935          ::Error("AnalysisTrainNew.C::Export","Could not generate file name");
936          return;
937       }
938       const char date[64];
939       fdate.getline(date,64);
940       fdate.close();
941       gSystem->Exec("rm date.tmp");
942       train_name = Form("%s_%s", train_name.Data(), date);
943    }   
944    TString cdir = gSystem->WorkingDirectory();
945    gSystem->MakeDirectory(train_name);
946    gSystem->ChangeDirectory(train_name);
947    ofstream out;
948    out.open(Form("%sConfig.C",train_name.Data()), ios::out); 
949    if (out.bad()) {
950       ::Error("AnalysisTrainNew.C::Export", "Cannot open ConfigTrain.C for writing");
951       return;
952    }
953    out << "{" << endl;
954    out << "   train_name      = " << "\"" << train_name.Data() << "\";" << endl;
955    out << "   proof_cluster   = " << "\"" << proof_cluster.Data() << "\";" << endl;
956    out << "   useAFPAR        = " << useAFPAR << ";" << endl;
957    if (useAFPAR) 
958       out << "   AFversion       = " << AFversion.Data() << ";" << endl;
959    out << "   proof_dataset   = " << "\"" << proof_dataset.Data() << "\";" << endl;
960    out << "   usePLUGIN       = " << usePLUGIN << ";" << endl;
961    out << "   usePAR          = " << usePAR << ";" << endl;
962    out << "   useCPAR         = " << useCPAR << ";" << endl;
963    out << "   root_version    = " << "\"" << root_version.Data() << "\";" << endl;
964    out << "   aliroot_version = " << "\"" << aliroot_version.Data() << "\";" << endl;
965    out << "   alien_datadir   = " << "\"" << alien_datadir.Data() << "\";" << endl;
966    if (!alien_outdir.Length()) alien_outdir = Form("output_%s",train_name.Data());
967    out << "   alien_outdir    = " << "\"" << alien_outdir.Data() << "\";" << endl;
968    out << "   maxMergeFiles   = " << maxMergeFiles << ";" << endl;
969    out << "   mergeExclude    = " << "\"" << mergeExclude.Data() << "\";" << endl;
970    out << "   nRunsPerMaster  = " << nRunsPerMaster << ";" << endl;
971    out << "   nFilesPerJob    = " << nFilesPerJob << ";" << endl;
972 //   for (Int_t i=0; i<10; i++) {
973 //      if (run_numbers[i]) 
974 //         out << "   run_numbers[" << i << "]  = " << run_numbers[i] << ";" << endl;
975 //   }
976 //   out << "   run_range[0]    = " << run_range[0] << ";" << endl;
977 //   out << "   run_range[1]    = " << run_range[1] << ";" << endl;
978    out << "   usePhysicsSelection = " << usePhysicsSelection << ";" << endl;
979    out << "   useTender       = " << useTender << ";" << endl;
980    out << "   useMergeViaJDL  = " << useMergeViaJDL << ";" << endl;
981    out << "   useOverwriteMode  = " << useOverwriteMode << ";" << endl;
982    out << "   useFastReadOption = " << useFastReadOption << ";" << endl;
983    out << "   useDBG          = " << useDBG << ";" << endl;
984    out << "   useMC           = " << useMC << ";" << endl;
985    out << "   useTAGS         = " << useTAGS << ";" << endl;
986    out << "   useKFILTER      = " << useKFILTER << ";" << endl;
987    out << "   useTR           = " << useTR << ";" << endl;
988    out << "   useCORRFW       = " << useCORRFW << ";" << endl;
989    out << "   useAODTAGS      = " << useAODTAGS << ";" << endl;
990    out << "   saveTrain       = " << "kFALSE;" << endl << endl;
991    out << "   // Analysis modules" << endl;
992    out << "   iAODanalysis    = " << iAODanalysis << ";" << endl;
993    out << "   iAODhandler     = " << iAODhandler << ";" << endl;
994    out << "   iPWG3hfe        = " << iPWG3hfe << ";" << endl;   
995    out << "   iPWG3JPSIfilter = " << iPWG3JPSIfilter << ";" << endl;   
996    out << "   iPWG3JPSI       = " << iPWG3JPSI << ";" << endl;   
997    out << "   iPWG3d2h        = " << iPWG3d2h << ";" << endl;   
998    out << "   iPWG3MuonTrain      = " << iPWG3MuonTrain << ";" << endl;   
999    out << "}" << endl;
1000    ::Info("AnalysisTrainNew.C::WriteConfig", "Train configuration wrote to file %s", Form("config_%s.C", train_name.Data()));
1001    gSystem->ChangeDirectory(cdir);
1002 }   
1003
1004 //______________________________________________________________________________
1005 Bool_t LoadConfig(const char *filename)
1006 {
1007 // Read train configuration from file
1008    if (gSystem->AccessPathName(filename)) {
1009       ::Error("AnalysisTrainNew.C::LoadConfig", "Config file name not found");
1010       return kFALSE;
1011    }   
1012    gROOT->ProcessLine(Form(".x %s", filename));
1013    ::Info("AnalysisTrainNew.C::LoadConfig", "Train configuration loaded from file %s", filename);
1014    return kTRUE;
1015 }