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