]> git.uio.no Git - u/mrichter/AliRoot.git/blob - PWG/muondep/AliMuonAccEffSubmitter.cxx
Merge branch 'TPCdev' of https://git.cern.ch/reps/AliRoot into TPCdev
[u/mrichter/AliRoot.git] / PWG / muondep / AliMuonAccEffSubmitter.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-commercial purposes is hereby granted   *
9  * without fee, provided that the above copyright notice appears in all   *
10  * copies and that both the copyright notice and this permission notice   *
11  * appear in the supporting documentation. The authors make no claims     *
12  * about the suitability of this software for any purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15
16 //
17 // AliMuonAccEffSubmitter : a class to help submit Acc x Eff simulations
18 // anchored to real runs for J/psi, upsilon, single muons, etc...
19 //
20 // This class is dealing with 3 different directories :
21 //
22 // - template directory ($ALICE_ROOT/PWG/muondep/AccEffTemplates) containing the
23 //   basic template files to be used for a simuation. A template can contain
24 //   some variables that will be replaced during during the copy from template
25 //   to local dir
26 //
27 // - local directory, where the files from the template directory, are copied
28 //   once the class has been configured properly (i.e. using the various Set, Use,
29 //   etc... methods). Some other files (e.g. JDL ones) are generated from
30 //   scratch and also copied into this directory.
31 //   At this point one could(should) check the files, as they are the ones
32 //   to be copied to the remote directory for the production
33 //
34 // - remote directory, the alien directory where the files will be copied
35 //   (from the local directory) before the actual submission
36 //
37 // ==========================================================
38 //
39 // Basic usage
40 //
41 // AliMuonAccEffSubmitter a;
42 // a.UseOCDBSnapshots(kFALSE);
43 // a.SetRemoteDir("/alice/cern.ch/user/l/laphecet/Analysis/LHC13d/simjpsi/pp503z0");
44 // a.ShouldOverwriteFiles(true);
45 // a.MakeNofEventsPropToTriggerCount("CMUL7-B-NOPF-MUON");
46 // a.SetVar("VAR_GENLIB_PARNAME","\"pp 5.03\"");
47 // a.SetRunList(195682);
48 // a.Print();
49 // a.Run("test"); // will do everything but the submit
50 // a.Submit(false); // actual submission
51 //
52 //
53 // author: Laurent Aphecetche (Subatech
54 //
55
56 #include "AliMuonAccEffSubmitter.h"
57
58 #include "AliAnalysisTriggerScalers.h"
59 #include "AliLog.h"
60 #include "TFile.h"
61 #include "TGrid.h"
62 #include "TGridResult.h"
63 #include "TMap.h"
64 #include "TMath.h"
65 #include "TObjString.h"
66 #include "TROOT.h"
67 #include "TString.h"
68 #include "TSystem.h"
69 #include <vector>
70 #include <fstream>
71 using std::ifstream;
72 namespace
73 {
74   Int_t splitLevel=10;
75 }
76
77 ClassImp(AliMuonAccEffSubmitter)
78
79 //______________________________________________________________________________
80 AliMuonAccEffSubmitter::AliMuonAccEffSubmitter(const char* generator, Bool_t localOnly)
81 : AliMuonGridSubmitter(AliMuonGridSubmitter::kAccEff,localOnly),
82 fRatio(-1.0),
83 fFixedNofEvents(10000),
84 fMaxEventsPerChunk(5000),
85 fOCDBPath(""),
86 fSplitMaxInputFileNumber(20),
87 fCompactMode(1),
88 fExternalConfig(""),
89 fUseOCDBSnapshots(kFALSE),
90 fSnapshotDir(""),
91 fUseAODMerging(kFALSE)
92 {
93   // ctor
94   
95   TString ocdbPath("raw://");
96   
97   if (localOnly) {
98     ocdbPath = "local://$ALICE_ROOT/OCDB";
99   }
100   
101   SetOCDBPath(ocdbPath.Data());
102   
103   SetLocalDirectory("Snapshot",LocalDir());
104   
105   SetVar("VAR_OCDB_PATH",Form("\"%s\"",ocdbPath.Data()));
106
107   SetVar("VAR_GENPARAM_INCLUDE","AliGenMUONLib.h");
108   SetVar("VAR_GENPARAM_NPART","1");
109   SetVar("VAR_GENPARAM_GENLIB_TYPE","AliGenMUONlib::kJpsi");
110   SetVar("VAR_GENPARAM_GENLIB_PARNAME","\"pPb 5.03\"");
111
112   SetVar("VAR_GENCORRHF_QUARK","5");
113   SetVar("VAR_GENCORRHF_ENERGY","5");
114
115   // some default values for J/psi
116   SetVar("VAR_GENPARAMCUSTOM_PDGPARTICLECODE","443");
117
118   // default values below are from J/psi p+Pb (from muon_calo pass)
119   SetVar("VAR_GENPARAMCUSTOM_Y_P0","4.08E5");
120   SetVar("VAR_GENPARAMCUSTOM_Y_P1","7.1E4");
121   
122   SetVar("VAR_GENPARAMCUSTOM_PT_P0","1.13E9");
123   SetVar("VAR_GENPARAMCUSTOM_PT_P1","18.05");
124   SetVar("VAR_GENPARAMCUSTOM_PT_P2","2.05");
125   SetVar("VAR_GENPARAMCUSTOM_PT_P3","3.34");
126
127   // some default values for single muons
128   SetVar("VAR_GENPARAMCUSTOMSINGLE_PTMIN","0.35");
129   
130   SetVar("VAR_GENPARAMCUSTOMSINGLE_PT_P0","4.05962");
131   SetVar("VAR_GENPARAMCUSTOMSINGLE_PT_P1","1.0");
132   SetVar("VAR_GENPARAMCUSTOMSINGLE_PT_P2","2.46187");
133   SetVar("VAR_GENPARAMCUSTOMSINGLE_PT_P3","2.08644");
134
135   SetVar("VAR_GENPARAMCUSTOMSINGLE_Y_P0","0.729545");
136   SetVar("VAR_GENPARAMCUSTOMSINGLE_Y_P1","0.53837");
137   SetVar("VAR_GENPARAMCUSTOMSINGLE_Y_P2","0.141776");
138   SetVar("VAR_GENPARAMCUSTOMSINGLE_Y_P3","0.0130173");
139
140   SetVar("VAR_PURELY_LOCAL",Form("%d",localOnly));
141   
142   SetVar("VAR_SIM_ALIGNDATA","\"alien://folder=/alice/simulation/2008/v4-15-Release/Ideal\"");
143   
144   SetVar("VAR_REC_ALIGNDATA","\"alien://folder=/alice/simulation/2008/v4-15-Release/Residual\"");
145   
146   UseOCDBSnapshots(fUseOCDBSnapshots);
147   
148   SetGenerator(generator);
149   
150   MakeNofEventsPropToTriggerCount();
151   
152   AddToTemplateFileList("CheckESD.C");
153   AddToTemplateFileList("CheckAOD.C");
154   AddToTemplateFileList("AODtrain.C");
155   AddToTemplateFileList("validation.sh");
156   
157   AddToTemplateFileList("Config.C");
158   AddToTemplateFileList("rec.C");
159   AddToTemplateFileList("sim.C");
160   AddToTemplateFileList("simrun.C");
161   AddToTemplateFileList(RunJDLName().Data());
162   
163   UseExternalConfig(fExternalConfig);
164 }
165
166 //______________________________________________________________________________
167 AliMuonAccEffSubmitter::~AliMuonAccEffSubmitter()
168 {
169   // dtor
170 }
171
172 ///______________________________________________________________________________
173 Bool_t AliMuonAccEffSubmitter::Generate(const char* jdlname) const
174 {
175   if ( TString(jdlname).Contains("merge",TString::kIgnoreCase) )
176   {
177     return GenerateMergeJDL(jdlname);
178   }
179   else
180   {
181     return GenerateRunJDL(jdlname);
182   }
183 }
184
185 ///______________________________________________________________________________
186 Bool_t AliMuonAccEffSubmitter::GenerateMergeJDL(const char* name) const
187 {
188   /// Create the JDL for merging jobs
189   /// FIXME: not checked !
190   
191   AliDebug(1,"");
192
193   std::ostream* os = CreateJDLFile(name);
194   
195   if (!os)
196   {
197     return kFALSE;
198   }
199   
200   Bool_t final = TString(name).Contains("merge",TString::kIgnoreCase);
201
202   (*os) << "# Generated merging jdl (production mode)" << std::endl
203   << "# $1 = run number" << std::endl
204   << "# $2 = merging stage" << std::endl
205   << "# Stage_<n>.xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip" << std::endl;
206
207   OutputToJDL(*os,"Packages",
208          GetMapValue("AliRoot"),
209          GetMapValue("Geant3"),
210          GetMapValue("Root"),
211          GetMapValue("API"));
212   
213   OutputToJDL(*os,"Executable","AOD_merge.sh");
214   
215   OutputToJDL(*os,"Price","1");
216
217   if ( final )
218   {
219     OutputToJDL(*os,"Jobtag","comment: AliMuonAccEffSubmitter final merging");
220   }
221   else
222   {
223     OutputToJDL(*os,"Jobtag","comment: AliMuonAccEffSubmitter merging stage $2");
224   }
225   
226   OutputToJDL(*os,"Workdirectorysize","5000MB");
227   
228   OutputToJDL(*os,"Validationcommand",Form("%s/validation_merge.sh",RemoteDir().Data()));
229   
230   OutputToJDL(*os,"TTL","7200");
231
232   OutputToJDL(*os,"OutputArchive",
233     "log_archive.zip:stderr,stdout@disk=1",
234     "root_archive.zip:AliAOD.root,AliAOD.Muons.root,AnalysisResults.root@disk=3"
235          );
236   
237   OutputToJDL(*os,"Arguments",(final ? "2":"1")); // for AOD_merge.sh, 1 means intermediate merging stage, 2 means final merging
238   
239   if ( !final )
240   {
241     OutputToJDL(*os,"InputFile",Form("LF:%s/AODtrain.C",RemoteDir().Data()));
242     OutputToJDL(*os,"OutputDir",Form("%s/$1/Stage_$2/#alien_counter_03i#",RemoteDir().Data()));
243     OutputToJDL(*os,"InputDataCollection",Form("%s/$1/Stage_$2.xml,nodownload",RemoteDir().Data()));
244     OutputToJDL(*os,"split","se");
245     OutputToJDL(*os,"SplitMaxInputFileNumber",GetSplitMaxInputFileNumber());
246     OutputToJDL(*os,"InputDataListFormat","xml-single");
247     OutputToJDL(*os,"InputDataList","wn.xml");
248   }
249   else
250   {
251     OutputToJDL(*os,"InputFile",Form("LF:%s/AODtrain.C",RemoteDir().Data()),
252            Form("LF:%s/$1/wn.xml",RemoteDir().Data()));
253     OutputToJDL(*os,"OutputDir",Form("%s/$1",RemoteDir().Data()));
254   }
255   
256   return kTRUE;
257 }
258
259 //______________________________________________________________________________
260 Bool_t AliMuonAccEffSubmitter::GenerateRunJDL(const char* name) const
261 {
262   /// Generate (locally) the JDL to perform the simulation+reco+aod filtering
263   /// (to be then copied to the grid and finally submitted)
264   
265   AliDebug(1,"");
266
267   std::ostream* os = CreateJDLFile(name);
268   
269   if (!os)
270   {
271     return kFALSE;
272   }
273   
274   OutputToJDL(*os,"Packages",
275               GetMapValue("AliRoot"),
276               GetMapValue("Geant3"),
277               GetMapValue("Root"),
278               GetMapValue("API"));
279               
280   OutputToJDL(*os,"Jobtag","comment: AliMuonAccEffSubmitter RUN $1");
281
282   OutputToJDL(*os,"split","production:1-$2");
283
284   OutputToJDL(*os,"Price","1");
285   
286   OutputToJDL(*os,"OutputDir",Form("%s/$1/#alien_counter_03i#",RemoteDir().Data()));
287
288   OutputToJDL(*os,"Executable","/alice/bin/aliroot_new");
289   
290   TObjArray files;
291   files.SetOwner(kTRUE);
292   TIter next(LocalFileList());
293   TObjString* file;
294   
295   while ( ( file = static_cast<TObjString*>(next())) )
296   {
297     if ( !file->String().Contains(".jdl",TString::kIgnoreCase) ||
298          !file->String().Contains("OCDB_") )
299     {
300       files.Add(new TObjString(Form("LF:%s/%s",RemoteDir().Data(),file->String().Data())));
301     }
302   }
303   
304   if ( fUseOCDBSnapshots )
305   {
306     files.Add(new TObjString(Form("LF:%s/OCDB/$1/OCDB_sim.root",RemoteDir().Data())));
307     files.Add(new TObjString(Form("LF:%s/OCDB/$1/OCDB_rec.root",RemoteDir().Data())));
308   }
309   
310   OutputToJDL(*os,"InputFile",files);
311   
312   if ( CompactMode() == 0 )
313   {
314     // store everything
315     OutputToJDL(*os,"OutputArchive",  "log_archive.zip:stderr,stdout,aod.log,checkaod.log,checkesd.log,rec.log,sim.log@disk=1",
316            "root_archive.zip:galice*.root,Kinematics*.root,TrackRefs*.root,AliESDs.root,AliAOD.root,AliAOD.Muons.root,Merged.QA.Data.root,Run*.root@disk=2");
317   }
318   else if ( CompactMode() == 1 )
319   {
320     // keep only muon AODs and QA
321     OutputToJDL(*os,"OutputArchive",  "log_archive.zip:stderr,stdout,aod.log,checkaod.log,checkesd.log,rec.log,sim.log@disk=1",
322            "root_archive.zip:galice*.root,AliAOD.Muons.root,Merged.QA.Data.root@disk=2");
323   }
324   else
325   {
326     AliError(Form("Unknown CompactMode %d",CompactMode()));
327     delete os;
328     return kFALSE;
329   }
330   
331   OutputToJDL(*os,"splitarguments","simrun.C --run $1 --chunk #alien_counter# --event $3");
332   
333   OutputToJDL(*os,"Workdirectorysize","5000MB");
334   
335   OutputToJDL(*os,"JDLVariables","Packages","OutputDir");
336
337   OutputToJDL(*os,"Validationcommand",Form("%s/validation.sh",RemoteDir().Data()));
338
339   OutputToJDL(*os,"TTL","72000");
340   
341   return kTRUE;
342 }
343
344 //______________________________________________________________________________
345 Bool_t AliMuonAccEffSubmitter::MakeOCDBSnapshots()
346 {
347   /// Run sim.C and rec.C in a special mode to generate OCDB snapshots
348   /// Can only be done after the templates have been copied locally
349   
350   if (!IsValid()) return kFALSE;
351
352   if (!fUseOCDBSnapshots) return kTRUE;
353   
354   if (!NofRuns()) return kFALSE;
355   
356   AliDebug(1,"");
357
358   Bool_t ok(kTRUE);
359   
360   const std::vector<int>& runs = RunList();
361   
362   for ( std::vector<int>::size_type i = 0; i < runs.size(); ++i )
363   {
364     Int_t runNumber = runs[i];
365
366     TString ocdbSim(Form("%s/OCDB/%d/OCDB_sim.root",SnapshotDir().Data(),runNumber));
367     TString ocdbRec(Form("%s/OCDB/%d/OCDB_rec.root",SnapshotDir().Data(),runNumber));
368
369     if ( !gSystem->AccessPathName(ocdbSim.Data()) &&
370          !gSystem->AccessPathName(ocdbRec.Data()) )
371     {
372       AliWarning(Form("Local OCDB snapshots already there for run %d. Will not redo them. If you want to force them, delete them by hand !",runNumber));
373       continue;
374     }
375     else
376     {
377       gSystem->Exec(Form("aliroot -b -q -x simrun.C --run %d --snapshot",runNumber));
378     
379       if ( gSystem->AccessPathName(ocdbSim.Data()) )
380       {
381         AliError(Form("Could not create OCDB snapshot for simulation"));
382         ok = kFALSE;
383       }
384
385       if ( gSystem->AccessPathName(ocdbRec.Data()) )
386       {
387         AliError(Form("Could not create OCDB snapshot for reconstruction"));
388         ok = kFALSE;
389       }
390     }
391     
392     AddToLocalFileList(ocdbSim);
393     AddToLocalFileList(ocdbRec);
394   }
395   
396   return ok;
397 }
398
399 //______________________________________________________________________________
400 Bool_t AliMuonAccEffSubmitter::Merge(Int_t stage, Bool_t dryRun)
401 {
402   /// Submit multiple merging jobs with the format "submit AOD_merge(_final).jdl run# (stage#)".
403   /// Also produce the xml collection before sending jobs
404   /// Initial AODs will be taken from fRemoteDir/[RUNNUMBER] while the merged
405   /// ones will be put into fMergedDir/AODs/[RUNNUMBER]
406   ///
407   /// Example:
408   /// - inDir = "/alice/sim/2012/LHC12a10_bis" (where to find the data to merge)
409   ///         = 0x0 --> inDir = homeDir/outDir/resDir
410   /// - outDir = "Sim/LHC11h/embedding/AODs" (where to store merged results)
411   /// - runList.txt must contains the list of run number
412   /// - stage=0 --> final merging / stage>0 --> intermediate merging i
413   ///
414   
415   if (!RemoteDirectoryExists(MergedDir().Data())) {
416     AliError(Form("directory %s does not exist", MergedDir().Data()));
417     return kFALSE;
418   }
419   
420   gGrid->Cd(MergedDir().Data());
421   
422   TString jdl = MergeJDLName(stage==0);
423   
424   if (!RemoteFileExists(jdl.Data()))
425   {
426     AliError(Form("file %s does not exist in %s\n", jdl.Data(), RemoteDir().Data()));
427     return kFALSE;
428   }
429   
430   const std::vector<int>& runs = RunList();
431   
432   if (runs.empty())
433   {
434     AliError("No run to work with");
435     return kFALSE;
436   }
437
438   TString currRun;
439   TString reply = "";
440   gSystem->Exec("rm -f __failed__");
441   Bool_t failedRun = kFALSE;
442   
443   for ( std::vector<int>::size_type i = 0; i < runs.size(); ++i )
444   {
445     Int_t run = runs[i];
446     AliInfo(Form("\n --- processing run %d ---\n", run));
447     
448     TString runDir = Form("%s/%d", MergedDir().Data(), run);
449     
450     if (!RemoteDirectoryExists(runDir.Data()))
451     {
452       AliInfo(Form(" - creating output directory %s\n", runDir.Data()));
453       gSystem->Exec(Form("alien_mkdir -p %s", runDir.Data()));
454     }
455     
456     if (RemoteFileExists(Form("%s/root_archive.zip", runDir.Data())))
457     {
458       AliWarning(" ! final merging already done");
459       continue;
460     }
461     
462     Int_t lastStage = GetLastStage(runDir.Data());
463     
464     if (stage > 0 && stage != lastStage+1)
465     {
466       AliError(Form(" ! lastest merging stage = %d. Next must be stage %d or final stage\n", lastStage, lastStage+1));
467       continue;
468     }
469     
470     TString wn = (stage > 0) ? Form("Stage_%d.xml", stage) : "wn.xml";
471     TString find = (lastStage == 0) ?
472     Form("alien_find -x %s %s/%d *root_archive.zip", wn.Data(), RemoteDir().Data(), run) :
473     Form("alien_find -x %s %s/%d/Stage_%d *root_archive.zip", wn.Data(), RemoteDir().Data(), run, lastStage);
474     gSystem->Exec(Form("%s 1> %s 2>/dev/null", find.Data(), wn.Data()));
475     gSystem->Exec(Form("grep -c /event %s > __nfiles__", wn.Data()));
476     ifstream f2("__nfiles__");
477     TString nFiles;
478     nFiles.ReadLine(f2,kTRUE);
479     f2.close();
480     gSystem->Exec("rm -f __nfiles__");
481     printf(" - number of files to merge = %d\n", nFiles.Atoi());
482     if (nFiles.Atoi() == 0) {
483       printf(" ! collection of files to merge is empty\n");
484       gSystem->Exec(Form("rm -f %s", wn.Data()));
485       continue;
486     } else if (stage > 0 && nFiles.Atoi() <= splitLevel && !reply.BeginsWith("y")) {
487       if (!reply.BeginsWith("n")) {
488         printf(" ! number of files to merge <= split level (%d). Continue? [Y/n] ", splitLevel);
489         fflush(stdout);
490         reply.Gets(stdin,kTRUE);
491         reply.ToLower();
492       }
493       if (reply.BeginsWith("n")) {
494         gSystem->Exec(Form("rm -f %s", wn.Data()));
495         continue;
496       } else reply = "y";
497     }
498     
499     if (!dryRun)
500     {
501       TString dirwn = Form("%s/%s", runDir.Data(), wn.Data());
502       if (RemoteFileExists(dirwn.Data())) gGrid->Rm(dirwn.Data());
503       gSystem->Exec(Form("alien_cp file:%s alien://%s", wn.Data(), dirwn.Data()));
504       gSystem->Exec(Form("rm -f %s", wn.Data()));
505     }
506     
507     TString query;
508     if (stage > 0) query = Form("submit %s %d %d", jdl.Data(), run, stage);
509     else query = Form("submit %s %d", jdl.Data(), run);
510     printf(" - %s ...", query.Data());
511     fflush(stdout);
512     
513     if (dryRun)
514     {
515       AliInfo(" dry run");
516       continue;
517     }
518     
519     Bool_t done = kFALSE;
520     TGridResult *res = gGrid->Command(query);
521     if (res)
522     {
523       TString cjobId1 = res->GetKey(0,"jobId");
524       if (!cjobId1.IsDec())
525       {
526         AliError(" FAILED");
527         gGrid->Stdout();
528         gGrid->Stderr();
529       }
530       else
531       {
532         AliInfo(Form(" DONE\n   --> the job Id is: %s \n", cjobId1.Data()));
533         done = kTRUE;
534       }
535       delete res;
536     }
537     else
538     {
539       AliError(" FAILED");
540     }
541     
542     if (!done)
543     {
544       gSystem->Exec(Form("echo %d >> __failed__", run));
545       failedRun = kTRUE;
546     }
547     
548   }
549   
550   if (failedRun)
551   {
552     AliInfo("\n--------------------\n");
553     AliInfo("list of failed runs:\n");
554     gSystem->Exec("cat __failed__");
555     gSystem->Exec("rm -f __failed__");
556     return kFALSE;
557   }
558   
559   return kTRUE;
560 }
561
562 //______________________________________________________________________________
563 void AliMuonAccEffSubmitter::Print(Option_t* opt) const
564 {
565   /// Printout
566   
567   AliMuonGridSubmitter::Print(opt);
568
569   if ( fRatio > 0 )
570   {
571     std::cout << Form("For each run, will generate %5.2f times the number of real events for trigger %s",
572                       fRatio,ReferenceTrigger().Data()) << std::endl;
573   }
574   else
575   {
576     std::cout << Form("For each run, will generate %10d events",fFixedNofEvents) << std::endl;
577   }
578   
579   std::cout << "MaxEventsPerChunk = " << fMaxEventsPerChunk << std::endl;
580   
581   std::cout << "Will" << (fUseOCDBSnapshots ? "" : " NOT") << " use OCDB snaphosts" << std::endl;
582 }
583
584 //______________________________________________________________________________
585 Bool_t AliMuonAccEffSubmitter::Run(const char* mode)
586 {
587   /// mode can be one of (case insensitive)
588   ///
589   /// LOCAL : copy the template files from the template directory to the local one
590   /// UPLOAD : copy the local files to the grid (requires LOCAL)
591   /// OCDB : make ocdb snapshots (requires LOCAL)
592   /// SUBMIT : submit the jobs (requires LOCAL + UPLOAD)
593   /// FULL : all of the above (requires all of the above)
594   ///
595   /// TEST : as SUBMIT, but in dry mode (does not actually submit the jobs)
596   ///
597   /// LOCALTEST : completely local test (including execution)
598   
599   if (!IsValid()) return kFALSE;
600   
601   TString smode(mode);
602   smode.ToUpper();
603   
604   if ( smode == "FULL")
605   {
606     return  ( Run("LOCAL") && Run("OCDB") && Run("UPLOAD") && Run("SUBMIT") );
607   }
608   
609   if ( smode == "LOCAL")
610   {
611     return CopyTemplateFilesToLocal();
612   }
613   
614   if ( smode == "UPLOAD" )
615   {
616     return (CopyLocalFilesToRemote());
617   }
618   
619   if ( smode == "OCDB" )
620   {
621     Bool_t ok = Run("LOCAL");
622     if (ok)
623     {
624       ok = MakeOCDBSnapshots();
625     }
626     return ok;
627   }
628   
629   if ( smode == "TEST" )
630   {
631     Bool_t ok = Run("LOCAL") && Run("OCDB") && Run("UPLOAD");
632     if ( ok )
633     {
634       ok = (Submit(kTRUE)>0);
635     }
636     return ok;
637   }
638   
639   if ( smode == "FULL" )
640   {
641     Bool_t ok = Run("LOCAL")  && Run("OCDB") && Run("UPLOAD");
642     if ( ok )
643     {
644       ok = (Submit(kFALSE)>0);
645     }
646     return ok;
647   }
648
649   if( smode == "SUBMIT" )
650   {
651     return (Submit(kFALSE)>0);
652   }
653   
654   if ( smode == "LOCALTEST" )
655   {
656     Bool_t ok = Run("LOCAL");
657     if ( ok )
658     {
659       ok = LocalTest();
660     }
661     return ok;
662   }
663   
664   return kFALSE;
665 }
666
667 //______________________________________________________________________________
668 Bool_t AliMuonAccEffSubmitter::SetGenerator(const char* generator)
669 {
670   // set the variable to select the generator macro in Config.C
671   
672   gSystem->Load("libEVGEN");
673   
674   Invalidate();
675   
676   TString generatorFile(Form("%s/%s.C",TemplateDir().Data(),generator));
677   
678   Int_t nofMissingVariables(0);
679   
680   // first check we indeed have such a macro
681   if (!gSystem->AccessPathName(generatorFile.Data()))
682   {
683     TObjArray* variables = GetVariables(generatorFile.Data());
684     
685     TIter next(variables);
686     TObjString* var;
687     
688     while ( ( var = static_cast<TObjString*>(next())) )
689     {
690       if ( !Vars()->GetValue(var->String()) )
691       {
692         ++nofMissingVariables;
693         AliError(Form("file %s expect the variable %s to be defined, but we've not defined it !",generatorFile.Data(),var->String().Data()));
694       }
695     }
696     
697     delete variables;
698     
699     if ( !nofMissingVariables )
700     {
701       if (CheckCompilation(generatorFile.Data()))
702       {
703         Validate();
704         SetVar("VAR_GENERATOR",Form("%s",generator));        
705         AddToTemplateFileList(Form("%s.C",generator));
706         return kTRUE;
707       }
708     }
709     else
710     {
711       return kFALSE;
712     }
713   }
714   else
715   {
716     AliError(Form("Can not work with the macro %s",generatorFile.Data()));
717   }
718   return kFALSE;
719 }
720
721 //______________________________________________________________________________
722 void AliMuonAccEffSubmitter::SetOCDBPath(const char* ocdbPath)
723 {
724   /// Sets the OCDB path to be used
725   
726   SetMapKeyValue("OCDBPath",ocdbPath);
727 }
728
729
730 //______________________________________________________________________________
731 void AliMuonAccEffSubmitter::SetOCDBSnapshotDir(const char* dir)
732 {
733   // change the directory used for snapshot
734   
735   if (gSystem->AccessPathName(Form("%s/OCDB",dir)))
736   {
737     AliError(Form("Snapshot top directory (%s) should contain an OCDB subdir with runnumbers in there",dir));
738   }
739   else
740   {
741     SetMapKeyValue("OCDBSnapshot",dir);
742   }
743 }
744
745 //______________________________________________________________________________
746 void AliMuonAccEffSubmitter::MakeNofEventsPropToTriggerCount(const char* trigger, Float_t ratio)
747 {
748   SetMapKeyValue("ReferenceTrigger",trigger);
749   fRatio = ratio;
750 }
751
752 //______________________________________________________________________________
753 void AliMuonAccEffSubmitter::MakeNofEventsFixed(Int_t nevents)
754 {
755   fFixedNofEvents = nevents;
756   fRatio=0.0;
757   SetMapKeyValue("ReferenceTrigger","");
758 }
759
760 //______________________________________________________________________________
761 Int_t AliMuonAccEffSubmitter::LocalTest()
762 {
763   /// Generate a local macro (simrun.sh) to execute locally a full scale test
764   /// Can only be used with a fixed number of events (and runnumber is fixed to zero)
765   
766   if ( fRatio > 0 )
767   {
768     AliError("Can only work in local test with a fixed number of events");
769     return 0;
770   }
771   
772   if ( fFixedNofEvents <= 0 )
773   {
774     AliError("Please fix the number of input events using MakeNofEventsFixed()");
775     return 0;
776   }
777   
778   const std::vector<int>& runs = RunList();
779
780   std::cout << "Generating script to execute : ./simrun.sh" << std::endl;
781
782   std::ofstream out("simrun.sh");
783   
784   out << "#!/bin/bash" << std::endl;
785 //  root.exe -b -q simrun.C  --run <x> --chunk <y> --event <n>
786   out << "root.exe -b -q simrun.C --run "<< runs[0] <<" --event " << fFixedNofEvents << std::endl;
787  
788   gSystem->Exec("chmod +x simrun.sh");
789   
790   std::cout << "Executing the script : ./simrun.sh" << std::endl;
791
792   gSystem->Exec("./simrun.sh");
793   
794   return 1;
795 }
796
797 //______________________________________________________________________________
798 Int_t AliMuonAccEffSubmitter::Submit(Bool_t dryRun)
799 {
800   /// Submit multiple production jobs with the format "submit jdl 000run#.xml 000run#".
801   ///
802   /// Return the number of submitted (master) jobs
803   ///
804   /// Example:
805   /// - outputDir = "/alice/cern.ch/user/p/ppillot/Sim/LHC10h/JPsiPbPb276/AlignRawVtxRaw/ESDs"
806   /// - runList must contains the list of run number
807   /// - trigger is the (fully qualified) trigger name used to compute the base number of events
808   /// - mult is the factor to apply to the number of trigger to get the number of events to be generated
809   ///   (# generated events = # triggers x mult
810   
811   if (!IsValid()) return 0;
812   
813   AliDebug(1,"");
814
815   gGrid->Cd(RemoteDir());
816   
817   if (!RemoteFileExists(RunJDLName()))
818   {
819     AliError(Form("file %s does not exist in %s", RunJDLName().Data(), RemoteDir().Data()));
820     return 0;
821   }
822   
823   if ( !NofRuns() )
824   {
825     AliError("No run list set. Use SetRunList");
826     return 0;
827   }
828   const std::vector<int>& runs = RunList();
829   
830   if (runs.empty())
831   {
832     AliError("No run to work with");
833     return 0;
834   }
835   
836   //  cout << "total number of selected MB events = " << totEvt << endl;
837   //  cout << "required number of generated events = " << nGenEvents << endl;
838   //  cout << "number of generated events per MB event = " << ratio << endl;
839   //  cout << endl;
840   
841   std::cout << "run\tchunks\tevents" << std::endl;
842   std::cout << "----------------------" << std::endl;
843   
844   Int_t nJobs(0);
845   Int_t nEvts(0);
846   
847   AliAnalysisTriggerScalers* ts(0x0);
848   
849   for (std::vector<int>::size_type i=0; i < runs.size(); ++i)
850   {
851     Int_t runNumber = runs[i];
852     
853     Int_t nEvtRun(fFixedNofEvents);
854     
855     if ( fRatio > 0 )
856     {
857       if (!ts)
858       {
859         AliInfo(Form("Creating AliAnalysisTriggerScalers from OCDB=%s",OCDBPath().Data()));
860         ts = new AliAnalysisTriggerScalers(runs,OCDBPath().Data());
861       }
862       
863       AliAnalysisTriggerScalerItem* trigger = ts->GetTriggerScaler(runNumber, "L2A", ReferenceTrigger().Data());
864     
865       if (!trigger)
866       {
867         AliError(Form("Could not get trigger %s for run %09d",ReferenceTrigger().Data(),runNumber));
868         continue;
869       }
870       nEvtRun = TMath::Nint(fRatio * trigger->Value());
871     }
872     
873     Int_t nChunk = 1;
874     
875     while (nEvtRun/nChunk+0.5 > MaxEventsPerChunk())
876     {
877       ++nChunk;
878     }
879     
880     Int_t nEvtChunk = TMath::Nint(nEvtRun/nChunk + 0.5);
881     
882     nJobs += nChunk;
883     
884     nEvts += nChunk*nEvtChunk;
885     
886     std::cout << runNumber << "\t" << nChunk << "\t" << nEvtChunk << std::endl;
887     
888     TString query(Form("submit %s %d %d %d", RunJDLName().Data(), runNumber, nChunk, nEvtChunk));
889     
890     std::cout << query.Data() << " ..." << std::flush;
891     
892     TGridResult* res = 0x0;
893     
894     if (!dryRun)
895     {
896       res = gGrid->Command(query);
897     }
898     
899     if (res)
900     {
901       TString cjobId1 = res->GetKey(0,"jobId");
902       
903       if (!cjobId1.Length())
904       {
905         std::cout << " FAILED" << std::endl << std::endl;
906         gGrid->Stdout();
907         gGrid->Stderr();
908       }
909       else
910       {
911         std::cout << "DONE" << std::endl;
912         std::cout << Form("   --> the job Id is: %s",cjobId1.Data()) << std::endl << std::endl;
913       }
914     }
915     else
916     {
917       std::cout << " FAILED" << std::endl << std::endl;
918     }
919     
920     delete res;
921   }
922   
923   std::cout << std::endl
924   << "total number of jobs = " << nJobs << std::endl
925   << "total number of generated events = " << nEvts << std::endl
926   << std::endl;
927   
928   delete ts;
929   
930   return nJobs;
931 }
932
933 //______________________________________________________________________________
934 void AliMuonAccEffSubmitter::UpdateLocalFileList(Bool_t clearSnapshots)
935 {
936   /// Update the list of local files
937   
938   AliMuonGridSubmitter::UpdateLocalFileList();
939   
940   if (!NofRuns()) return;
941   
942   if ( clearSnapshots )
943   {
944     TIter next(LocalFileList());
945     TObjString* file;
946     
947     while ( ( file = static_cast<TObjString*>(next())) )
948     {
949       if ( file->String().Contains("OCDB_") )
950       {
951         LocalFileList()->Remove(file);
952       }
953     }
954     LocalFileList()->Compress();
955   }
956
957   const char* type[] = { "sim","rec" };
958   
959   const std::vector<int>& runs = RunList();
960   
961   for ( std::vector<int>::size_type i = 0; i < runs.size(); ++i )
962   {
963     Int_t runNumber = runs[i];
964     
965     for ( Int_t t = 0; t < 2; ++t )
966     {
967       TString snapshot(Form("%s/OCDB/%d/OCDB_%s.root",SnapshotDir().Data(),runNumber,type[t]));
968       
969       if ( !gSystem->AccessPathName(snapshot.Data()) )
970       {
971         AddToLocalFileList(snapshot);
972       }
973     }
974   }
975 }
976
977 //______________________________________________________________________________
978 void AliMuonAccEffSubmitter::UseOCDBSnapshots(Bool_t flag)
979 {
980   /// Whether or not to use OCDB snapshots
981   /// Using OCDB snapshots will speed-up both the sim and reco initialization
982   /// phases on each worker node, but takes time to produce...
983   /// So using them is not always a win-win...
984   
985   fUseOCDBSnapshots = flag;
986   if ( flag )
987   {
988     SetVar("VAR_OCDB_SNAPSHOT","kTRUE");
989   }
990   else
991   {
992     SetVar("VAR_OCDB_SNAPSHOT","kFALSE");
993   }
994   
995   UpdateLocalFileList();
996 }
997
998 //______________________________________________________________________________
999 void AliMuonAccEffSubmitter::UseAODMerging(Bool_t flag)
1000 {
1001   /// whether or not we should generate JDL for merging AODs
1002   
1003   fUseAODMerging = flag;
1004   
1005   AddToTemplateFileList(MergeJDLName(kFALSE).Data());
1006   AddToTemplateFileList(MergeJDLName(kTRUE).Data());
1007   AddToTemplateFileList("AOD_merge.sh");
1008   AddToTemplateFileList("validation_merge.sh");
1009 }
1010
1011 //______________________________________________________________________________
1012 void AliMuonAccEffSubmitter::UseExternalConfig(const char* externalConfigFullFilePath)
1013 {
1014   // use an external config (or the default Config.C if externalConfigFullFilePath="")
1015   
1016   fExternalConfig = externalConfigFullFilePath;
1017   if ( fExternalConfig.Length() > 0 )
1018   {
1019     AddToTemplateFileList(fExternalConfig);
1020   }
1021   else
1022   {
1023     AddToTemplateFileList("Config.C");
1024   }
1025 }