]> git.uio.no Git - u/mrichter/AliRoot.git/blob - ANALYSIS/macros/AnalysisTrainNew.C
Some mods to match the last version of the alien plugin.
[u/mrichter/AliRoot.git] / ANALYSIS / macros / AnalysisTrainNew.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         = "LHC09a5"; // enters file names, so no blancs or special characters
20 //==============================================================================
21
22 // ### Settings that make sense in PROOF only
23 //==============================================================================
24 TString     proof_cluster      = "alicecaf.cern.ch";
25 Bool_t      useAFPAR           = kFALSE;  // use AF special par file
26 TString     AFversion          = "AF-v4-16";
27 // Change CAF dataset here
28 TString     proof_dataset      = "/COMMON/COMMON/LHC09a4_run8100X#/esdTree";
29 TString     proof_outdir       = "";
30
31 // ### Settings that make sense when using the Alien plugin
32 //==============================================================================
33 Bool_t      usePLUGIN          = kTRUE;   // do not change
34 // Usage of par files ONLY in grid mode and ONLY if the code is not available
35 // in the deployed AliRoot versions. Par file search path: local dir, if not there $ALICE_ROOT.
36 // To refresh par files, remove the ones in the workdir, then do "make <target.par>" in 
37 // AliRoot.
38 Bool_t      usePAR             = kFALSE;  // use par files for extra libs
39 Bool_t      useCPAR            = kFALSE;  // use par files for common libs
40 TString     root_version       = "v5-23-04";
41 TString     aliroot_version    = "v4-17-03";
42 // Change production base directory here
43 TString     alien_datadir      = "/alice/sim/PDC_09/LHC09a5/";
44 // AliEn output directory. If blank will become output_<train_name>
45 TString     alien_outdir       = "/alice/sim/PDC_09/LHC09a5/AOD";
46 // Number of files merged in a chunk
47 Int_t       maxMergeFiles      = 50;
48 // Files that should not be merged
49 TString     mergeExclude       = "AliAOD.root AliAOD.VertexingHF.root AOD.tag.root";
50 // Number of runs per master job
51 Int_t       nRunsPerMaster     = 10;
52 // Maximum number of files per job (gives size of AOD)
53 Int_t       nFilesPerJob       = 100;
54 // Set the run range
55 Int_t       run_range[2]       =  {90000, 90040};
56 // ### Settings that make sense only for local analysis
57 //==============================================================================
58 // Change local xml dataset for local interactive analysis
59 TString     local_xmldataset   = "";
60
61 // ### Other flags to steer the analysis
62 //==============================================================================
63 Bool_t      useDATE            = kFALSE; // use date in train name
64 Bool_t      useDBG             = kFALSE; // activate debugging
65 Bool_t      useMC              = kTRUE;  // use MC info
66 Bool_t      useTAGS            = kFALSE; // use ESD tags for selection
67 Bool_t      useKFILTER         = kTRUE;  // use Kinematics filter
68 Bool_t      useTR              = kFALSE; // use track references
69 Bool_t      useCORRFW          = kFALSE; // do not change
70 Bool_t      useAODTAGS         = kTRUE;  // use AOD tags
71 Bool_t      saveTrain          = kTRUE;  // save train configuration as: 
72 Bool_t      saveProofToAlien   = kFALSE; // save proof outputs in AliEn
73                                          // train_[trainName]_ddMonthyyyy_time.C
74 // ### Analysis modules to be included. Some may not be yet fully implemented.
75 //==============================================================================
76 Int_t       iAODanalysis       = 0;      // Analysis on input AOD's
77 Int_t       iAODhandler        = 1;      // Analysis produces an AOD or dAOD's
78 Int_t       iESDfilter         = 1;      // ESD to AOD filter (barrel + muon tracks)
79 Int_t       iMUONcopyAOD       = 0;      // Task that copies only muon events in a separate AOD (PWG3)
80 Int_t       iJETAN             = 1;      // Jet analysis (PWG4) - needs ESD filter
81 Int_t       iPWG4partcorr      = 1;      // Gamma-hadron correlations task (PWG4)
82 Int_t       iPWG3vertexing     = 1;      // Vertexing HF task (PWG2)
83 Int_t       iPWG2femto         = 1;      // Femtoscopy task (PWG2)
84 Int_t       iPWG2spectra       = 1;      // Spectra PWG2 tasks (protons, cascades, V0 check, strange)
85 Int_t       iPWG2flow          = 1;      // Flow analysis task (PWG2)
86 Int_t       iPWG2res           = 1;      // Resonances task (PWG2)
87 Int_t       iPWG2kink          = 1;      // Kink analysis task (PWG2)
88
89 // Temporaries.
90 TString anaPars = "";
91 TString anaLibs = "";
92 // Function signatures
93 class AliAnalysisGrid;
94
95 //______________________________________________________________________________
96 void AnalysisTrainNew(const char *analysis_mode="grid", 
97                       const char *plugin_mode="full",
98                       const char *config_file="")
99 {
100 // Main analysis train macro. If a configuration file is provided, all parameters
101 // are taken from there but may be altered by CheckModuleFlags.
102    if (strlen(config_file) && !LoadConfig(config_file)) return;
103    TString smode(analysis_mode);
104    smode.ToUpper();
105    if (saveTrain)              WriteConfig();
106    // Check compatibility of selected modules
107    CheckModuleFlags(smode);
108
109    printf("==================================================================\n");
110    printf("===========    RUNNING ANALYSIS TRAIN %s IN %s MODE   ==========\n", train_name.Data(),smode.Data());
111    printf("==================================================================\n");
112    printf("=  Configuring analysis train for:                               =\n");
113    if (iAODanalysis) printf("=  AOD analysis                                                  =\n");
114    else              printf("=  ESD analysis                                                  =\n");
115    if (iESDfilter)   printf("=  ESD filter                                                    =\n");
116    if (iMUONcopyAOD) printf("=  MUON copy AOD                                                 =\n");
117    if (iJETAN)       printf("=  Jet analysis                                                  =\n");
118    if (iPWG2spectra) printf("=  PWG2 proton, checkCascade, checkV0, strange                   =\n");
119    if (iPWG2femto)   printf("=  PWG2 femtoscopy                                               =\n");
120    if (iPWG2flow)    printf("=  PWG2 flow                                                     =\n");
121    if (iPWG2res)     printf("=  PWG2 resonances                                               =\n");
122    if (iPWG2kink)    printf("=  PWG2 kink analysis                                            =\n");
123    if (iPWG3vertexing) printf("=  PWG3 vertexing                                            =\n");
124    if (iPWG4partcorr)  printf("=  PWG4 gamma-hadron, pi0 and gamma-jet correlations         =\n");
125    printf("==================================================================\n");
126    printf(":: use MC truth      %d\n", (UInt_t)useMC);
127    printf(":: use KINE filter   %d\n", (UInt_t)useKFILTER);
128    printf(":: use track refs    %d\n", (UInt_t)useTR);
129    printf(":: use tags          %d\n", (UInt_t)useTAGS);
130    printf(":: use AOD tags      %d\n", (UInt_t)useAODTAGS);
131    printf(":: use debugging     %d\n", (UInt_t)useDBG);
132    printf(":: use PAR files     %d\n", (UInt_t)usePAR);
133    printf(":: use AliEn plugin  %d\n", (UInt_t)usePLUGIN);
134
135    //==========================================================================
136    // Connect to back-end system
137    if (!Connect(smode)) {
138       ::Error("AnalysisTrain", "Could not connect to %s back-end", analysis_mode);
139       return;
140    }   
141
142    // Load common libraries and set include path
143    if (!LoadCommonLibraries(smode)) {
144       ::Error("AnalysisTrain", "Could not load common libraries");
145       return;
146    }
147     
148    // Make the analysis manager and connect event handlers
149    AliAnalysisManager *mgr  = new AliAnalysisManager("Analysis Train", "Production train");
150    if (saveProofToAlien) mgr->SetSpecialOutputLocation(proof_outdir);
151
152    // Load analysis specific libraries
153    if (!LoadAnalysisLibraries(smode)) {
154       ::Error("AnalysisTrain", "Could not load analysis libraries");
155       return;
156    }   
157
158    // Create input handler (input container created automatically)
159    if (iAODanalysis) {
160    // AOD input handler
161       AliAODInputHandler *aodH = new AliAODInputHandler();
162       mgr->SetInputEventHandler(aodH);
163    } else {   
164    // ESD input handler
165       AliESDInputHandler *esdHandler = new AliESDInputHandler();
166       if (useTAGS) esdHandler->SetReadTags();
167       mgr->SetInputEventHandler(esdHandler);       
168    }
169    // Monte Carlo handler
170    if (useMC && !iAODanalysis) {
171       AliMCEventHandler* mcHandler = new AliMCEventHandler();
172       mgr->SetMCtruthEventHandler(mcHandler);
173       mcHandler->SetReadTR(useTR); 
174    }   
175    // AOD output container, created automatically when setting an AOD handler
176    if (iAODhandler) {
177       // AOD output handler
178       AliAODHandler* aodHandler   = new AliAODHandler();
179       aodHandler->SetOutputFileName("AliAOD.root");
180       mgr->SetOutputEventHandler(aodHandler);
181       if (iAODanalysis) {
182          aodHandler->SetCreateNonStandardAOD();
183          if (iPWG3vertexing) aodHandler->SetOutputFileName("AliAOD.VertexingHF.root");
184       } 
185    }
186    // Debugging if needed
187    if (useDBG) mgr->SetDebugLevel(3);
188
189    //==========================================================================
190    // Create the chain. In this example it is created only from ALIEN files but
191    // can be done to work in batch or grid mode as well.
192    TChain *chain = CreateChain(smode, plugin_mode);
193         
194    //==========================================================================
195    // Load the tasks configuration macros for all wagons. These files are supposed now to be
196    // in the current workdir, but in AliEn they will be in the file catalog, 
197    // mapped from AliRoot and pecified in the jdl input list.
198     
199    // For now connection to top input container and common AOD output container
200    // is done in this macro, but in future these containers will be connected
201    // from each task configuration macro.
202
203    if (iESDfilter && !iAODanalysis) {
204       //  ESD filter task configuration.
205       gROOT->LoadMacro("$ALICE_ROOT/ANALYSIS/macros/AddTaskESDFilter.C");
206       AliAnalysisTaskESDfilter *taskesdfilter = AddTaskESDFilter(useKFILTER);
207    }   
208
209    // AOD tags
210    if (useAODTAGS) {
211       AliAnalysisTaskTagCreator* tagTask = new AliAnalysisTaskTagCreator("AOD Tag Creator");
212       mgr->AddTask(tagTask);
213       AliAnalysisDataContainer *coutTags = mgr->CreateContainer("cTag",  TTree::Class(), 
214                                            AliAnalysisManager::kOutputContainer, "AOD.tag.root");
215       mgr->ConnectInput (tagTask, 0, mgr->GetCommonInputContainer());
216       mgr->ConnectOutput(tagTask, 1, coutTags);
217    }   
218     
219     // Jet analysis
220    if (iJETAN) {
221       gROOT->LoadMacro("$ALICE_ROOT/PWG4/macros/AddTaskJets.C");
222       AliAnalysisTaskJets *taskjets = AddTaskJets("AOD", "UA1");
223       if (!taskjets) ::Warning("AnalysisTrainNew", "AliAnalysisTaskJets cannot run for this train conditions - EXCLUDED");
224    }
225        
226    // Proton analysis
227    if (iPWG2spectra) {
228       // protons
229       gROOT->LoadMacro("$ALICE_ROOT/PWG2/SPECTRA/macros/AddTaskProtons.C");
230       AliAnalysisTaskProtons *taskprotons = AddTaskProtons();
231       if (!taskprotons) ::Warning("AnalysisTrainNew", "AliAnalysisTaskProtons cannot run for this train conditions - EXCLUDED");
232       // cascades
233       gROOT->LoadMacro("$ALICE_ROOT/PWG2/SPECTRA/macros/AddTaskCheckCascade.C");
234       AliAnalysisTaskCheckCascade *taskcheckcascade = AddTaskCheckCascade();      
235       if (!taskcheckcascade) ::Warning("AnalysisTrainNew", "AliAnalysisTaskCheckCascade cannot run for this train conditions - EXCLUDED");
236       // v0's
237       gROOT->LoadMacro("$ALICE_ROOT/PWG2/SPECTRA/macros/AddTaskCheckV0.C");
238       AliAnalysisTaskCheckV0 *taskcheckV0 = AddTaskCheckV0();
239       if (!taskcheckV0) ::Warning("AnalysisTrainNew", "AliAnalysisTaskCheckV0 cannot run for this train conditions - EXCLUDED");
240       // strangeness
241       gROOT->LoadMacro("$ALICE_ROOT/PWG2/SPECTRA/macros/AddTaskStrange.C");
242       AliAnalysisTaskStrange *taskstrange = AddTaskStrange();
243       if (!taskstrange) ::Warning("AnalysisTrainNew", "AliAnalysisTaskStrange cannot run for this train conditions - EXCLUDED");
244    }   
245    
246    // Femtoscopy analysis modules
247    if (iPWG2femto) {
248       gROOT->LoadMacro("$ALICE_ROOT/PWG2/FEMTOSCOPY/macros/AddTaskFemto.C");
249       AliAnalysisTaskFemto *taskfemto = AddTaskFemto();
250       if (!taskfemto) ::Warning("AnalysisTrainNew", "AliAnalysisTaskFemto cannot run for this train conditions - EXCLUDED");
251    }   
252
253    // Kink analysis
254    if (iPWG2kink) {
255       gROOT->LoadMacro("$ALICE_ROOT/PWG2/KINK/macros/AddTaskKink.C");
256       AliAnalysisKinkESDMC *taskkink = AddTaskKink();
257       if (!taskkink) ::Warning("AnalysisTrainNew", "AliAnalysisKinkESDMC cannot run for this train conditions - EXCLUDED");
258       gROOT->LoadMacro("$ALICE_ROOT/PWG2/KINK/macros/AddTaskKinkResonance.C");
259       AliResonanceKinkPID *taskkinkres = AddTaskKinkResonance();
260       if (!taskkinkres) ::Warning("AnalysisTrainNew", "AliResonanceKinkPID cannot run for this train conditions - EXCLUDED");
261       gROOT->LoadMacro("$ALICE_ROOT/PWG2/KINK/macros/AddTaskKinkResonanceLikeSign.C");
262       AliResonanceKinkLikeSign *taskkinklikesign = AddTaskKinkResonanceLikeSign();
263       if (!taskkinklikesign) ::Warning("AnalysisTrainNew", "AliResonanceKinkLikeSign cannot run for this train conditions - EXCLUDED");
264    }   
265
266    // Flow analysis
267    if (iPWG2flow) {
268       gROOT->LoadMacro("$ALICE_ROOT/PWG2/FLOW/macros/AddTaskFlow.C");
269       Bool_t SP     = kTRUE;
270       Bool_t LYZ1   = kTRUE;
271       Bool_t LYZ2   = kFALSE;
272       Bool_t LYZEP  = kFALSE;
273       Bool_t GFC    = kTRUE;
274       Bool_t QC     = kTRUE;
275       Bool_t FQD    = kTRUE;
276       Bool_t MCEP   = kFALSE; //not for pp 
277       Bool_t kineFromESD = kTRUE;
278       Bool_t METHODS[] = {SP,LYZ1,LYZ2,LYZEP,GFC,QC,FQD,MCEP};
279       // Analysis type can be ESD, AOD, MC, ESDMC0, ESDMC1
280       TString type = "AOD";
281       if (!iAODanalysis) type = "ESD";
282       if (useMC) {
283          type += "MC";
284          if (!kineFromESD) type += "1";
285          else type += "0";
286       }   
287       // Boolean to fill/not fill the QA histograms
288       Bool_t QA = kTRUE;   
289       // Boolean to use/not use weights for the Q vector
290       Bool_t WEIGHTS[] = {kFALSE,kFALSE,kFALSE}; //Phi, v'(pt), v'(eta)
291       AliAnalysisTaskFlowEvent* taskFE = AddTaskFlow(type,METHODS,QA,WEIGHTS);
292       if (!taskFE) ::Warning("AnalysisTrainNew", "AliAnalysisTaskFlowEvent cannot run for this train conditions - EXCLUDED");
293    }   
294
295    // PWG2 resonances
296    if (iPWG2res) {
297       gROOT->LoadMacro("$ALICE_ROOT/PWG2/RESONANCES/macros/AddAnalysisTaskRsn.C");
298       AddAnalysisTaskRsn("rsn.root", useMC);
299    }   
300            
301    // PWG3 vertexing
302    if (iPWG3vertexing) {
303       gROOT->LoadMacro("$ALICE_ROOT/PWG3/vertexingHF/AddTaskVertexingHF.C");
304       AliAnalysisTaskSEVertexingHF *taskvertexingHF = AddTaskVertexingHF();
305       if (!taskvertexingHF) ::Warning("AnalysisTrainNew", "AliAnalysisTaskSEVertexingHF cannot run for this train conditions - EXCLUDED");
306    }   
307       
308    // PWG4 hadron correlations
309    if (iPWG4partcorr) {
310       gROOT->LoadMacro("$ALICE_ROOT/PWG4/macros/AddTaskPartCorr.C");
311       AliAnalysisTaskParticleCorrelation *taskpartcorrPHOS = AddTaskPartCorr("AOD", "PHOS");
312       if (!taskpartcorrPHOS) ::Warning("AnalysisTrainNew", "AliAnalysisTaskParticleCorrelation PHOS cannot run for this train conditions - EXCLUDED");
313       AliAnalysisTaskParticleCorrelation *taskpartcorrEMCAL = AddTaskPartCorr("AOD", "EMCAL");
314       if (!taskpartcorrEMCAL) ::Warning("AnalysisTrainNew", "AliAnalysisTaskParticleCorrelation EMCAL cannot run for this train conditions - EXCLUDED");
315    }   
316    //==========================================================================
317    // FOR THE REST OF THE TASKS THE MACRO AddTaskXXX() is not yet implemented/
318    // Run the analysis
319    //    
320    if (mgr->InitAnalysis()) {
321       mgr->PrintStatus();
322       if (saveTrain || strlen(config_file)) gSystem->ChangeDirectory(train_name);
323       StartAnalysis(smode, chain);
324       if (saveTrain) {
325          printf("=== Registering ConfigTrain.C in the output directory <%s> ===\n",
326                 alien_outdir.Data());
327          TFile::Cp("file:ConfigTrain.C", Form("alien://%s/ConfigTrain.C", alien_outdir.Data()));
328       }
329    }
330 }
331
332 //______________________________________________________________________________
333 void StartAnalysis(const char *mode, TChain *chain) {
334 // Start analysis.
335    Int_t imode = -1;
336    AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
337    if (!strcmp(mode, "LOCAL")) imode = 0;
338    if (!strcmp(mode, "PROOF")) imode = 1;
339    if (!strcmp(mode, "GRID"))  imode = 2;
340    switch (imode) {
341       case 0:
342          if (!chain) {
343             ::Error("AnalysisTrainNew.C::StartAnalysis", "Cannot create the chain");
344             return;
345          }   
346          mgr->StartAnalysis(mode, chain);
347          return;
348       case 1:
349          if (!proof_dataset.Length()) {
350             ::Error("AnalysisTrainNew.C::StartAnalysis", "proof_dataset is empty");
351             return;
352          }   
353          mgr->StartAnalysis(mode, proof_dataset, 1000);
354          return;
355       case 2:
356          if (usePLUGIN) {
357             if (!mgr->GetGridHandler()) {
358                ::Error("AnalysisTrainNew.C::StartAnalysis", "Grid plugin not initialized");
359                return;
360             }   
361             mgr->StartAnalysis("grid");
362          } else {
363             if (!chain) {
364                ::Error("AnalysisTrainNew.C::StartAnalysis", "Cannot create the chain");
365                return;
366             }   
367             mgr->StartAnalysis(mode, chain);
368          }   
369          return;
370    }      
371 }          
372     
373 //______________________________________________________________________________
374 void CheckModuleFlags(const char *mode) {
375 // Checks selected modules and insure compatibility
376    Int_t imode = -1;
377    if (!strcmp(mode, "LOCAL")) imode = 0;
378    if (!strcmp(mode, "PROOF")) imode = 1;
379    if (!strcmp(mode, "GRID"))  imode = 2;
380    if (imode==1) {
381       if (!usePAR) {
382          ::Info("AnalysisTrainNew.C::CheckModuleFlags", "PAR files enabled due to PROOF analysis");
383          usePAR = kTRUE;
384       }   
385    }  
386    if (imode != 2) {
387       ::Info("AnalysisTrainNew.C::CheckModuleFlags", "AliEn plugin disabled since not in GRID mode");
388       usePLUGIN = kFALSE; 
389    }   
390    if (iAODanalysis) {
391    // AOD analysis
392       if (useMC)
393          ::Info("AnalysisTrainNew.C::CheckModuleFlags", "MC usage disabled in analysis on AOD's");
394       useMC = kFALSE;
395       useTR = kFALSE;
396       if (iESDfilter)
397          ::Info("AnalysisTrainNew.C::CheckModuleFlags", "ESD filter disabled in analysis on AOD's");
398       iESDfilter   = 0;
399       if (!iAODhandler) {
400          if (iJETAN) 
401             ::Info("AnalysisTrainNew.C::CheckModuleFlags", "JETAN disabled in analysis on AOD's without AOD handler");
402          iJETAN = 0;
403       }
404       // Disable tasks that do not work yet on AOD data
405       if (iPWG2kink)         
406          ::Info("AnalysisTrainNew.C::CheckModuleFlags", "PWG2kink disabled in analysis on AOD's");
407          iPWG2kink = 0;
408    } else {   
409    // ESD analysis
410       iMUONcopyAOD = 0;
411    }       
412    if (iJETAN) iESDfilter=1;
413    if (iESDfilter) iAODhandler=1;
414    if (iPWG2spectra || iPWG2flow || iPWG3vertexing) useCORRFW = kTRUE;
415    if (useKFILTER && !useMC) useKFILTER = kFALSE;
416    if (useAODTAGS && !iAODhandler) useAODTAGS = kFALSE;
417 }
418
419 //______________________________________________________________________________
420 Bool_t Connect(const char *mode) {
421 // Connect <username> to the back-end system.
422    Int_t imode = -1;
423    if (!strcmp(mode, "LOCAL")) imode = 0;
424    if (!strcmp(mode, "PROOF")) imode = 1;
425    if (!strcmp(mode, "GRID"))  imode = 2;
426    TString username = gSystem->Getenv("alien_API_USER");
427    switch (imode) {
428       case 0:
429          break;
430       case 1:
431          if  (!username.Length()) {
432             ::Error(Form("AnalysisTrainNew.C::Connect <%s>", mode), "Make sure you:\n \
433                            1. Have called: alien-token-init <username>\n \
434                            2. Have called: >source /tmp/gclient_env_$UID");
435             return kFALSE;
436          }
437          ::Info("AnalysisTrainNew.C::Connect", "Connecting user <%s> to PROOF cluster <%s>", 
438                 username.Data(), proof_cluster.Data());
439          gEnv->SetValue("XSec.GSI.DelegProxy", "2");
440 //         TProof::Open(Form("%s@%s:31093", username.Data(), proof_cluster.Data()));       
441          TProof::Open(Form("%s@%s", username.Data(), proof_cluster.Data()));       
442          if (!gProof) {
443             if (strcmp(gSystem->Getenv("XrdSecGSISRVNAMES"), "lxfsrd0506.cern.ch"))
444                ::Error(Form("AnalysisTrainNew.C::Connect <%s>", mode), "Environment XrdSecGSISRVNAMES different from lxfsrd0506.cern.ch");
445             return kFALSE;
446          }
447          TGrid::Connect("alien://");
448          if (gGrid) {
449             TString homedir = gGrid->GetHomeDirectory();
450             TString workdir = homedir + train_name;
451             if (!gGrid->Cd(workdir)) {
452                gGrid->Cd(homedir);
453                if (gGrid->Mkdir(workdir)) {
454                   gGrid->Cd(train_name);
455                   ::Info("AnalysisTrainNew::Connect()", "Directory %s created", gGrid->Pwd());
456                }
457             }
458             gGrid->Mkdir("proof_output");
459             gGrid->Cd("proof_output");
460             proof_outdir = Form("alien://%s", gGrid->Pwd());
461          }   
462          break;
463       case 2:      
464          if  (!username.Length()) {
465             ::Error(Form("AnalysisTrainNew.C::Connect <%s>", mode), "Make sure you:\n \
466                            1. Have called: alien-token-init <username>\n \
467                            2. Have called: >source /tmp/gclient_env_$UID");
468             return kFALSE;
469          }
470          if (usePLUGIN && !gSystem->Getenv("alien_CLOSE_SE")) {
471             ::Error(Form("AnalysisTrainNew.C::Connect <%s>", mode), 
472                            "When using the AliEn plugin it is preferable to define the \
473                            variable alien_CLOSE_SE in your environment.");
474             return kFALSE;
475          }
476          ::Info("AnalysisTrainNew.C::Connect", "Connecting user <%s> to AliEn ...", 
477                 username.Data());
478          TGrid::Connect("alien://");
479          if (!gGrid || !gGrid->IsConnected()) return kFALSE;
480          break;
481       default:
482          ::Error("AnalysisTrainNew.C::Connect", "Unknown run mode: %s", mode);
483          return kFALSE;
484    }
485    ::Info("AnalysisTrainNew.C::Connect","Connected in %s mode", mode);
486    return kTRUE;
487 }
488
489 //______________________________________________________________________________
490 Bool_t LoadCommonLibraries(const char *mode)
491 {
492 // Load common analysis libraries.
493    Int_t imode = -1;
494    if (!strcmp(mode, "LOCAL")) imode = 0;
495    if (!strcmp(mode, "PROOF")) imode = 1;
496    if (!strcmp(mode, "GRID"))  imode = 2;
497    if (!gSystem->Getenv("ALICE_ROOT")) {
498       ::Error("AnalysisTrainNew.C::LoadCommonLibraries", "Analysis train requires that analysis libraries are compiled with a local AliRoot"); 
499       return kFALSE;
500    }   
501    Bool_t success = kTRUE;
502    // ROOT libraries
503    gSystem->Load("libTree.so");
504    gSystem->Load("libGeom.so");
505    gSystem->Load("libVMC.so");
506    gSystem->Load("libPhysics.so");
507    
508    // Load framework classes. Par option ignored here.
509    switch (imode) {
510       case 0:
511       case 2:
512          if (useCPAR) {
513             success &= LoadLibrary("STEERBase", mode, kTRUE);
514             success &= LoadLibrary("ESD", mode, kTRUE);
515             success &= LoadLibrary("AOD", mode, kTRUE);
516             success &= LoadLibrary("ANALYSIS", mode, kTRUE);
517             success &= LoadLibrary("ANALYSISalice", mode, kTRUE);
518             if (useCORRFW) success &= LoadLibrary("CORRFW", mode, kTRUE);
519          } else {   
520             success &= LoadLibrary("libSTEERBase.so", mode);
521             success &= LoadLibrary("libESD.so", mode);
522             success &= LoadLibrary("libAOD.so", mode);
523             success &= LoadLibrary("libANALYSIS.so", mode);
524             success &= LoadLibrary("libANALYSISalice.so", mode);
525             if (useCORRFW) success &= LoadLibrary("libCORRFW.so", mode);
526             gROOT->ProcessLine(".include $ALICE_ROOT/include");
527          }   
528          break;
529       case 1:
530          Int_t ires = -1;
531          if (useAFPAR && !gSystem->AccessPathName(AFversion)) ires = gProof->UploadPackage(AFversion);
532          if (ires < 0) {
533             success &= LoadLibrary("STEERBase", mode);
534             success &= LoadLibrary("ESD", mode);
535             success &= LoadLibrary("AOD", mode);
536             success &= LoadLibrary("ANALYSIS", mode);
537             success &= LoadLibrary("ANALYSISalice", mode);
538             if (useCORRFW) success &= LoadLibrary("CORRFW", mode);
539          } else { 
540             ires = gProof->EnablePackage(AFversion);
541             if (ires<0) success = kFALSE;
542             if (useCORRFW) success &= LoadLibrary("CORRFW", mode);
543          }
544          break;         
545       default:
546          ::Error("AnalysisTrainNew.C::LoadCommonLibraries", "Unknown run mode: %s", mode);
547          return kFALSE;
548    }
549    if (success) {
550       ::Info("AnalysisTrainNew.C::LoadCommodLibraries", "Load common libraries:    SUCCESS");
551       ::Info("AnalysisTrainNew.C::LoadCommodLibraries", "Include path for Aclic compilation:\n%s",
552               gSystem->GetIncludePath());
553    } else {           
554       ::Info("AnalysisTrainNew.C::LoadCommodLibraries", "Load common libraries:    FAILED");
555    }   
556       
557    return success;
558 }
559
560 //______________________________________________________________________________
561 Bool_t LoadAnalysisLibraries(const char *mode)
562 {
563 // Load common analysis libraries.
564    Bool_t success = kTRUE;
565    if (iESDfilter) {
566       if (!LoadLibrary("PWG3base", mode, kTRUE) ||
567           !LoadLibrary("PWG3muon", mode, kTRUE)) return kFALSE;
568    }   
569    // JETAN
570    if (iJETAN) {
571       if (!LoadLibrary("JETAN", mode, kTRUE)) return kFALSE;
572    }   
573             
574    // PWG4 particle correlations
575    if (iPWG4partcorr) {   
576       if (!LoadLibrary("PWG4PartCorrBase", mode, kTRUE) ||
577           !LoadLibrary("PWG4PartCorrDep", mode, kTRUE)) return kFALSE;
578    }
579    // PWG2 task protons 
580    if (iPWG2spectra) {
581       if (!LoadLibrary("PWG2spectra", mode, kTRUE)) return kFALSE;
582    }
583    // PWG2 flow
584    if (iPWG2flow) {
585       if (!LoadLibrary("PWG2flowCommon", mode, kTRUE) ||
586           !LoadLibrary("PWG2flowTasks", mode, kTRUE)) return kFALSE;
587    }
588    // PWG2 resonances
589    if (iPWG2res) {
590       if (!LoadLibrary("PWG2resonances", mode, kTRUE)) return kFALSE;
591    }   
592    // PWG2 kink
593    if (iPWG2kink) {
594       if (!LoadLibrary("PWG2kink", mode, kTRUE)) return kFALSE;
595    }   
596    // PWG2 femtoscopy
597    if (iPWG2femto) {
598       if (!LoadLibrary("PWG2AOD", mode, kTRUE) ||
599           !LoadLibrary("PWG2femtoscopy", mode, kTRUE) ||
600           !LoadLibrary("PWG2femtoscopyUser", mode, kTRUE)) return kFALSE;
601       TFile::Cp(gSystem->ExpandPathName("$(ALICE_ROOT)/PWG2/FEMTOSCOPY/macros/ConfigFemtoAnalysis.C"), Form("%s/ConfigFemtoAnalysis.C", train_name.Data()));
602       anaLibs += "ConfigFemtoAnalysis.C ";
603    }   
604    // Vertexing HF
605    if (iPWG3vertexing) {
606       if (!LoadLibrary("PWG3base", mode, kTRUE) ||
607           !LoadLibrary("PWG3vertexingHF", mode, kTRUE)) return kFALSE;
608    }   
609    ::Info("AnalysisTrainNew.C::LoadAnalysisLibraries", "Load other libraries:   SUCCESS");
610    return kTRUE;
611 }
612
613 //______________________________________________________________________________
614 Bool_t LoadLibrary(const char *module, const char *mode, Bool_t rec=kFALSE)
615 {
616 // Load a module library in a given mode. Reports success.
617    Int_t imode = -1;
618    Int_t result;
619    TString smodule(module);
620    if (!strcmp(mode, "LOCAL")) imode = 0;
621    if (!strcmp(mode, "PROOF")) imode = 1;
622    if (!strcmp(mode, "GRID"))  imode = 2;
623    TString mod(module);
624    if (!mod.Length()) {
625       ::Error("AnalysisTrainNew.C::LoadLibrary", "Empty module name");
626       return kFALSE;
627    }   
628    // If a library is specified, just load it
629    if (smodule.EndsWith(".so")) {
630       mod.Remove(mod.Index(".so"));
631       result = gSystem->Load(mod);
632       if (result < 0) {
633          ::Error("AnalysisTrainNew.C::LoadLibrary", "Could not load library %s", module);
634          return kFALSE;
635       }
636       if (rec) anaLibs += Form("%s.so ",mod.Data()); 
637       return kTRUE;
638    } 
639    // Check if the library is already loaded
640    if (strlen(gSystem->GetLibraries(Form("%s.so", module), "", kFALSE)) > 0)
641       return kTRUE;    
642    switch (imode) {
643       case 0:
644       case 2:
645          if (usePAR) {
646             result = SetupPar(module);
647             if (rec) anaPars += Form("%s.par ", module);
648          } else {
649             result = gSystem->Load(Form("lib%s.so", module));
650             if (rec) anaLibs += Form("lib%s.so ", module);
651          }   
652          break;
653       case 1:
654          result = gProof->UploadPackage(module);
655          if (result<0) {
656             result = gProof->UploadPackage(gSystem->ExpandPathName(Form("$ALICE_ROOT/%s.par", module)));
657             if (result<0) {
658                ::Error("AnalysisTrainNew.C::LoadLibrary", "Could not find module %s.par in current directory nor in $ALICE_ROOT", module);
659                return kFALSE;
660             }
661          }   
662          result = gProof->EnablePackage(module);
663          break;
664       default:
665          return kFALSE;
666    }         
667    if (result < 0) {
668       ::Error("AnalysisTrainNew.C::LoadLibrary", "Could not load module %s", module);
669       return kFALSE;
670    }
671    return kTRUE;
672 }           
673
674
675 //______________________________________________________________________________
676 TChain *CreateChain(const char *mode, const char *plugin_mode)
677 {
678 // Create the input chain
679    Int_t imode = -1;
680    if (!strcmp(mode, "LOCAL")) imode = 0;
681    if (!strcmp(mode, "PROOF")) imode = 1;
682    if (!strcmp(mode, "GRID"))  imode = 2;
683    TChain *chain = NULL;
684    // Local chain
685    switch (imode) {
686       case 0:
687          if (iAODanalysis) {
688             if (!local_xmldataset.Length()) {
689                // Local AOD
690                chain = new TChain("aodTree");
691                if (gSystem->AccessPathName("data/AliAOD.root")) 
692                   ::Error("AnalysisTrainNew.C::CreateChain", "File: AliAOD.root not in ./data dir");
693                else {
694                   if (!saveTrain) chain->Add("data/AliAOD.root");
695                   else            chain->Add("../data/AliAOD.root");
696                }   
697             } else {
698                // Interactive AOD
699                chain = CreateChainSingle(local_xmldataset, "aodTree");
700             }
701          } else {      
702             if (!local_xmldataset.Length()) {
703                // Local ESD
704                chain = new TChain("esdTree");
705                if (gSystem->AccessPathName("data/AliESDs.root")) 
706                   ::Error("AnalysisTrainNew.C::CreateChain", "File: AliESDs.root not in ./data dir");
707                else {
708                   if (!saveTrain) chain->Add("data/AliESDs.root");
709                   else            chain->Add("../data/AliESDs.root");
710                }   
711             } else {
712                // Interactive ESD
713                chain = CreateChainSingle(local_xmldataset, "esdTree");
714             }   
715          }
716          break;
717       case 1:
718          break;
719       case 2:
720          if (usePLUGIN) {
721             AliAnalysisGrid *alienHandler = CreateAlienHandler(plugin_mode);
722             AliAnalysisManager::GetAnalysisManager()->SetGridHandler(alienHandler);
723          } else {
724             TString           treeName = "esdTree";
725             if (iAODanalysis) treeName = "aodTree";
726             chain = CreateChainSingle("wn.xml", treeName);
727          }
728          break;      
729       default:   
730    }
731    if (chain && chain->GetNtrees()) return chain;
732    return NULL;
733 }   
734
735 //______________________________________________________________________________
736 TChain* CreateChainSingle(const char* xmlfile, const char *treeName)
737 {
738    printf("*******************************\n");
739    printf("*** Getting the ESD Chain   ***\n");
740    printf("*******************************\n");
741    TAlienCollection * myCollection  = TAlienCollection::Open(xmlfile);
742
743    if (!myCollection) {
744       ::Error("AnalysisTrainNew.C::CreateChainSingle", "Cannot create an AliEn collection from %s", xmlfile) ;
745       return NULL ;
746    }
747
748    TChain* chain = new TChain(treeName);
749    myCollection->Reset() ;
750    while ( myCollection->Next() ) chain->Add(myCollection->GetTURL("")) ;
751    chain->ls();
752    return chain;
753 }
754
755 //______________________________________________________________________________
756 Int_t SetupPar(char* pararchivename)
757 {
758    if (!pararchivename || !strlen(pararchivename)) return -1;
759    char processline[1024];
760    if (gSystem->AccessPathName(Form("%s.par", pararchivename))) {
761       if (!gSystem->AccessPathName(Form("%s/%s.par", gSystem->Getenv("ALICE_ROOT"),pararchivename))) {
762          ::Info("AnalysisTrainNew.C::SetupPar", "Getting %s.par from $ALICE_ROOT", pararchivename);
763          TFile::Cp(gSystem->ExpandPathName(Form("$ALICE_ROOT/%s.par", pararchivename)), 
764                    Form("%s.par",pararchivename));
765       } else {
766          ::Error("AnalysisTrainNew.C::SetupPar", "Cannot find %s.par", pararchivename);
767          return -1;
768       }   
769    }
770    if (usePLUGIN && saveTrain) gSystem->Exec(Form("ln -s ../%s.par %s",pararchivename, train_name.Data()));
771    gSystem->Exec(Form("tar xvzf %s.par", pararchivename));
772
773    TString ocwd = gSystem->WorkingDirectory();
774    if (!gSystem->ChangeDirectory(pararchivename)) return -1;
775         
776    // check for BUILD.sh and execute
777    if (!gSystem->AccessPathName("PROOF-INF/BUILD.sh")) {
778       printf("*******************************\n");
779       printf("*** Building PAR archive    ***\n");
780       printf("*******************************\n");          
781       if (gSystem->Exec("PROOF-INF/BUILD.sh")) {
782          Error("runProcess","Cannot Build the PAR Archive! - Abort!");
783          return -1;
784       }
785    }
786
787         // check for SETUP.C and execute
788         if (!gSystem->AccessPathName("PROOF-INF/SETUP.C")) {
789             printf("*******************************\n");
790             printf("*** Setup PAR archive       ***\n");
791             printf("*******************************\n");
792             gROOT->Macro("PROOF-INF/SETUP.C");
793         }       
794         if (!gSystem->ChangeDirectory(ocwd.Data())) return -1;
795    return 0;
796 }
797
798 //______________________________________________________________________________
799 AliAnalysisGrid* CreateAlienHandler(const char *plugin_mode)
800 {
801 // Check if user has a valid token, otherwise make one. This has limitations.
802 // One can always follow the standard procedure of calling alien-token-init then
803 //   source /tmp/gclient_env_$UID in the current shell.
804    if (!AliAnalysisGrid::CreateToken()) return NULL;
805    AliAnalysisAlien *plugin = new AliAnalysisAlien();
806 // Set the run mode (can be "full", "test", "offline", "submit" or "terminate")
807    plugin->SetRunMode(plugin_mode);
808    plugin->SetNtestFiles(1);
809    plugin->SetPreferedSE("ALICE::Legnaro::SE");
810 // Set versions of used packages
811    plugin->SetAPIVersion("V2.4");
812    plugin->SetROOTVersion(root_version);
813    plugin->SetAliROOTVersion(aliroot_version);
814 // Declare input data to be processed.
815 // Method 1: Create automatically XML collections using alien 'find' command.
816 // Define production directory LFN
817    plugin->SetGridDataDir(alien_datadir);
818 // Set data search pattern
819    if (iAODanalysis) plugin->SetDataPattern("*AliAOD.root");
820    else              plugin->SetDataPattern("*ESD.tag.root");
821 // ...then add run numbers to be considered
822    plugin->SetRunRange(run_range[0], run_range[1]);
823 //   for (Int_t i=0; i<10; i++) {
824 //      if (run_numbers[i]==0) break;
825 //      plugin->AddRunNumber(run_numbers[i]);
826 //   }   
827 // Method 2: Declare existing data files (raw collections, xml collections, root file)
828 // If no path mentioned data is supposed to be in the work directory (see SetGridWorkingDir())
829 // XML collections added via this method can be combined with the first method if
830 // the content is compatible (using or not tags)
831 //   plugin->AddDataFile("tag.xml");
832 //   plugin->AddDataFile("/alice/data/2008/LHC08c/000057657/raw/Run57657.Merged.RAW.tag.root");
833 // Define alien work directory where all files will be copied. Relative to alien $HOME.
834    if (iAODanalysis) plugin->SetGridWorkingDir("analysisAOD");
835    else              plugin->SetGridWorkingDir("analysisESD");
836 // Declare alien output directory. Relative to working directory.
837    if (!alien_outdir.Length()) alien_outdir = Form("output_%s",train_name.Data());
838    plugin->SetGridOutputDir(alien_outdir);
839
840    TString ana_sources = "";
841    TString ana_add = "";
842    if (usePAR && anaPars.Length()) {
843       printf("%s\n", anaPars.Data());
844       TObjArray *arr;
845       TObjString *objstr;
846       arr = anaPars.Tokenize(" ");
847       TIter next(arr);
848       while ((objstr=(TObjString*)next())) plugin->EnablePackage(objstr->GetString());
849       delete arr;
850    } 
851    
852 // Declare the analysis source files names separated by blancs. To be compiled runtime
853 // using ACLiC on the worker nodes.
854    ana_sources = ana_sources.Strip();
855 // Declare all libraries (other than the default ones for the framework. These will be
856 // loaded by the generated analysis macro. Add all extra files (task .cxx/.h) here.
857    anaLibs     = anaLibs.Strip();   
858    if (ana_sources.Length()) plugin->SetAnalysisSource(ana_sources);
859    if (anaLibs.Length())     plugin->SetAdditionalLibs(anaLibs);
860      
861 // Declare the output file names separated by blancs.
862 // (can be like: file.root or file.root@ALICE::Niham::File)
863    plugin->SetDefaultOutputs();
864    plugin->SetMergeExcludes(mergeExclude);
865    plugin->SetMaxMergeFiles(maxMergeFiles);
866    plugin->SetNrunsPerMaster(nRunsPerMaster);
867 // Optionally define the files to be archived.
868 //   plugin->SetOutputArchive("log_archive.zip:stdout,stderr@ALICE::NIHAM::File root_archive.zip:*.root@ALICE::NIHAM::File");
869    plugin->SetOutputArchive("log_archive.zip:stdout,stderr");
870 // Optionally set a name for the generated analysis macro (default MyAnalysis.C)
871    plugin->SetAnalysisMacro(Form("%s.C", train_name.Data()));
872 // Optionally set maximum number of input files/subjob (default 100, put 0 to ignore)
873    plugin->SetSplitMaxInputFileNumber(nFilesPerJob);
874 // Optionally set number of failed jobs that will trigger killing waiting sub-jobs.
875 //   plugin->SetMaxInitFailed(5);
876 // Optionally resubmit threshold.
877 //   plugin->SetMasterResubmitThreshold(90);
878 // Optionally set time to live (default 30000 sec)
879    plugin->SetTTL(30000);
880 // Optionally set input format (default xml-single)
881    plugin->SetInputFormat("xml-single");
882 // Optionally modify the name of the generated JDL (default analysis.jdl)
883    plugin->SetJDLName(Form("%s.jdl", train_name.Data()));
884 // Optionally modify the executable name (default analysis.sh)
885    plugin->SetExecutable(Form("%s.sh", train_name.Data()));
886 // Optionally modify job price (default 1)
887    plugin->SetPrice(1);      
888 // Optionally modify split mode (default 'se')    
889    plugin->SetSplitMode("se");
890    return plugin;
891 }
892
893 //______________________________________________________________________________
894 void WriteConfig()
895 {
896 // Write train configuration in a file. The file name has the format:
897 // train_[trainName]_ddMonthyyyy_time.C
898    gSystem->Exec("date +%d%b%Y_%Hh%M > date.tmp");
899    ifstream fdate("date.tmp");
900    if (!fdate.is_open()) {
901       ::Error("AnalysisTrainNew.C::Export","Could not generate file name");
902       return;
903    }
904    if (useDATE) {
905       const char date[64];
906       fdate.getline(date,64);
907       fdate.close();
908       gSystem->Exec("rm date.tmp");
909       train_name = Form("train_%s_%s", train_name.Data(), date);
910    } else {
911       train_name = Form("train_%s", train_name.Data());
912    }   
913    TString cdir = gSystem->WorkingDirectory();
914    gSystem->MakeDirectory(train_name);
915    gSystem->ChangeDirectory(train_name);
916    ofstream out;
917    out.open("ConfigTrain.C", ios::out); 
918    if (out.bad()) {
919       ::Error("AnalysisTrainNew.C::Export", "Cannot open ConfigTrain.C for writing");
920       return;
921    }
922    out << "{" << endl;
923    out << "   train_name      = " << "\"" << train_name.Data() << "\";" << endl;
924    out << "   proof_cluster   = " << "\"" << proof_cluster.Data() << "\";" << endl;
925    out << "   useAFPAR        = " << useAFPAR << ";" << endl;
926    if (useAFPAR) 
927       out << "   AFversion       = " << AFversion.Data() << ";" << endl;
928    out << "   proof_dataset   = " << "\"" << proof_dataset.Data() << "\";" << endl;
929    out << "   usePLUGIN       = " << usePLUGIN << ";" << endl;
930    out << "   usePAR          = " << usePAR << ";" << endl;
931    out << "   useCPAR         = " << useCPAR << ";" << endl;
932    out << "   root_version    = " << "\"" << root_version.Data() << "\";" << endl;
933    out << "   aliroot_version = " << "\"" << aliroot_version.Data() << "\";" << endl;
934    out << "   alien_datadir   = " << "\"" << alien_datadir.Data() << "\";" << endl;
935    if (!alien_outdir.Length()) alien_outdir = Form("output_%s",train_name.Data());
936    out << "   alien_outdir    = " << "\"" << alien_outdir.Data() << "\";" << endl;
937    out << "   maxMergeFiles   = " << maxMergeFiles << ";" << endl;
938    out << "   mergeExclude    = " << "\"" << mergeExclude.Data() << "\";" << endl;
939    out << "   nRunsPerMaster  = " << nRunsPerMaster << ";" << endl;
940    out << "   nFilesPerJob    = " << nFilesPerJob << ";" << endl;
941 //   for (Int_t i=0; i<10; i++) {
942 //      if (run_numbers[i]) 
943 //         out << "   run_numbers[" << i << "]  = " << run_numbers[i] << ";" << endl;
944 //   }
945    out << "   run_range[0]    = " << run_range[0] << ";" << endl;
946    out << "   run_range[1]    = " << run_range[1] << ";" << endl;
947    out << "   useDBG          = " << useDBG << ";" << endl;
948    out << "   useMC           = " << useMC << ";" << endl;
949    out << "   useTAGS         = " << useTAGS << ";" << endl;
950    out << "   useKFILTER      = " << useKFILTER << ";" << endl;
951    out << "   useTR           = " << useTR << ";" << endl;
952    out << "   useCORRFW       = " << useCORRFW << ";" << endl;
953    out << "   useAODTAGS      = " << useAODTAGS << ";" << endl;
954    out << "   saveTrain       = " << "kFALSE;" << endl << endl;
955    out << "   // Analysis modules" << endl;
956    out << "   iAODanalysis    = " << iAODanalysis << ";" << endl;
957    out << "   iAODhandler     = " << iAODhandler << ";" << endl;
958    out << "   iESDfilter      = " << iESDfilter << ";" << endl;
959    out << "   iMUONcopyAOD    = " << iMUONcopyAOD << ";" << endl;
960    out << "   iJETAN          = " << iJETAN << ";" << endl;
961    out << "   iPWG4partcorr   = " << iPWG4partcorr << ";" << endl;
962    out << "   iPWG2femto      = " << iPWG2femto << ";" << endl;
963    out << "   iPWG2spectra    = " << iPWG2spectra << ";" << endl;
964    out << "   iPWG2flow       = " << iPWG2flow << ";" << endl;
965    out << "   iPWG2res        = " << iPWG2res << ";" << endl;
966    out << "   iPWG2kink       = " << iPWG2kink << ";" << endl;
967    out << "}" << endl;
968    ::Info("AnalysisTrainNew.C::WriteConfig", "Train configuration wrote to file %s", Form("config_%s.C", train_name.Data()));
969    gSystem->ChangeDirectory(cdir);
970 }   
971
972 //______________________________________________________________________________
973 Bool_t LoadConfig(const char *filename)
974 {
975 // Read train configuration from file
976    if (gSystem->AccessPathName(filename)) {
977       ::Error("AnalysisTrainNew.C::LoadConfig", "Config file name not found");
978       return kFALSE;
979    }   
980    gROOT->ProcessLine(Form(".x %s", filename));
981    ::Info("AnalysisTrainNew.C::LoadConfig", "Train configuration loaded from file %s", filename);
982    return kTRUE;
983 }