]> git.uio.no Git - u/mrichter/AliRoot.git/blame - PWG/muondep/AliMuonAccEffSubmitter.cxx
New classes for getting the results out of the output of AliAnalysisTaskMuMu: AliAnal...
[u/mrichter/AliRoot.git] / PWG / muondep / AliMuonAccEffSubmitter.cxx
CommitLineData
a58729a5 1#include "AliMuonAccEffSubmitter.h"
2
3#include "AliAnalysisTriggerScalers.h"
4#include "AliLog.h"
5#include "TFile.h"
6#include "TGrid.h"
7#include "TGridResult.h"
8#include "TMap.h"
9#include "TMath.h"
10#include "TObjString.h"
11#include "TString.h"
12#include "TSystem.h"
13#include <vector>
14
15namespace
16{
17 Int_t splitLevel=10;
18}
19
20//______________________________________________________________________________
21AliMuonAccEffSubmitter::AliMuonAccEffSubmitter()
22: TObject(),
23fScalers(0x0),
24fRemoteDir(""),
25fReferenceTrigger(""),
26fRatio(1.0),
27fMaxEventsPerChunk(5000),
28fLocalDir(gSystem->pwd()),
29fOCDBPath("raw://"),
30fTemplateDir(gSystem->ExpandPathName("$ALICE_ROOT/PWG/muondep/AccEffTemplates")),
31fPackageAliroot(),
32fPackageGeant3(),
33fPackageRoot(),
34fPackageApi(),
35fMergedDir(Form("%s/AODs",fRemoteDir.Data())),
36fSplitMaxInputFileNumber(20),
37fCompactMode(1),
38fShouldOverwriteFiles(kFALSE),
39fVars(0x0),
40fExternalConfig(""),
41fUseOCDBSnapshots(kTRUE),
42fIsValid(kFALSE),
43fTemplateFileList(0x0),
44fLocalFileList(0x0),
45fSnapshotDir(fLocalDir)
46{
47 // ctor
48
49 if (!TGrid::Connect("alien://"))
50 {
51 AliError("cannot connect to grid");
52 fIsValid = kFALSE;
53 }
54
55 SetPackages("VO_ALICE@AliRoot::v5-03-Rev-09","VO_ALICE@GEANT3::v1-14-6","VO_ALICE@ROOT::v5-34-02-1");
56
57// SetVar("VAR_ENERGY","5.03");
58 SetVar("VAR_GENLIB_TYPE","AliGenMUONlib::kJpsi");
59 SetVar("VAR_GENLIB_PARNAME","\"pPb 5.03\"");
60 SetVar("VAR_OCDB_PATH","\"raw://\"");
61 UseOCDBSnapshots(kTRUE);
62}
63
64//______________________________________________________________________________
65AliMuonAccEffSubmitter::~AliMuonAccEffSubmitter()
66{
67 // dtor
68 delete fScalers;
69 delete fTemplateFileList;
70 delete fLocalFileList;
71 delete fVars;
72}
73
74//______________________________________________________________________________
75Bool_t AliMuonAccEffSubmitter::CheckLocal() const
76{
77 /// Check whether all required local files are there
78 TIter next(LocalFileList());
79 TObjString* file;
80
81 while ( ( file = static_cast<TObjString*>(next())) )
82 {
83 if ( gSystem->AccessPathName(file->String().Data()) )
84 {
85 return kFALSE;
86 }
87 }
88
89 return kTRUE;
90}
91
92//______________________________________________________________________________
93Bool_t AliMuonAccEffSubmitter::CheckRemote() const
94{
95 /// Check whether all required remote files are there
96 AliWarning("implement me");
97 return kFALSE;
98}
99
100//______________________________________________________________________________
101void AliMuonAccEffSubmitter::CleanLocal(Bool_t cleanSnapshots) const
102{
103 /// Clean (remove) local generated files
104 /// As OCDB snapshot creation is a long process, cleanSnapshots
105 /// is kFALSE by default in order not to delete those.
106
107 TIter next(LocalFileList());
108 TObjString* file;
109
110 while ( ( file = static_cast<TObjString*>(next())) )
111 {
112 if ( !cleanSnapshots && file->String().Contains("OCDB_") ) continue;
113 gSystem->Unlink(file->String().Data());
114 }
115}
116
117//______________________________________________________________________________
118void AliMuonAccEffSubmitter::CleanRemote() const
119{
120 /// Clean (remove) remote files
121 AliWarning("implement me");
122}
123
124//______________________________________________________________________________
125Bool_t AliMuonAccEffSubmitter::CopyFile(const char* localFile)
126{
127 TString local;
128
129 if ( gSystem->IsAbsoluteFileName(localFile) )
130 {
131 local = localFile;
132 }
133 else
134 {
135 local = Form("%s/%s",fLocalDir.Data(),gSystem->ExpandPathName(localFile));
136 }
137
138 if (gSystem->AccessPathName(local.Data()))
139 {
140 AliError(Form("Local file %s does not exist",local.Data()));
141 return kFALSE;
142 }
143
144 TString remote;
145
146 remote += fRemoteDir;
147 remote += "/";
148
149 if ( gSystem->IsAbsoluteFileName(localFile) )
150 {
151 TString tmp(localFile);
152 tmp.ReplaceAll(fSnapshotDir.Data(),"");
153 remote += tmp;
154 }
155 else
156 {
157 remote += localFile;
158 }
159
160 TString dirName = gSystem->DirName(remote.Data());
161
162 Bool_t ok(kTRUE);
163
164 if (!RemoteDirectoryExists(dirName.Data()))
165 {
166 ok = gGrid->Mkdir(dirName.Data(),"-p");
167 }
168
169 if ( ok )
170 {
171 return TFile::Cp(local.Data(),Form("alien://%s",remote.Data()));
172 }
173 else
174 {
175 return kFALSE;
176 }
177}
178
179//______________________________________________________________________________
180Bool_t AliMuonAccEffSubmitter::CheckRemoteDir() const
181{
182 /// Check we have a grid connection and that the remote dir exists
183
184 if (fRemoteDir.IsNull())
185 {
186 AliError("you must provide the grid location where to copy the files");
187 return kFALSE;
188 }
189
190 // connect to alien
191 if (!gGrid)
192 {
193 if (!TGrid::Connect("alien://"))
194 {
195 AliError("Cannot connect to grid");
196 return kFALSE;
197 }
198 }
199
200 if (!RemoteDirectoryExists(fRemoteDir))
201 {
202 AliError(Form("directory %s does not exist", fRemoteDir.Data()));
203 return kFALSE;
204 }
205
206 return kTRUE;
207}
208
209//______________________________________________________________________________
210Bool_t AliMuonAccEffSubmitter::CopyLocalFilesToRemote()
211{
212 /// copy all files necessary to run the simulation into remote directory
213
214 if (!IsValid()) return kFALSE;
215
216 if ( CheckRemoteDir() )
217 {
218 TString sdir(gSystem->ExpandPathName(LocalDir()));
219
220 TIter next(LocalFileList());
221 TObjString* ftc;
222
223 Bool_t allok(kTRUE);
224
225 while ( ( ftc = static_cast<TObjString*>(next())) )
226 {
227 allok = allok && CopyFile(ftc->String());
228 }
229 return allok;
230 }
231
232 return kFALSE;
233}
234
235//______________________________________________________________________________
236Bool_t AliMuonAccEffSubmitter::CopyTemplateFilesToLocal()
237{
238 // copy (or generate) local files from the template ones
239
240 if (!IsValid()) return kFALSE;
241
242 TIter next(TemplateFileList());
243 TObjString* file;
244
245 Int_t err(0);
246 Bool_t potentialProblem(kFALSE);
247
248 while ( ( file = static_cast<TObjString*>(next())) )
249 {
250 if ( file->String().Contains("OCDB") )
251 {
252 /// OCDB snapshots are not in template
253 continue;
254 }
255
256 if ( !ShouldOverwriteFiles() && !gSystem->AccessPathName(file->String().Data()) )
257 {
258 AliError(Form("Local file %s already exists. Remove it first if you want to update overwrite it",file->String().Data()));
259 potentialProblem = kTRUE;
260 }
261 else
262 {
263 TString stemplate(Form("%s/%s",fTemplateDir.Data(),file->String().Data()));
264 TString slocal(Form("%s/%s",fLocalDir.Data(),file->String().Data()));
265
266 Int_t c = gSystem->CopyFile(stemplate.Data(),slocal.Data(),ShouldOverwriteFiles());
267 if ( c )
268 {
269 Bool_t ok(kFALSE);
270 if ( stemplate.Contains(".jdl",TString::kIgnoreCase) )
271 {
272 if ( stemplate.Contains("merge",TString::kIgnoreCase) )
273 {
274 ok = GenerateMergeJDL(file->String().Data());
275 }
276 else
277 {
278 ok = GenerateRunJDL(file->String().Data());
279 }
280 }
281 if (!ok)
282 {
283 AliError(Form("Error %d copying file %s",c,stemplate.Data()));
284 }
285 else
286 {
287 c=0;
288 }
289 }
290 else
291 {
292 if ( HasVars(slocal.Data()) )
293 {
294 if (!ReplaceVars(slocal.Data()))
295 {
296 AliError("pb in ReplaceVars");
297 c=1;
298 }
299 }
300 }
301 err += c;
302 }
303 }
304
305 if ( potentialProblem )
306 {
307 AliWarning("At least one local file could not be overwritten. Cross-check that the local files are OK before we try to upload them to the Grid !");
308 return kFALSE;
309 }
310 return (err==0);
311}
312
313//______________________________________________________________________________
314std::ostream* AliMuonAccEffSubmitter::CreateJDLFile(const char* name) const
315{
316 TString jdl(Form("%s/%s",fLocalDir.Data(),name));
317
318 if ( !ShouldOverwriteFiles() && !gSystem->AccessPathName(jdl.Data()) )
319 {
320 AliError(Form("File %s already exists. Remove it if you want to overwrite it",jdl.Data()));
321 return 0x0;
322 }
323
324 std::ofstream* os = new std::ofstream(gSystem->ExpandPathName(jdl.Data()));
325
326 if (os->bad())
327 {
328 AliError(Form("Cannot create file %s",jdl.Data()));
329 delete os;
330 os=0x0;
331 }
332
333 return os;
334}
335
336///______________________________________________________________________________
337Bool_t AliMuonAccEffSubmitter::GenerateMergeJDL(const char* name)
338{
339 std::ostream* os = CreateJDLFile(name);
340
341 if (!os)
342 {
343 return kFALSE;
344 }
345
346 Bool_t final = TString(name).Contains("merge",TString::kIgnoreCase);
347
348 (*os) << "# Generated merging jdl (production mode)" << std::endl
349 << "# $1 = run number" << std::endl
350 << "# $2 = merging stage" << std::endl
351 << "# Stage_<n>.xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip" << std::endl;
352
353 Output(*os,"Packages",fPackageAliroot.Data(),fPackageGeant3.Data(),
354 fPackageRoot.Data(),fPackageApi.Data());
355
356 Output(*os,"Executable","AOD_merge.sh");
357
358 Output(*os,"Price","1");
359
360 if ( final )
361 {
362 Output(*os,"Jobtag","comment: AliMuonAccEffSubmitter final merging");
363 }
364 else
365 {
366 Output(*os,"Jobtag","comment: AliMuonAccEffSubmitter merging stage $2");
367 }
368
369 Output(*os,"Workdirectorysize","5000MB");
370
371 Output(*os,"Validationcommand",Form("%s/validation_merge.sh",fRemoteDir.Data()));
372
373 Output(*os,"TTL","7200");
374
375 Output(*os,"OutputArchive",
376 "log_archive.zip:stderr,stdout@disk=1",
377 "root_archive.zip:AliAOD.root,AliAOD.Muons.root,AnalysisResults.root@disk=3"
378 );
379
380 Output(*os,"Arguments",(final ? "2":"1")); // for AOD_merge.sh, 1 means intermediate merging stage, 2 means final merging
381
382 if ( !final )
383 {
384 Output(*os,"InputFile",Form("LF:%s/AODtrain.C",fRemoteDir.Data()));
385 Output(*os,"OutputDir",Form("%s/$1/Stage_$2/#alien_counter_03i#",fRemoteDir.Data()));
386 Output(*os,"InputDataCollection",Form("%s/$1/Stage_$2.xml,nodownload",fRemoteDir.Data()));
387 Output(*os,"split","se");
388 Output(*os,"SplitMaxInputFileNumber",GetSplitMaxInputFileNumber());
389 Output(*os,"InputDataListFormat","xml-single");
390 Output(*os,"InputDataList","wn.xml");
391 }
392 else
393 {
394 Output(*os,"InputFile",Form("LF:%s/AODtrain.C",fRemoteDir.Data()),
395 Form("LF:%s/$1/wn.xml",fRemoteDir.Data()));
396 Output(*os,"OutputDir",Form("%s/$1",fRemoteDir.Data()));
397 }
398
399 return kTRUE;
400}
401
402//______________________________________________________________________________
403Bool_t AliMuonAccEffSubmitter::GenerateRunJDL(const char* name)
404{
405 /// Generate (locally) the JDL to perform the simulation+reco+aod filtering
406 /// (to be then copied to the grid and finally submitted)
407
408 std::ostream* os = CreateJDLFile(name);
409
410 if (!os)
411 {
412 return kFALSE;
413 }
414
415 Output(*os,"Packages",fPackageAliroot.Data(),fPackageGeant3.Data(),
416 fPackageRoot.Data(),fPackageApi.Data());
417
418 Output(*os,"Jobtag","comment: AliMuonAccEffSubmitter RUN $1");
419
420 Output(*os,"split","production:1-$2");
421
422 Output(*os,"Price","1");
423
424 Output(*os,"OutputDir",Form("%s/$1/#alien_counter_03i#",fRemoteDir.Data()));
425
426 Output(*os,"Executable","/alice/bin/aliroot_new");
427
428 TObjArray files;
429 files.SetOwner(kTRUE);
430 TIter next(TemplateFileList());
431 TObjString* file;
432
433 while ( ( file = static_cast<TObjString*>(next())) )
434 {
435 if ( !file->String().Contains(".jdl",TString::kIgnoreCase) ||
436 !file->String().Contains("OCDB_") )
437 {
438 files.Add(new TObjString(Form("LF:%s/%s",fRemoteDir.Data(),file->String().Data())));
439 }
440 }
441
442 if ( fUseOCDBSnapshots )
443 {
444 files.Add(new TObjString(Form("LF:%s/OCDB/$1/OCDB_sim.root",fRemoteDir.Data())));
445 files.Add(new TObjString(Form("LF:%s/OCDB/$1/OCDB_rec.root",fRemoteDir.Data())));
446 }
447
448 Output(*os,"InputFile",files);
449
450 if ( CompactMode() == 0 )
451 {
452 // store everything
453 Output(*os,"OutputArchive", "log_archive.zip:stderr,stdout,aod.log,checkaod.log,checkesd.log,rec.log,recwatch.log,sim.log,simwatch.log@disk=1",
454 "root_archive.zip:galice*.root,Kinematics*.root,TrackRefs*.root,AliESDs.root,AliAOD.root,AliAOD.Muons.root,Merged.QA.Data.root,Run*.root@disk=2");
455 }
456 else if ( CompactMode() == 1 )
457 {
458 // keep only muon AODs
459 Output(*os,"OutputArchive", "log_archive.zip:stderr,stdout,aod.log,checkaod.log,checkesd.log,rec.log,sim.log@disk=1",
460 "root_archive.zip:galice*.root,AliAOD.Muons.root@disk=2");
461 }
462 else
463 {
464 AliError(Form("Unknown CompactMode %d",CompactMode()));
465 delete os;
466 return kFALSE;
467 }
468
469 Output(*os,"splitarguments","simrun.C --run $1 --chunk #alien_counter# --event $3");
470
471 Output(*os,"Workdirectorysize","5000MB");
472
473 Output(*os,"JDLVariables","Packages","OutputDir");
474
475 Output(*os,"Validationcommand",Form("%s/validation.sh",fRemoteDir.Data()));
476
477 Output(*os,"TTL","72000");
478
479 return kTRUE;
480}
481
482//______________________________________________________________________________
483Bool_t AliMuonAccEffSubmitter::GetLastStage(const char* remoteDir) const
484{
485 Int_t n = 0, lastStage = 0;
486 gSystem->Exec(Form("alien_ls -F %s | grep Stage_.*/ > __stage__", remoteDir));
487 ifstream f("__stage__");
488 std::string dummy;
489 while (std::getline(f, dummy)) n++;
490 f.close();
491 while (n > 0) if (gSystem->Exec(Form("grep Stage_%d/ __stage__ 2>&1 >/dev/null", ++lastStage)) == 0) n--;
492 gSystem->Exec("rm -f __stage__");
493 return lastStage;
494}
495
496//______________________________________________________________________________
497Bool_t AliMuonAccEffSubmitter::HasVars(const char* file) const
498{
499 /// Whether or not the file contains variables that have to
500 /// be substituted
501
502 std::ifstream in(file);
503 char line[1024];
504 while ( in.getline(line,1023,'\n') )
505 {
506 TString sline(line);
507 if (sline.Contains("VAR_") && !sline.BeginsWith("//") )
508 {
509 return kTRUE;
510 }
511 }
512 return kFALSE;
513}
514
515//______________________________________________________________________________
516TObjArray* AliMuonAccEffSubmitter::LocalFileList() const
517{
518 /// Return (after createing and filling it if needed)
519 /// the internal file list with paths from the local directory
520
521 if (!fLocalFileList)
522 {
523 fLocalFileList = static_cast<TObjArray*>(TemplateFileList()->Clone());
524 }
525
526 return fLocalFileList;
527}
528
529//______________________________________________________________________________
530Bool_t AliMuonAccEffSubmitter::MakeOCDBSnapshots()
531{
532 /// Run sim.C and rec.C in a special mode to generate OCDB snapshots
533 /// Can only be done after the templates have been copied locally
534
535 if (!IsValid()) return kFALSE;
536
537 if (!fUseOCDBSnapshots) return kTRUE;
538
539 if (!fScalers) return kFALSE;
540
541 const std::vector<int>& runs = fScalers->GetRunList();
542
543 Bool_t ok(kTRUE);
544
545 for ( std::vector<int>::size_type i = 0; i < runs.size(); ++i )
546 {
547 Int_t runNumber = runs[i];
548
549 TString ocdbSim(Form("%s/OCDB/%d/OCDB_sim.root",SnapshotDir().Data(),runNumber));
550 TString ocdbRec(Form("%s/OCDB/%d/OCDB_rec.root",SnapshotDir().Data(),runNumber));
551
552 if ( !gSystem->AccessPathName(ocdbSim.Data()) &&
553 !gSystem->AccessPathName(ocdbRec.Data()) )
554 {
555 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));
556 }
557 else
558 {
559 gSystem->Exec(Form("aliroot -b -q -x simrun.C --run %d --snapshot",runNumber));
560
561 if ( gSystem->AccessPathName(ocdbSim.Data()) )
562 {
563 AliError(Form("Could not create OCDB snapshot for simulation"));
564 ok = kFALSE;
565 }
566
567 if ( gSystem->AccessPathName(ocdbRec.Data()) )
568 {
569 AliError(Form("Could not create OCDB snapshot for reconstruction"));
570 ok = kFALSE;
571 }
572 }
573
574 LocalFileList()->Add(new TObjString(ocdbSim));
575 LocalFileList()->Add(new TObjString(ocdbRec));
576 }
577
578 return ok;
579}
580
581//______________________________________________________________________________
582Bool_t AliMuonAccEffSubmitter::Merge(Int_t stage, Bool_t dryRun)
583{
584 /// Submit multiple merging jobs with the format "submit AOD_merge(_final).jdl run# (stage#)".
585 /// Also produce the xml collection before sending jobs
586 /// Initial AODs will be taken from fRemoteDir/[RUNNUMBER] while the merged
587 /// ones will be put into fMergedDir/AODs/[RUNNUMBER]
588 ///
589 /// Example:
590 /// - inDir = "/alice/sim/2012/LHC12a10_bis" (where to find the data to merge)
591 /// = 0x0 --> inDir = homeDir/outDir/resDir
592 /// - outDir = "Sim/LHC11h/embedding/AODs" (where to store merged results)
593 /// - runList.txt must contains the list of run number
594 /// - stage=0 --> final merging / stage>0 --> intermediate merging i
595 ///
596
597 if (!RemoteDirectoryExists(fMergedDir.Data())) {
598 AliError(Form("directory %s does not exist", fMergedDir.Data()));
599 return kFALSE;
600 }
601
602 gGrid->Cd(fMergedDir.Data());
603
604 TString jdl = MergeJDLName(stage==0);
605
606 if (!RemoteFileExists(jdl.Data()))
607 {
608 AliError(Form("file %s does not exist in %s\n", jdl.Data(), fRemoteDir.Data()));
609 return kFALSE;
610 }
611
612 const std::vector<int>& runs = fScalers->GetRunList();
613
614 if (runs.empty())
615 {
616 AliError("No run to work with");
617 return kFALSE;
618 }
619
620 TString currRun;
621 TString reply = "";
622 gSystem->Exec("rm -f __failed__");
623 Bool_t failedRun = kFALSE;
624
625 for ( std::vector<int>::size_type i = 0; i < runs.size(); ++i )
626 {
627 Int_t run = runs[i];
628 AliInfo(Form("\n --- processing run %d ---\n", run));
629
630 TString runDir = Form("%s/%d", fMergedDir.Data(), run);
631
632 if (!RemoteDirectoryExists(runDir.Data()))
633 {
634 AliInfo(Form(" - creating output directory %s\n", runDir.Data()));
635 gSystem->Exec(Form("alien_mkdir -p %s", runDir.Data()));
636 }
637
638 if (RemoteFileExists(Form("%s/root_archive.zip", runDir.Data())))
639 {
640 AliWarning(" ! final merging already done");
641 continue;
642 }
643
644 Int_t lastStage = GetLastStage(runDir.Data());
645
646 if (stage > 0 && stage != lastStage+1)
647 {
648 AliError(Form(" ! lastest merging stage = %d. Next must be stage %d or final stage\n", lastStage, lastStage+1));
649 continue;
650 }
651
652 TString wn = (stage > 0) ? Form("Stage_%d.xml", stage) : "wn.xml";
653 TString find = (lastStage == 0) ?
654 Form("alien_find -x %s %s/%d *root_archive.zip", wn.Data(), fRemoteDir.Data(), run) :
655 Form("alien_find -x %s %s/%d/Stage_%d *root_archive.zip", wn.Data(), fRemoteDir.Data(), run, lastStage);
656 gSystem->Exec(Form("%s 1> %s 2>/dev/null", find.Data(), wn.Data()));
657 gSystem->Exec(Form("grep -c /event %s > __nfiles__", wn.Data()));
658 ifstream f2("__nfiles__");
659 TString nFiles;
660 nFiles.ReadLine(f2,kTRUE);
661 f2.close();
662 gSystem->Exec("rm -f __nfiles__");
663 printf(" - number of files to merge = %d\n", nFiles.Atoi());
664 if (nFiles.Atoi() == 0) {
665 printf(" ! collection of files to merge is empty\n");
666 gSystem->Exec(Form("rm -f %s", wn.Data()));
667 continue;
668 } else if (stage > 0 && nFiles.Atoi() <= splitLevel && !reply.BeginsWith("y")) {
669 if (!reply.BeginsWith("n")) {
670 printf(" ! number of files to merge <= split level (%d). Continue? [Y/n] ", splitLevel);
671 fflush(stdout);
672 reply.Gets(stdin,kTRUE);
673 reply.ToLower();
674 }
675 if (reply.BeginsWith("n")) {
676 gSystem->Exec(Form("rm -f %s", wn.Data()));
677 continue;
678 } else reply = "y";
679 }
680
681 if (!dryRun)
682 {
683 TString dirwn = Form("%s/%s", runDir.Data(), wn.Data());
684 if (RemoteFileExists(dirwn.Data())) gGrid->Rm(dirwn.Data());
685 gSystem->Exec(Form("alien_cp file:%s alien://%s", wn.Data(), dirwn.Data()));
686 gSystem->Exec(Form("rm -f %s", wn.Data()));
687 }
688
689 TString query;
690 if (stage > 0) query = Form("submit %s %d %d", jdl.Data(), run, stage);
691 else query = Form("submit %s %d", jdl.Data(), run);
692 printf(" - %s ...", query.Data());
693 fflush(stdout);
694
695 if (dryRun)
696 {
697 AliInfo(" dry run");
698 continue;
699 }
700
701 Bool_t done = kFALSE;
702 TGridResult *res = gGrid->Command(query);
703 if (res)
704 {
705 TString cjobId1 = res->GetKey(0,"jobId");
706 if (!cjobId1.IsDec())
707 {
708 AliError(" FAILED");
709 gGrid->Stdout();
710 gGrid->Stderr();
711 }
712 else
713 {
714 AliInfo(Form(" DONE\n --> the job Id is: %s \n", cjobId1.Data()));
715 done = kTRUE;
716 }
717 delete res;
718 }
719 else
720 {
721 AliError(" FAILED");
722 }
723
724 if (!done)
725 {
726 gSystem->Exec(Form("echo %d >> __failed__", run));
727 failedRun = kTRUE;
728 }
729
730 }
731
732 if (failedRun)
733 {
734 AliInfo("\n--------------------\n");
735 AliInfo("list of failed runs:\n");
736 gSystem->Exec("cat __failed__");
737 gSystem->Exec("rm -f __failed__");
738 return kFALSE;
739 }
740
741 return kTRUE;
742}
743
744//______________________________________________________________________________
745UInt_t AliMuonAccEffSubmitter::NofRuns() const
746{
747 // number of runs we're dealing with
748 if (!fScalers) return 0;
749
750 return fScalers->GetRunList().size();
751}
752
753//______________________________________________________________________________
754void AliMuonAccEffSubmitter::Output(std::ostream& out, const char* key,
755 const TObjArray& values) const
756{
757 out << key << " = ";
758
759 Int_t n = values.GetEntries();
760
761 if ( n > 1 )
762 {
763 out << "{" << std::endl;
764 TIter next(&values);
765 TObjString* v;
766
767 while ( ( v = static_cast<TObjString*>(next())) )
768 {
769 --n;
770 out << "\t\"" << v->String().Data() << "\"";
771 if ( n ) out << ",";
772 out << std::endl;
773 }
774 out << "}";
775 }
776 else
777 {
778 TString& v1 = static_cast<TObjString*>(values.At(0))->String();
779
780 if ( v1.IsDigit() )
781 {
782 out << v1.Atoi();
783 }
784 else
785 {
786 out << "\"" << v1.Data() << "\"";
787 }
788 }
789 out << ";" << std::endl;
790}
791
792//______________________________________________________________________________
793void AliMuonAccEffSubmitter::Output(std::ostream& out, const char* key, const char* v1,
794 const char* v2, const char* v3, const char* v4,
795 const char* v5, const char* v6, const char* v7,
796 const char* v8, const char* v9) const
797{
798 TObjArray values;
799 values.SetOwner(kTRUE);
800
801 values.Add(new TObjString(v1));
802 if ( strlen(v2) > 0 ) values.Add(new TObjString(v2));
803 if ( strlen(v3) > 0 ) values.Add(new TObjString(v3));
804 if ( strlen(v4) > 0 ) values.Add(new TObjString(v4));
805 if ( strlen(v5) > 0 ) values.Add(new TObjString(v5));
806 if ( strlen(v6) > 0 ) values.Add(new TObjString(v6));
807 if ( strlen(v7) > 0 ) values.Add(new TObjString(v7));
808 if ( strlen(v8) > 0 ) values.Add(new TObjString(v8));
809 if ( strlen(v9) > 0 ) values.Add(new TObjString(v9));
810
811 Output(out,key,values);
812}
813
814
815//______________________________________________________________________________
816void AliMuonAccEffSubmitter::Print(Option_t* /*opt*/) const
817{
818 if (!IsValid())
819 {
820 std::cout << std::string(80,'*') << std::endl;
821 std::cout << "INVALID OBJECT. CHECK BELOW THE CONFIGURATION." << std::endl;
822 std::cout << std::string(80,'*') << std::endl;
823 }
824
825 std::cout << "Template directory = " << fTemplateDir.Data() << std::endl;
826 std::cout << "Local directory = " << fLocalDir.Data() << std::endl;
827 std::cout << "Remote directory = " << fRemoteDir.Data() << std::endl;
828
829 std::cout << "OCDB path = " << fOCDBPath.Data() << std::endl;
830
831 if ( fRatio > 0 )
832 {
833 std::cout << Form("For each run, will generate %5.2f times the number of real events for trigger %s",
834 fRatio,fReferenceTrigger.Data()) << std::endl;
835 }
836 else
837 {
838 std::cout << Form("For each run, will generate %10d events",fFixedNofEvents) << std::endl;
839 }
840
841 std::cout << "MaxEventsPerChunk = " << fMaxEventsPerChunk << std::endl;
842
843 if ( NofRuns() )
844 {
845 std::cout << NofRuns() << " run";
846 if ( NofRuns() > 1 ) std::cout << "s";
847 std::cout << " = ";
848 fScalers->Print();
849 }
850
851 if ( fVars )
852 {
853 TIter next(fVars);
854 TObjString* key;
855 while ( ( key = static_cast<TObjString*>(next())) )
856 {
857 TObjString* value = static_cast<TObjString*>(fVars->GetValue(key->String()));
858 std::cout << "Variable " << key->String() << " will be replaced by " << value->String() << std::endl;
859 }
860 }
861
862 std::cout << "Files to be uploaded:" << std::endl;
863 TIter nextFile(LocalFileList());
864 TObjString* sfile;
865 while ( ( sfile = static_cast<TObjString*>(nextFile())) )
866 {
867 std::cout << sfile->String().Data() << std::endl;
868 }
869}
870
871
872//______________________________________________________________________________
873Bool_t AliMuonAccEffSubmitter::RemoteDirectoryExists(const char *dirname) const
874{
875 // Returns true if directory exists. Can be also a path.
876 if (!gGrid) return kFALSE;
877 // Check if dirname is a path
878 TString dirstripped = dirname;
879 dirstripped = dirstripped.Strip();
880 dirstripped = dirstripped.Strip(TString::kTrailing, '/');
881 TString dir = gSystem->BaseName(dirstripped);
882 dir += "/";
883 TString path = gSystem->DirName(dirstripped);
884 TGridResult *res = gGrid->Ls(path, "-F");
885 if (!res) return kFALSE;
886 TIter next(res);
887 TMap *map;
888 TObject *obj;
889 while ((map=dynamic_cast<TMap*>(next()))) {
890 obj = map->GetValue("name");
891 if (!obj) break;
892 if (dir == obj->GetName()) {
893 delete res;
894 return kTRUE;
895 }
896 }
897 delete res;
898 return kFALSE;
899}
900
901//______________________________________________________________________________
902Bool_t AliMuonAccEffSubmitter::RemoteFileExists(const char *lfn) const
903{
904 // Returns true if file exists.
905 if (!gGrid) return kFALSE;
906 TGridResult *res = gGrid->Ls(lfn);
907 if (!res) return kFALSE;
908 TMap *map = dynamic_cast<TMap*>(res->At(0));
909 if (!map) {
910 delete res;
911 return kFALSE;
912 }
913 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("name"));
914 if (!objs || !objs->GetString().Length()) {
915 delete res;
916 return kFALSE;
917 }
918 delete res;
919 return kTRUE;
920}
921
922//______________________________________________________________________________
923Bool_t AliMuonAccEffSubmitter::ReplaceVars(const char* file)
924{
925 std::ifstream in(file);
926 char line[1024];
927 TObjArray lines;
928 lines.SetOwner(kTRUE);
929 Int_t nvars(0);
930 Int_t nreplaced(0);
931
932 TIter next(fVars);
933
934 while ( in.getline(line,1023,'\n') )
935 {
936 TString sline(line);
937 while (sline.Contains("VAR_") && !sline.BeginsWith("//") )
938 {
939 ++nvars;
940 TObjString* key;
941 next.Reset();
942 while ( ( key = static_cast<TObjString*>(next())) )
943 {
944 if ( sline.Contains(key->String()) )
945 {
946 ++nreplaced;
947 TObjString* value = static_cast<TObjString*>(fVars->GetValue(key->String()));
948 sline.ReplaceAll(key->String(),value->String());
949 break;
950 }
951 }
952 }
953
954 lines.Add(new TObjString(sline));
955 }
956
957 in.close();
958
959 if ( nvars > 0 )
960 {
961 if ( nreplaced != nvars )
962 {
963 AliError(Form("nvars=%d nreplaced=%d",nvars,nreplaced));
964 return kFALSE;
965 }
966 std::ofstream out(file);
967 TIter nextLine(&lines);
968 TObjString* s;
969 while ( ( s = static_cast<TObjString*>(nextLine()) ) )
970 {
971 out << s->String().Data() << std::endl;
972 }
973 out.close();
974 }
975
976 return kTRUE;
977}
978
979//______________________________________________________________________________
980Bool_t AliMuonAccEffSubmitter::Run(const char* mode)
981{
982 /// mode can be one of (case insensitive)
983 ///
984 /// LOCAL : copy the template files from the template directory to the local one
985 /// UPLOAD : copy the local files to the grid (requires LOCAL)
986 /// OCDB : make ocdb snapshots (requires LOCAL)
987 /// SUBMIT : submit the jobs (requires LOCAL + UPLOAD)
988 /// FULL : all of the above (requires all of the above)
989 ///
990 /// TEST : as SUBMIT, but in dry mode (does not actually submit the jobs)
991
992 if (!IsValid()) return kFALSE;
993
994 TString smode(mode);
995 smode.ToUpper();
996
997 if ( smode == "FULL")
998 {
999 return ( Run("LOCAL") && Run("OCDB") && Run("UPLOAD") && Run("SUBMIT") );
1000 }
1001
1002 if ( smode == "LOCAL")
1003 {
1004 return CopyTemplateFilesToLocal();
1005 }
1006
1007 if ( smode == "UPLOAD" )
1008 {
1009 return (CopyLocalFilesToRemote());
1010 }
1011
1012 if ( smode == "OCDB" )
1013 {
1014 Bool_t ok = Run("LOCAL");
1015 if (ok)
1016 {
1017 ok = MakeOCDBSnapshots();
1018 }
1019 return ok;
1020 }
1021
1022 if ( smode == "TEST" )
1023 {
1024 Bool_t ok = Run("LOCAL") && Run("OCDB") && Run("UPLOAD");
1025 if ( ok )
1026 {
1027 ok = (Submit(kTRUE)>0);
1028 }
1029 return ok;
1030 }
1031
1032 if ( smode == "FULL" )
1033 {
1034 Bool_t ok = Run("LOCAL") && Run("OCDB") && Run("UPLOAD");
1035 if ( ok )
1036 {
1037 ok = (Submit(kFALSE)>0);
1038 }
1039 return ok;
1040 }
1041
1042 if( smode == "SUBMIT" )
1043 {
1044 return (Submit(kFALSE)>0);
1045 }
1046
1047 return kFALSE;
1048}
1049
1050//______________________________________________________________________________
1051void AliMuonAccEffSubmitter::SetPackages(const char* aliroot,
1052 const char* root,
1053 const char* geant3,
1054 const char* api)
1055{
1056 fPackageAliroot = aliroot;
1057 fPackageRoot = root;
1058 fPackageGeant3 = geant3;
1059 fPackageApi = api;
1060}
1061
1062//______________________________________________________________________________
1063TString AliMuonAccEffSubmitter::GetRemoteDir(const char* dir, Bool_t create)
1064{
1065 /// Set the target remote directory (on the grid)
1066
1067 if (!RemoteDirectoryExists(dir))
1068 {
1069 if (!create)
1070 {
1071 AliError(Form("Remote directory %s does not exist", dir));
1072 return "";
1073 }
1074 else
1075 {
1076 AliInfo(Form("Remote directory %s does not exist. Trying to create it...",dir));
1077 if ( !gGrid->Mkdir(dir,"-p") )
1078 {
1079 AliError(Form("Could not create remote dir. Sorry."));
1080 return "";
1081 }
1082 }
1083 }
1084 return dir;
1085}
1086
1087//______________________________________________________________________________
1088Bool_t AliMuonAccEffSubmitter::SetMergedDir(const char* dir, Bool_t create)
1089{
1090 fMergedDir = GetRemoteDir(dir,create);
1091 return (fMergedDir.Length()>0);
1092}
1093
1094//______________________________________________________________________________
1095Bool_t AliMuonAccEffSubmitter::SetRemoteDir(const char* dir, Bool_t create)
1096{
1097 fRemoteDir = GetRemoteDir(dir,create);
1098 return (fIsValid = (fRemoteDir.Length()>0));
1099}
1100
1101
1102//______________________________________________________________________________
1103void AliMuonAccEffSubmitter::SetRunList(const char* runList)
1104{
1105 // set the runlist from a text file
1106 if (!fScalers)
1107 {
1108 fScalers = new AliAnalysisTriggerScalers(runList,fOCDBPath.Data());
1109 }
1110 else
1111 {
1112 fScalers->SetRunList(runList);
1113 }
1114 UpdateLocalFileList(kTRUE);
1115}
1116
1117//______________________________________________________________________________
1118void AliMuonAccEffSubmitter::SetRunList(int runNumber)
1119{
1120 // set the runlist from a text file
1121 if (!fScalers)
1122 {
1123 fScalers = new AliAnalysisTriggerScalers(runNumber,fOCDBPath.Data());
1124 }
1125 else
1126 {
1127 fScalers->SetRunList(runNumber);
1128 }
1129 UpdateLocalFileList(kTRUE);
1130}
1131
1132//______________________________________________________________________________
1133Bool_t AliMuonAccEffSubmitter::SetVar(const char* varname, const char* value)
1134{
1135 TString s(varname);
1136 s.ToUpper();
1137 if (!s.BeginsWith("VAR_"))
1138 {
1139 AliError("Variable name should start with VAR_");
1140 return kFALSE;
1141 }
1142 if (!fVars)
1143 {
1144 fVars = new TMap;
1145 fVars->SetOwnerKeyValue(kTRUE,kTRUE);
1146 }
1147
1148 TObject* o = new TObjString(s);
1149 fVars->Remove(o);
1150
1151 fVars->Add(o,new TObjString(value));
1152
1153 return kTRUE;
1154}
1155
1156//______________________________________________________________________________
1157Int_t AliMuonAccEffSubmitter::Submit(Bool_t dryRun)
1158{
1159 /// Submit multiple production jobs with the format "submit jdl 000run#.xml 000run#".
1160 ///
1161 /// Return the number of submitted (master) jobs
1162 ///
1163 /// Example:
1164 /// - outputDir = "/alice/cern.ch/user/p/ppillot/Sim/LHC10h/JPsiPbPb276/AlignRawVtxRaw/ESDs"
1165 /// - runList must contains the list of run number
1166 /// - trigger is the (fully qualified) trigger name used to compute the base number of events
1167 /// - mult is the factor to apply to the number of trigger to get the number of events to be generated
1168 /// (# generated events = # triggers x mult
1169
1170 if (!IsValid()) return 0;
1171
1172 gGrid->Cd(RemoteDir());
1173
1174 if (!RemoteFileExists(RunJDLName()))
1175 {
1176 AliError(Form("file %s does not exist in %s", RunJDLName().Data(), RemoteDir().Data()));
1177 return 0;
1178 }
1179
1180 if ( !fScalers )
1181 {
1182 AliError("No run list set. Use SetRunList");
1183 return 0;
1184 }
1185 const std::vector<int>& runs = fScalers->GetRunList();
1186
1187 if (runs.empty())
1188 {
1189 AliError("No run to work with");
1190 return 0;
1191 }
1192
1193 // cout << "total number of selected MB events = " << totEvt << endl;
1194 // cout << "required number of generated events = " << nGenEvents << endl;
1195 // cout << "number of generated events per MB event = " << ratio << endl;
1196 // cout << endl;
1197
1198 std::cout << "run\tchunks\tevents" << std::endl;
1199 std::cout << "----------------------" << std::endl;
1200
1201 Int_t nJobs(0);
1202 Int_t nEvts(0);
1203
1204 for (std::vector<int>::size_type i=0; i < runs.size(); ++i)
1205 {
1206 Int_t runNumber = runs[i];
1207
1208 Int_t nEvtRun(fFixedNofEvents);
1209
1210 if ( fRatio > 0 )
1211 {
1212 AliAnalysisTriggerScalerItem* trigger = fScalers->GetTriggerScaler(runNumber, "L2A", ReferenceTrigger().Data());
1213
1214 if (!trigger)
1215 {
1216 AliError(Form("Could not get trigger %s for run %09d",ReferenceTrigger().Data(),runNumber));
1217 continue;
1218 }
1219 nEvtRun = TMath::Nint(fRatio * trigger->Value());
1220 }
1221
1222 Int_t nChunk = 1;
1223
1224 while (nEvtRun/nChunk+0.5 > MaxEventsPerChunk())
1225 {
1226 ++nChunk;
1227 }
1228
1229 Int_t nEvtChunk = TMath::Nint(nEvtRun/nChunk + 0.5);
1230
1231 nJobs += nChunk;
1232
1233 nEvts += nChunk*nEvtChunk;
1234
1235 std::cout << runNumber << "\t" << nChunk << "\t" << nEvtChunk << std::endl;
1236
1237 TString query(Form("submit %s %d %d %d", RunJDLName().Data(), runNumber, nChunk, nEvtChunk));
1238
1239 std::cout << query.Data() << " ..." << std::flush;
1240
1241 TGridResult* res = 0x0;
1242
1243 if (!dryRun)
1244 {
1245 res = gGrid->Command(query);
1246 }
1247
1248 if (res)
1249 {
1250 TString cjobId1 = res->GetKey(0,"jobId");
1251
1252 if (!cjobId1.Length())
1253 {
1254 std::cout << " FAILED" << std::endl << std::endl;
1255 gGrid->Stdout();
1256 gGrid->Stderr();
1257 }
1258 else
1259 {
1260 std::cout << "DONE" << std::endl;
1261 std::cout << Form(" --> the job Id is: %s",cjobId1.Data()) << std::endl << std::endl;
1262 }
1263 }
1264 else
1265 {
1266 std::cout << " FAILED" << std::endl << std::endl;
1267 }
1268
1269 delete res;
1270 }
1271
1272 std::cout << std::endl
1273 << "total number of jobs = " << nJobs << std::endl
1274 << "total number of generated events = " << nEvts << std::endl
1275 << std::endl;
1276
1277 return nJobs;
1278}
1279
1280//______________________________________________________________________________
1281TObjArray* AliMuonAccEffSubmitter::TemplateFileList() const
1282{
1283 /// Return (after createing and filling it if needed)
1284 /// the internal file list with paths from the template directory
1285
1286 if (!fTemplateFileList)
1287 {
1288 fTemplateFileList = new TObjArray;
1289 fTemplateFileList->SetOwner(kTRUE);
1290
1291 fTemplateFileList->Add(new TObjString("CheckESD.C"));
1292 fTemplateFileList->Add(new TObjString("CheckAOD.C"));
1293 fTemplateFileList->Add(new TObjString("AODtrain.C"));
1294 fTemplateFileList->Add(new TObjString("validation.sh"));
1295 if ( fExternalConfig.Length() > 0 )
1296 {
1297 fTemplateFileList->Add(new TObjString(fExternalConfig));
1298 }
1299 else
1300 {
1301 fTemplateFileList->Add(new TObjString("Config.C"));
1302 }
1303 fTemplateFileList->Add(new TObjString("rec.C"));
1304 fTemplateFileList->Add(new TObjString("sim.C"));
1305 fTemplateFileList->Add(new TObjString("simrun.C"));
1306 fTemplateFileList->Add(new TObjString(RunJDLName().Data()));
1307 fTemplateFileList->Add(new TObjString(MergeJDLName(kFALSE).Data()));
1308 fTemplateFileList->Add(new TObjString(MergeJDLName(kTRUE).Data()));
1309 fTemplateFileList->Add(new TObjString("AOD_merge.sh"));
1310 fTemplateFileList->Add(new TObjString("validation_merge.sh"));
1311 }
1312
1313 return fTemplateFileList;
1314}
1315
1316//______________________________________________________________________________
1317void AliMuonAccEffSubmitter::UpdateLocalFileList(Bool_t clearSnapshots)
1318{
1319 if (!fScalers) return;
1320
1321 if ( clearSnapshots )
1322 {
1323 TIter next(LocalFileList());
1324 TObjString* file;
1325
1326 while ( ( file = static_cast<TObjString*>(next())) )
1327 {
1328 if ( file->String().Contains("OCDB_") )
1329 {
1330 LocalFileList()->Remove(file);
1331 }
1332 }
1333 LocalFileList()->Compress();
1334 }
1335
1336 const std::vector<int>& runs = fScalers->GetRunList();
1337
1338 const char* type[] = { "sim","rec" };
1339
1340 for ( std::vector<int>::size_type i = 0; i < runs.size(); ++i )
1341 {
1342 Int_t runNumber = runs[i];
1343
1344 for ( Int_t t = 0; t < 2; ++t )
1345 {
1346 TString snapshot(Form("%s/OCDB/%d/OCDB_%s.root",SnapshotDir().Data(),runNumber,type[t]));
1347
1348 if ( !gSystem->AccessPathName(snapshot.Data()) )
1349 {
1350 if ( !LocalFileList()->FindObject(snapshot.Data()) )
1351 {
1352 LocalFileList()->Add(new TObjString(snapshot));
1353 }
1354 }
1355 }
1356 }
1357
1358}
1359
1360//______________________________________________________________________________
1361void AliMuonAccEffSubmitter::UseOCDBSnapshots(Bool_t flag)
1362{
1363 fUseOCDBSnapshots = flag;
1364 if ( flag )
1365 {
1366 SetVar("VAR_OCDB_SNAPSHOT","kTRUE");
1367 }
1368 else
1369 {
1370 SetVar("VAR_OCDB_SNAPSHOT","kFALSE");
1371 }
1372
1373 UpdateLocalFileList();
1374}
1375