1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
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 **************************************************************************/
17 // AliMuonAccEffSubmitter : a class to help submit Acc x Eff simulations
18 // anchored to real runs for J/psi, upsilon, single muons, etc...
20 // This class is dealing with 3 different directories :
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
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
34 // - remote directory, the alien directory where the files will be copied
35 // (from the local directory) before the actual submission
37 // ==========================================================
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);
49 // a.Run("test"); // will do everything but the submit
50 // a.Submit(false); // actual submission
53 // author: Laurent Aphecetche (Subatech
56 #include "AliMuonAccEffSubmitter.h"
58 #include "AliAnalysisTriggerScalers.h"
62 #include "TGridResult.h"
65 #include "TObjString.h"
76 //______________________________________________________________________________
77 AliMuonAccEffSubmitter::AliMuonAccEffSubmitter(const char* generator)
81 fReferenceTrigger(""),
83 fFixedNofEvents(10000),
84 fMaxEventsPerChunk(5000),
85 fLocalDir(gSystem->pwd()),
87 fTemplateDir(gSystem->ExpandPathName("$ALICE_ROOT/PWG/muondep/AccEffTemplates")),
92 fMergedDir(Form("%s/AODs",fRemoteDir.Data())),
93 fSplitMaxInputFileNumber(20),
95 fShouldOverwriteFiles(kFALSE),
98 fUseOCDBSnapshots(kTRUE),
100 fTemplateFileList(0x0),
102 fSnapshotDir(fLocalDir)
106 if (!TGrid::Connect("alien://"))
108 AliError("cannot connect to grid");
112 SetPackages("VO_ALICE@AliRoot::v5-03-Rev-18","VO_ALICE@GEANT3::v1-14-8","VO_ALICE@ROOT::v5-34-05-1");
114 SetVar("VAR_OCDB_PATH","\"raw://\"");
116 SetVar("VAR_GENPARAM_GENLIB_TYPE","AliGenMUONlib::kJpsi");
117 SetVar("VAR_GENPARAM_GENLIB_PARNAME","\"pPb 5.03\"");
119 SetVar("VAR_GENCORRHF_QUARK","5");
120 SetVar("VAR_GENCORRHF_ENERGY","5");
122 SetVar("VAR_GENPARAMCUSTOM_PDGPARTICLECODE","443");
124 // default values below are from J/psi p+Pb (from muon_calo pass)
125 SetVar("VAR_GENPARAMCUSTOM_Y_P0","4.08E5");
126 SetVar("VAR_GENPARAMCUSTOM_Y_P1","7.1E4");
128 SetVar("VAR_GENPARAMCUSTOM_PT_P0","1.13E9");
129 SetVar("VAR_GENPARAMCUSTOM_PT_P1","18.05");
130 SetVar("VAR_GENPARAMCUSTOM_PT_P2","2.05");
131 SetVar("VAR_GENPARAMCUSTOM_PT_P3","3.34");
133 UseOCDBSnapshots(kTRUE);
135 SetGenerator(generator);
138 //______________________________________________________________________________
139 AliMuonAccEffSubmitter::~AliMuonAccEffSubmitter()
143 delete fTemplateFileList;
144 delete fLocalFileList;
148 //______________________________________________________________________________
149 Bool_t AliMuonAccEffSubmitter::CheckCompilation(const char* file) const
151 /// Check whether file can be compiled or not
152 /// FIXME: use gSystem->TempFileName for tmpfile !
156 TString sfile(gSystem->BaseName(file));
157 TString tmpfile(Form("tmpfile_%s",sfile.Data()));
159 gSystem->Exec(Form("cp %s %s",file,tmpfile.Data()));
161 ReplaceVars(tmpfile.Data());
163 gSystem->AddIncludePath("-I$ALICE_ROOT/include");
164 gSystem->AddIncludePath("-I$ALICE_ROOT/EVGEN");
166 if (gROOT->LoadMacro(Form("%s++",tmpfile.Data())))
168 AliError(Form("macro %s can not be compiled. Please check.",file));
172 gSystem->Exec(Form("rm %s",tmpfile.Data()));
178 //______________________________________________________________________________
179 Bool_t AliMuonAccEffSubmitter::CheckLocal() const
181 /// Check whether all required local files are there
182 TIter next(LocalFileList());
185 while ( ( file = static_cast<TObjString*>(next())) )
187 if ( gSystem->AccessPathName(file->String().Data()) )
196 //______________________________________________________________________________
197 Bool_t AliMuonAccEffSubmitter::CheckRemote() const
199 /// Check whether all required remote files are there
200 AliWarning("implement me");
204 //______________________________________________________________________________
205 void AliMuonAccEffSubmitter::CleanLocal(Bool_t cleanSnapshots) const
207 /// Clean (remove) local generated files
208 /// As OCDB snapshot creation is a long process, cleanSnapshots
209 /// is kFALSE by default in order not to delete those.
211 TIter next(LocalFileList());
214 while ( ( file = static_cast<TObjString*>(next())) )
216 if ( !cleanSnapshots && file->String().Contains("OCDB_") ) continue;
217 gSystem->Unlink(file->String().Data());
221 //______________________________________________________________________________
222 void AliMuonAccEffSubmitter::CleanRemote() const
224 /// Clean (remove) remote files
225 AliWarning("implement me");
228 //______________________________________________________________________________
229 Bool_t AliMuonAccEffSubmitter::CopyFile(const char* localFile)
231 /// copy a local file to remote destination
234 if ( gSystem->IsAbsoluteFileName(localFile) )
240 local = Form("%s/%s",fLocalDir.Data(),gSystem->ExpandPathName(localFile));
243 if (gSystem->AccessPathName(local.Data()))
245 AliError(Form("Local file %s does not exist",local.Data()));
251 remote += fRemoteDir;
254 if ( gSystem->IsAbsoluteFileName(localFile) )
256 TString tmp(localFile);
257 tmp.ReplaceAll(fSnapshotDir.Data(),"");
265 TString dirName = gSystem->DirName(remote.Data());
269 if (!RemoteDirectoryExists(dirName.Data()))
271 ok = gGrid->Mkdir(dirName.Data(),"-p");
276 AliDebug(1,Form("cp %s alien://%s",local.Data(),remote.Data()));
277 return TFile::Cp(local.Data(),Form("alien://%s",remote.Data()));
285 //______________________________________________________________________________
286 Bool_t AliMuonAccEffSubmitter::CheckRemoteDir() const
288 /// Check we have a grid connection and that the remote dir exists
290 if (fRemoteDir.IsNull())
292 AliError("you must provide the grid location where to copy the files");
299 if (!TGrid::Connect("alien://"))
301 AliError("Cannot connect to grid");
306 if (!RemoteDirectoryExists(fRemoteDir))
308 AliError(Form("directory %s does not exist", fRemoteDir.Data()));
315 //______________________________________________________________________________
316 Bool_t AliMuonAccEffSubmitter::CopyLocalFilesToRemote()
318 /// copy all files necessary to run the simulation into remote directory
320 if (!IsValid()) return kFALSE;
324 if ( CheckRemoteDir() )
326 TString sdir(gSystem->ExpandPathName(LocalDir()));
328 TIter next(LocalFileList());
333 while ( ( ftc = static_cast<TObjString*>(next())) )
335 allok = allok && CopyFile(ftc->String());
343 //______________________________________________________________________________
344 Bool_t AliMuonAccEffSubmitter::CopyTemplateFilesToLocal()
346 // copy (or generate) local files from the template ones
348 if (!IsValid()) return kFALSE;
352 TIter next(TemplateFileList());
356 Bool_t potentialProblem(kFALSE);
358 while ( ( file = static_cast<TObjString*>(next())) )
360 if ( file->String().Contains("OCDB") )
362 /// OCDB snapshots are not in template
366 if ( !ShouldOverwriteFiles() && !gSystem->AccessPathName(file->String().Data()) )
368 AliError(Form("Local file %s already exists. Remove it first if you want to update overwrite it",file->String().Data()));
369 potentialProblem = kTRUE;
373 TString stemplate(Form("%s/%s",fTemplateDir.Data(),file->String().Data()));
374 TString slocal(Form("%s/%s",fLocalDir.Data(),file->String().Data()));
376 Int_t c = gSystem->CopyFile(stemplate.Data(),slocal.Data(),ShouldOverwriteFiles());
380 if ( stemplate.Contains(".jdl",TString::kIgnoreCase) )
382 if ( stemplate.Contains("merge",TString::kIgnoreCase) )
384 ok = GenerateMergeJDL(file->String().Data());
388 ok = GenerateRunJDL(file->String().Data());
393 AliError(Form("Error %d copying file %s",c,stemplate.Data()));
402 if ( HasVars(slocal.Data()) )
404 if (!ReplaceVars(slocal.Data()))
406 AliError("pb in ReplaceVars");
415 if ( potentialProblem )
417 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 !");
423 //______________________________________________________________________________
424 std::ostream* AliMuonAccEffSubmitter::CreateJDLFile(const char* name) const
426 /// Create a JDL file
429 TString jdl(Form("%s/%s",fLocalDir.Data(),name));
431 if ( !ShouldOverwriteFiles() && !gSystem->AccessPathName(jdl.Data()) )
433 AliError(Form("File %s already exists. Remove it if you want to overwrite it",jdl.Data()));
437 std::ofstream* os = new std::ofstream(gSystem->ExpandPathName(jdl.Data()));
441 AliError(Form("Cannot create file %s",jdl.Data()));
449 ///______________________________________________________________________________
450 Bool_t AliMuonAccEffSubmitter::GenerateMergeJDL(const char* name)
452 /// Create the JDL for merging jobs
453 /// FIXME: not checked !
457 std::ostream* os = CreateJDLFile(name);
464 Bool_t final = TString(name).Contains("merge",TString::kIgnoreCase);
466 (*os) << "# Generated merging jdl (production mode)" << std::endl
467 << "# $1 = run number" << std::endl
468 << "# $2 = merging stage" << std::endl
469 << "# Stage_<n>.xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip" << std::endl;
471 Output(*os,"Packages",fPackageAliroot.Data(),fPackageGeant3.Data(),
472 fPackageRoot.Data(),fPackageApi.Data());
474 Output(*os,"Executable","AOD_merge.sh");
476 Output(*os,"Price","1");
480 Output(*os,"Jobtag","comment: AliMuonAccEffSubmitter final merging");
484 Output(*os,"Jobtag","comment: AliMuonAccEffSubmitter merging stage $2");
487 Output(*os,"Workdirectorysize","5000MB");
489 Output(*os,"Validationcommand",Form("%s/validation_merge.sh",fRemoteDir.Data()));
491 Output(*os,"TTL","7200");
493 Output(*os,"OutputArchive",
494 "log_archive.zip:stderr,stdout@disk=1",
495 "root_archive.zip:AliAOD.root,AliAOD.Muons.root,AnalysisResults.root@disk=3"
498 Output(*os,"Arguments",(final ? "2":"1")); // for AOD_merge.sh, 1 means intermediate merging stage, 2 means final merging
502 Output(*os,"InputFile",Form("LF:%s/AODtrain.C",fRemoteDir.Data()));
503 Output(*os,"OutputDir",Form("%s/$1/Stage_$2/#alien_counter_03i#",fRemoteDir.Data()));
504 Output(*os,"InputDataCollection",Form("%s/$1/Stage_$2.xml,nodownload",fRemoteDir.Data()));
505 Output(*os,"split","se");
506 Output(*os,"SplitMaxInputFileNumber",GetSplitMaxInputFileNumber());
507 Output(*os,"InputDataListFormat","xml-single");
508 Output(*os,"InputDataList","wn.xml");
512 Output(*os,"InputFile",Form("LF:%s/AODtrain.C",fRemoteDir.Data()),
513 Form("LF:%s/$1/wn.xml",fRemoteDir.Data()));
514 Output(*os,"OutputDir",Form("%s/$1",fRemoteDir.Data()));
520 //______________________________________________________________________________
521 Bool_t AliMuonAccEffSubmitter::GenerateRunJDL(const char* name)
523 /// Generate (locally) the JDL to perform the simulation+reco+aod filtering
524 /// (to be then copied to the grid and finally submitted)
528 std::ostream* os = CreateJDLFile(name);
535 Output(*os,"Packages",fPackageAliroot.Data(),fPackageGeant3.Data(),
536 fPackageRoot.Data(),fPackageApi.Data());
538 Output(*os,"Jobtag","comment: AliMuonAccEffSubmitter RUN $1");
540 Output(*os,"split","production:1-$2");
542 Output(*os,"Price","1");
544 Output(*os,"OutputDir",Form("%s/$1/#alien_counter_03i#",fRemoteDir.Data()));
546 Output(*os,"Executable","/alice/bin/aliroot_new");
549 files.SetOwner(kTRUE);
550 TIter next(TemplateFileList());
553 while ( ( file = static_cast<TObjString*>(next())) )
555 if ( !file->String().Contains(".jdl",TString::kIgnoreCase) ||
556 !file->String().Contains("OCDB_") )
558 files.Add(new TObjString(Form("LF:%s/%s",fRemoteDir.Data(),file->String().Data())));
562 if ( fUseOCDBSnapshots )
564 files.Add(new TObjString(Form("LF:%s/OCDB/$1/OCDB_sim.root",fRemoteDir.Data())));
565 files.Add(new TObjString(Form("LF:%s/OCDB/$1/OCDB_rec.root",fRemoteDir.Data())));
568 Output(*os,"InputFile",files);
570 if ( CompactMode() == 0 )
573 Output(*os,"OutputArchive", "log_archive.zip:stderr,stdout,aod.log,checkaod.log,checkesd.log,rec.log,recwatch.log,sim.log,simwatch.log@disk=1",
574 "root_archive.zip:galice*.root,Kinematics*.root,TrackRefs*.root,AliESDs.root,AliAOD.root,AliAOD.Muons.root,Merged.QA.Data.root,Run*.root@disk=2");
576 else if ( CompactMode() == 1 )
578 // keep only muon AODs
579 Output(*os,"OutputArchive", "log_archive.zip:stderr,stdout,aod.log,checkaod.log,checkesd.log,rec.log,sim.log@disk=1",
580 "root_archive.zip:galice*.root,AliAOD.Muons.root@disk=2");
584 AliError(Form("Unknown CompactMode %d",CompactMode()));
589 Output(*os,"splitarguments","simrun.C --run $1 --chunk #alien_counter# --event $3");
591 Output(*os,"Workdirectorysize","5000MB");
593 Output(*os,"JDLVariables","Packages","OutputDir");
595 Output(*os,"Validationcommand",Form("%s/validation.sh",fRemoteDir.Data()));
597 Output(*os,"TTL","72000");
602 //______________________________________________________________________________
603 Bool_t AliMuonAccEffSubmitter::GetLastStage(const char* remoteDir) const
605 /// Get the last staging phase already performed
606 /// FIXME : not checked !
608 Int_t n = 0, lastStage = 0;
609 gSystem->Exec(Form("alien_ls -F %s | grep Stage_.*/ > __stage__", remoteDir));
610 ifstream f("__stage__");
612 while (std::getline(f, dummy)) n++;
614 while (n > 0) if (gSystem->Exec(Form("grep Stage_%d/ __stage__ 2>&1 >/dev/null", ++lastStage)) == 0) n--;
615 gSystem->Exec("rm -f __stage__");
619 //______________________________________________________________________________
620 TObjArray* AliMuonAccEffSubmitter::GetVariables(const char* file) const
622 /// Find the variables in the file
624 std::ifstream in(file);
626 TObjArray* variables(0x0);
628 while ( in.getline(line,1023,'\n') )
631 while (sline.Contains("VAR_") && !sline.BeginsWith("//") )
633 Int_t i1 = sline.Index("VAR_");
636 while ( ( i2 < sline.Length() ) && ( isalnum(sline[i2]) || sline[i2]=='_' ) ) ++i2;
640 variables = new TObjArray;
641 variables->SetOwner(kTRUE);
644 TString var = sline(i1,i2-i1);
645 if ( !variables->FindObject(var) )
647 variables->Add(new TObjString(var));
649 sline.ReplaceAll(var,"");
658 //______________________________________________________________________________
659 Bool_t AliMuonAccEffSubmitter::HasVars(const char* file) const
661 /// Whether or not the file contains variables that have to
664 std::ifstream in(file);
666 while ( in.getline(line,1023,'\n') )
669 if (sline.Contains("VAR_") && !sline.BeginsWith("//") )
677 //______________________________________________________________________________
678 TObjArray* AliMuonAccEffSubmitter::LocalFileList() const
680 /// Return (after createing and filling it if needed)
681 /// the internal file list with paths from the local directory
685 fLocalFileList = static_cast<TObjArray*>(TemplateFileList()->Clone());
688 return fLocalFileList;
691 //______________________________________________________________________________
692 Bool_t AliMuonAccEffSubmitter::MakeOCDBSnapshots()
694 /// Run sim.C and rec.C in a special mode to generate OCDB snapshots
695 /// Can only be done after the templates have been copied locally
697 if (!IsValid()) return kFALSE;
699 if (!fUseOCDBSnapshots) return kTRUE;
701 if (!fScalers) return kFALSE;
705 const std::vector<int>& runs = fScalers->GetRunList();
709 for ( std::vector<int>::size_type i = 0; i < runs.size(); ++i )
711 Int_t runNumber = runs[i];
713 TString ocdbSim(Form("%s/OCDB/%d/OCDB_sim.root",SnapshotDir().Data(),runNumber));
714 TString ocdbRec(Form("%s/OCDB/%d/OCDB_rec.root",SnapshotDir().Data(),runNumber));
716 if ( !gSystem->AccessPathName(ocdbSim.Data()) &&
717 !gSystem->AccessPathName(ocdbRec.Data()) )
719 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));
724 gSystem->Exec(Form("aliroot -b -q -x simrun.C --run %d --snapshot",runNumber));
726 if ( gSystem->AccessPathName(ocdbSim.Data()) )
728 AliError(Form("Could not create OCDB snapshot for simulation"));
732 if ( gSystem->AccessPathName(ocdbRec.Data()) )
734 AliError(Form("Could not create OCDB snapshot for reconstruction"));
739 LocalFileList()->Add(new TObjString(ocdbSim));
740 LocalFileList()->Add(new TObjString(ocdbRec));
746 //______________________________________________________________________________
747 Bool_t AliMuonAccEffSubmitter::Merge(Int_t stage, Bool_t dryRun)
749 /// Submit multiple merging jobs with the format "submit AOD_merge(_final).jdl run# (stage#)".
750 /// Also produce the xml collection before sending jobs
751 /// Initial AODs will be taken from fRemoteDir/[RUNNUMBER] while the merged
752 /// ones will be put into fMergedDir/AODs/[RUNNUMBER]
755 /// - inDir = "/alice/sim/2012/LHC12a10_bis" (where to find the data to merge)
756 /// = 0x0 --> inDir = homeDir/outDir/resDir
757 /// - outDir = "Sim/LHC11h/embedding/AODs" (where to store merged results)
758 /// - runList.txt must contains the list of run number
759 /// - stage=0 --> final merging / stage>0 --> intermediate merging i
762 if (!RemoteDirectoryExists(fMergedDir.Data())) {
763 AliError(Form("directory %s does not exist", fMergedDir.Data()));
767 gGrid->Cd(fMergedDir.Data());
769 TString jdl = MergeJDLName(stage==0);
771 if (!RemoteFileExists(jdl.Data()))
773 AliError(Form("file %s does not exist in %s\n", jdl.Data(), fRemoteDir.Data()));
777 const std::vector<int>& runs = fScalers->GetRunList();
781 AliError("No run to work with");
787 gSystem->Exec("rm -f __failed__");
788 Bool_t failedRun = kFALSE;
790 for ( std::vector<int>::size_type i = 0; i < runs.size(); ++i )
793 AliInfo(Form("\n --- processing run %d ---\n", run));
795 TString runDir = Form("%s/%d", fMergedDir.Data(), run);
797 if (!RemoteDirectoryExists(runDir.Data()))
799 AliInfo(Form(" - creating output directory %s\n", runDir.Data()));
800 gSystem->Exec(Form("alien_mkdir -p %s", runDir.Data()));
803 if (RemoteFileExists(Form("%s/root_archive.zip", runDir.Data())))
805 AliWarning(" ! final merging already done");
809 Int_t lastStage = GetLastStage(runDir.Data());
811 if (stage > 0 && stage != lastStage+1)
813 AliError(Form(" ! lastest merging stage = %d. Next must be stage %d or final stage\n", lastStage, lastStage+1));
817 TString wn = (stage > 0) ? Form("Stage_%d.xml", stage) : "wn.xml";
818 TString find = (lastStage == 0) ?
819 Form("alien_find -x %s %s/%d *root_archive.zip", wn.Data(), fRemoteDir.Data(), run) :
820 Form("alien_find -x %s %s/%d/Stage_%d *root_archive.zip", wn.Data(), fRemoteDir.Data(), run, lastStage);
821 gSystem->Exec(Form("%s 1> %s 2>/dev/null", find.Data(), wn.Data()));
822 gSystem->Exec(Form("grep -c /event %s > __nfiles__", wn.Data()));
823 ifstream f2("__nfiles__");
825 nFiles.ReadLine(f2,kTRUE);
827 gSystem->Exec("rm -f __nfiles__");
828 printf(" - number of files to merge = %d\n", nFiles.Atoi());
829 if (nFiles.Atoi() == 0) {
830 printf(" ! collection of files to merge is empty\n");
831 gSystem->Exec(Form("rm -f %s", wn.Data()));
833 } else if (stage > 0 && nFiles.Atoi() <= splitLevel && !reply.BeginsWith("y")) {
834 if (!reply.BeginsWith("n")) {
835 printf(" ! number of files to merge <= split level (%d). Continue? [Y/n] ", splitLevel);
837 reply.Gets(stdin,kTRUE);
840 if (reply.BeginsWith("n")) {
841 gSystem->Exec(Form("rm -f %s", wn.Data()));
848 TString dirwn = Form("%s/%s", runDir.Data(), wn.Data());
849 if (RemoteFileExists(dirwn.Data())) gGrid->Rm(dirwn.Data());
850 gSystem->Exec(Form("alien_cp file:%s alien://%s", wn.Data(), dirwn.Data()));
851 gSystem->Exec(Form("rm -f %s", wn.Data()));
855 if (stage > 0) query = Form("submit %s %d %d", jdl.Data(), run, stage);
856 else query = Form("submit %s %d", jdl.Data(), run);
857 printf(" - %s ...", query.Data());
866 Bool_t done = kFALSE;
867 TGridResult *res = gGrid->Command(query);
870 TString cjobId1 = res->GetKey(0,"jobId");
871 if (!cjobId1.IsDec())
879 AliInfo(Form(" DONE\n --> the job Id is: %s \n", cjobId1.Data()));
891 gSystem->Exec(Form("echo %d >> __failed__", run));
899 AliInfo("\n--------------------\n");
900 AliInfo("list of failed runs:\n");
901 gSystem->Exec("cat __failed__");
902 gSystem->Exec("rm -f __failed__");
909 //______________________________________________________________________________
910 UInt_t AliMuonAccEffSubmitter::NofRuns() const
912 // number of runs we're dealing with
913 if (!fScalers) return 0;
915 return fScalers->GetRunList().size();
918 //______________________________________________________________________________
919 void AliMuonAccEffSubmitter::Output(std::ostream& out, const char* key,
920 const TObjArray& values) const
922 /// output to ostream of key,{values} pair
926 Int_t n = values.GetEntries();
930 out << "{" << std::endl;
934 while ( ( v = static_cast<TObjString*>(next())) )
937 out << "\t\"" << v->String().Data() << "\"";
945 TString& v1 = static_cast<TObjString*>(values.At(0))->String();
953 out << "\"" << v1.Data() << "\"";
956 out << ";" << std::endl;
959 //______________________________________________________________________________
960 void AliMuonAccEffSubmitter::Output(std::ostream& out, const char* key, const char* v1,
961 const char* v2, const char* v3, const char* v4,
962 const char* v5, const char* v6, const char* v7,
963 const char* v8, const char* v9) const
965 /// output to ostream
968 values.SetOwner(kTRUE);
970 values.Add(new TObjString(v1));
971 if ( strlen(v2) > 0 ) values.Add(new TObjString(v2));
972 if ( strlen(v3) > 0 ) values.Add(new TObjString(v3));
973 if ( strlen(v4) > 0 ) values.Add(new TObjString(v4));
974 if ( strlen(v5) > 0 ) values.Add(new TObjString(v5));
975 if ( strlen(v6) > 0 ) values.Add(new TObjString(v6));
976 if ( strlen(v7) > 0 ) values.Add(new TObjString(v7));
977 if ( strlen(v8) > 0 ) values.Add(new TObjString(v8));
978 if ( strlen(v9) > 0 ) values.Add(new TObjString(v9));
980 Output(out,key,values);
984 //______________________________________________________________________________
985 void AliMuonAccEffSubmitter::Print(Option_t* /*opt*/) const
991 std::cout << std::string(80,'*') << std::endl;
992 std::cout << "INVALID OBJECT. CHECK BELOW THE CONFIGURATION." << std::endl;
993 std::cout << std::string(80,'*') << std::endl;
996 std::cout << "Template directory = " << fTemplateDir.Data() << std::endl;
997 std::cout << "Local directory = " << fLocalDir.Data() << std::endl;
998 std::cout << "Remote directory = " << fRemoteDir.Data() << std::endl;
1000 if ( fSnapshotDir != fLocalDir )
1002 std::cout << "Snapshots directory = " << fSnapshotDir.Data() << std::endl;
1005 std::cout << "OCDB path = " << fOCDBPath.Data() << std::endl;
1009 std::cout << Form("For each run, will generate %5.2f times the number of real events for trigger %s",
1010 fRatio,fReferenceTrigger.Data()) << std::endl;
1014 std::cout << Form("For each run, will generate %10d events",fFixedNofEvents) << std::endl;
1017 std::cout << "MaxEventsPerChunk = " << fMaxEventsPerChunk << std::endl;
1021 std::cout << NofRuns() << " run";
1022 if ( NofRuns() > 1 ) std::cout << "s";
1031 while ( ( key = static_cast<TObjString*>(next())) )
1033 TObjString* value = static_cast<TObjString*>(fVars->GetValue(key->String()));
1034 std::cout << "Variable " << key->String() << " will be replaced by " << value->String() << std::endl;
1038 std::cout << "Files to be uploaded:" << std::endl;
1039 TIter nextFile(LocalFileList());
1041 while ( ( sfile = static_cast<TObjString*>(nextFile())) )
1043 std::cout << sfile->String().Data() << std::endl;
1048 //______________________________________________________________________________
1049 Bool_t AliMuonAccEffSubmitter::RemoteDirectoryExists(const char *dirname) const
1051 // Returns true if directory exists. Can be also a path.
1052 if (!gGrid) return kFALSE;
1053 // Check if dirname is a path
1054 TString dirstripped = dirname;
1055 dirstripped = dirstripped.Strip();
1056 dirstripped = dirstripped.Strip(TString::kTrailing, '/');
1057 TString dir = gSystem->BaseName(dirstripped);
1059 TString path = gSystem->DirName(dirstripped);
1060 TGridResult *res = gGrid->Ls(path, "-F");
1061 if (!res) return kFALSE;
1065 while ((map=dynamic_cast<TMap*>(next()))) {
1066 obj = map->GetValue("name");
1068 if (dir == obj->GetName()) {
1077 //______________________________________________________________________________
1078 Bool_t AliMuonAccEffSubmitter::RemoteFileExists(const char *lfn) const
1080 // Returns true if file exists.
1081 if (!gGrid) return kFALSE;
1082 TGridResult *res = gGrid->Ls(lfn);
1083 if (!res) return kFALSE;
1084 TMap *map = dynamic_cast<TMap*>(res->At(0));
1089 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("name"));
1090 if (!objs || !objs->GetString().Length()) {
1098 //______________________________________________________________________________
1099 Bool_t AliMuonAccEffSubmitter::ReplaceVars(const char* file) const
1101 /// Replace the variables (i.e. things starting by VAR_) found in file
1103 std::ifstream in(file);
1106 lines.SetOwner(kTRUE);
1112 while ( in.getline(line,1023,'\n') )
1114 TString sline(line);
1115 while (sline.Contains("VAR_") && !sline.BeginsWith("//") )
1120 while ( ( key = static_cast<TObjString*>(next())) )
1122 if ( sline.Contains(key->String()) )
1125 TObjString* value = static_cast<TObjString*>(fVars->GetValue(key->String()));
1126 sline.ReplaceAll(key->String(),value->String());
1132 lines.Add(new TObjString(sline));
1139 if ( nreplaced != nvars )
1141 AliError(Form("nvars=%d nreplaced=%d",nvars,nreplaced));
1144 std::ofstream out(file);
1145 TIter nextLine(&lines);
1147 while ( ( s = static_cast<TObjString*>(nextLine()) ) )
1149 out << s->String().Data() << std::endl;
1157 //______________________________________________________________________________
1158 Bool_t AliMuonAccEffSubmitter::Run(const char* mode)
1160 /// mode can be one of (case insensitive)
1162 /// LOCAL : copy the template files from the template directory to the local one
1163 /// UPLOAD : copy the local files to the grid (requires LOCAL)
1164 /// OCDB : make ocdb snapshots (requires LOCAL)
1165 /// SUBMIT : submit the jobs (requires LOCAL + UPLOAD)
1166 /// FULL : all of the above (requires all of the above)
1168 /// TEST : as SUBMIT, but in dry mode (does not actually submit the jobs)
1170 if (!IsValid()) return kFALSE;
1172 TString smode(mode);
1175 if ( smode == "FULL")
1177 return ( Run("LOCAL") && Run("OCDB") && Run("UPLOAD") && Run("SUBMIT") );
1180 if ( smode == "LOCAL")
1182 return CopyTemplateFilesToLocal();
1185 if ( smode == "UPLOAD" )
1187 return (CopyLocalFilesToRemote());
1190 if ( smode == "OCDB" )
1192 Bool_t ok = Run("LOCAL");
1195 ok = MakeOCDBSnapshots();
1200 if ( smode == "TEST" )
1202 Bool_t ok = Run("LOCAL") && Run("OCDB") && Run("UPLOAD");
1205 ok = (Submit(kTRUE)>0);
1210 if ( smode == "FULL" )
1212 Bool_t ok = Run("LOCAL") && Run("OCDB") && Run("UPLOAD");
1215 ok = (Submit(kFALSE)>0);
1220 if( smode == "SUBMIT" )
1222 return (Submit(kFALSE)>0);
1228 //______________________________________________________________________________
1229 void AliMuonAccEffSubmitter::SetPackages(const char* aliroot,
1234 /// Set the packages to be used by the jobs
1235 /// Must be a valid combination, see http://alimonitor.cern.ch/packages/
1237 fPackageAliroot = aliroot;
1238 fPackageRoot = root;
1239 fPackageGeant3 = geant3;
1243 //______________________________________________________________________________
1244 TString AliMuonAccEffSubmitter::GetRemoteDir(const char* dir, Bool_t create)
1246 /// Set the target remote directory (on the grid)
1248 if (!RemoteDirectoryExists(dir))
1252 AliError(Form("Remote directory %s does not exist", dir));
1257 AliInfo(Form("Remote directory %s does not exist. Trying to create it...",dir));
1258 if ( !gGrid->Mkdir(dir,"-p") )
1260 AliError(Form("Could not create remote dir. Sorry."));
1268 //______________________________________________________________________________
1269 Bool_t AliMuonAccEffSubmitter::SetGenerator(const char* generator)
1271 // set the variable to select the generator macro in Config.C
1273 gSystem->Load("libEVGEN");
1277 TString generatorFile(Form("%s/%s.C",fTemplateDir.Data(),generator));
1279 Int_t nofMissingVariables(0);
1281 // first check we indeed have such a macro
1282 if (!gSystem->AccessPathName(generatorFile.Data()))
1284 TObjArray* variables = GetVariables(generatorFile.Data());
1286 TIter next(variables);
1289 while ( ( var = static_cast<TObjString*>(next())) )
1291 if ( !fVars->GetValue(var->String()) )
1293 ++nofMissingVariables;
1294 AliError(Form("file %s expect the variable %s to be defined, but we've not defined it !",generatorFile.Data(),var->String().Data()));
1300 if ( !nofMissingVariables )
1302 if (CheckCompilation(generatorFile.Data()))
1305 SetVar("VAR_GENERATOR",Form("%s",generator));
1306 TemplateFileList()->Add(new TObjString(Form("%s.C",generator)));
1317 AliError(Form("Can not work with the macro %s",generatorFile.Data()));
1322 //______________________________________________________________________________
1323 Bool_t AliMuonAccEffSubmitter::SetMergedDir(const char* dir, Bool_t create)
1325 // Set the merged directory to be used
1326 fMergedDir = GetRemoteDir(dir,create);
1327 return (fMergedDir.Length()>0);
1330 //______________________________________________________________________________
1331 Bool_t AliMuonAccEffSubmitter::SetRemoteDir(const char* dir, Bool_t create)
1333 // Set the remote directory to be used
1334 fRemoteDir = GetRemoteDir(dir,create);
1335 return (fIsValid = (fRemoteDir.Length()>0));
1339 //______________________________________________________________________________
1340 void AliMuonAccEffSubmitter::SetRunList(const char* runList)
1342 // set the runlist from a text file
1345 fScalers = new AliAnalysisTriggerScalers(runList,fOCDBPath.Data());
1349 fScalers->SetRunList(runList);
1351 UpdateLocalFileList(kTRUE);
1354 //______________________________________________________________________________
1355 void AliMuonAccEffSubmitter::SetRunList(int runNumber)
1357 // set the runlist from a text file
1360 fScalers = new AliAnalysisTriggerScalers(runNumber,fOCDBPath.Data());
1364 fScalers->SetRunList(runNumber);
1366 UpdateLocalFileList(kTRUE);
1369 //______________________________________________________________________________
1370 void AliMuonAccEffSubmitter::SetOCDBPath(const char* ocdbPath)
1372 /// Sets the OCDB path to be used
1374 fOCDBPath = ocdbPath;
1378 // redefine trigger scalers to use the new ocdb path
1379 AliAnalysisTriggerScalers* ts = new AliAnalysisTriggerScalers(fScalers->GetRunList(),
1388 //______________________________________________________________________________
1389 void AliMuonAccEffSubmitter::SetOCDBSnapshotDir(const char* dir)
1391 // change the directory used for snapshot
1393 if (gSystem->AccessPathName(Form("%s/OCDB",dir)))
1395 AliError(Form("Snapshot top directory (%s) should contain an OCDB subdir with runnumbers in there",dir));
1403 //______________________________________________________________________________
1404 Bool_t AliMuonAccEffSubmitter::SetVar(const char* varname, const char* value)
1410 if (!s.BeginsWith("VAR_"))
1412 AliError("Variable name should start with VAR_");
1418 fVars->SetOwnerKeyValue(kTRUE,kTRUE);
1421 TObject* o = new TObjString(s);
1424 fVars->Add(o,new TObjString(value));
1429 //______________________________________________________________________________
1430 Int_t AliMuonAccEffSubmitter::Submit(Bool_t dryRun)
1432 /// Submit multiple production jobs with the format "submit jdl 000run#.xml 000run#".
1434 /// Return the number of submitted (master) jobs
1437 /// - outputDir = "/alice/cern.ch/user/p/ppillot/Sim/LHC10h/JPsiPbPb276/AlignRawVtxRaw/ESDs"
1438 /// - runList must contains the list of run number
1439 /// - trigger is the (fully qualified) trigger name used to compute the base number of events
1440 /// - mult is the factor to apply to the number of trigger to get the number of events to be generated
1441 /// (# generated events = # triggers x mult
1443 if (!IsValid()) return 0;
1447 gGrid->Cd(RemoteDir());
1449 if (!RemoteFileExists(RunJDLName()))
1451 AliError(Form("file %s does not exist in %s", RunJDLName().Data(), RemoteDir().Data()));
1457 AliError("No run list set. Use SetRunList");
1460 const std::vector<int>& runs = fScalers->GetRunList();
1464 AliError("No run to work with");
1468 // cout << "total number of selected MB events = " << totEvt << endl;
1469 // cout << "required number of generated events = " << nGenEvents << endl;
1470 // cout << "number of generated events per MB event = " << ratio << endl;
1473 std::cout << "run\tchunks\tevents" << std::endl;
1474 std::cout << "----------------------" << std::endl;
1479 for (std::vector<int>::size_type i=0; i < runs.size(); ++i)
1481 Int_t runNumber = runs[i];
1483 Int_t nEvtRun(fFixedNofEvents);
1487 AliAnalysisTriggerScalerItem* trigger = fScalers->GetTriggerScaler(runNumber, "L2A", ReferenceTrigger().Data());
1491 AliError(Form("Could not get trigger %s for run %09d",ReferenceTrigger().Data(),runNumber));
1494 nEvtRun = TMath::Nint(fRatio * trigger->Value());
1499 while (nEvtRun/nChunk+0.5 > MaxEventsPerChunk())
1504 Int_t nEvtChunk = TMath::Nint(nEvtRun/nChunk + 0.5);
1508 nEvts += nChunk*nEvtChunk;
1510 std::cout << runNumber << "\t" << nChunk << "\t" << nEvtChunk << std::endl;
1512 TString query(Form("submit %s %d %d %d", RunJDLName().Data(), runNumber, nChunk, nEvtChunk));
1514 std::cout << query.Data() << " ..." << std::flush;
1516 TGridResult* res = 0x0;
1520 res = gGrid->Command(query);
1525 TString cjobId1 = res->GetKey(0,"jobId");
1527 if (!cjobId1.Length())
1529 std::cout << " FAILED" << std::endl << std::endl;
1535 std::cout << "DONE" << std::endl;
1536 std::cout << Form(" --> the job Id is: %s",cjobId1.Data()) << std::endl << std::endl;
1541 std::cout << " FAILED" << std::endl << std::endl;
1547 std::cout << std::endl
1548 << "total number of jobs = " << nJobs << std::endl
1549 << "total number of generated events = " << nEvts << std::endl
1555 //______________________________________________________________________________
1556 TObjArray* AliMuonAccEffSubmitter::TemplateFileList() const
1558 /// Return (after createing and filling it if needed)
1559 /// the internal file list with paths from the template directory
1561 if (!fTemplateFileList)
1563 fTemplateFileList = new TObjArray;
1564 fTemplateFileList->SetOwner(kTRUE);
1566 fTemplateFileList->Add(new TObjString("CheckESD.C"));
1567 fTemplateFileList->Add(new TObjString("CheckAOD.C"));
1568 fTemplateFileList->Add(new TObjString("AODtrain.C"));
1569 fTemplateFileList->Add(new TObjString("validation.sh"));
1570 if ( fExternalConfig.Length() > 0 )
1572 fTemplateFileList->Add(new TObjString(fExternalConfig));
1576 fTemplateFileList->Add(new TObjString("Config.C"));
1578 fTemplateFileList->Add(new TObjString("rec.C"));
1579 fTemplateFileList->Add(new TObjString("sim.C"));
1580 fTemplateFileList->Add(new TObjString("simrun.C"));
1581 fTemplateFileList->Add(new TObjString(RunJDLName().Data()));
1582 fTemplateFileList->Add(new TObjString(MergeJDLName(kFALSE).Data()));
1583 fTemplateFileList->Add(new TObjString(MergeJDLName(kTRUE).Data()));
1584 fTemplateFileList->Add(new TObjString("AOD_merge.sh"));
1585 fTemplateFileList->Add(new TObjString("validation_merge.sh"));
1588 return fTemplateFileList;
1591 //______________________________________________________________________________
1592 void AliMuonAccEffSubmitter::UpdateLocalFileList(Bool_t clearSnapshots)
1594 /// Update the list of local files
1596 if (!fScalers) return;
1598 if ( clearSnapshots )
1600 TIter next(LocalFileList());
1603 while ( ( file = static_cast<TObjString*>(next())) )
1605 if ( file->String().Contains("OCDB_") )
1607 LocalFileList()->Remove(file);
1610 LocalFileList()->Compress();
1613 const std::vector<int>& runs = fScalers->GetRunList();
1615 const char* type[] = { "sim","rec" };
1617 for ( std::vector<int>::size_type i = 0; i < runs.size(); ++i )
1619 Int_t runNumber = runs[i];
1621 for ( Int_t t = 0; t < 2; ++t )
1623 TString snapshot(Form("%s/OCDB/%d/OCDB_%s.root",SnapshotDir().Data(),runNumber,type[t]));
1625 if ( !gSystem->AccessPathName(snapshot.Data()) )
1627 if ( !LocalFileList()->FindObject(snapshot.Data()) )
1629 LocalFileList()->Add(new TObjString(snapshot));
1637 //______________________________________________________________________________
1638 void AliMuonAccEffSubmitter::UseOCDBSnapshots(Bool_t flag)
1640 /// Whether or not to use OCDB snapshots
1641 /// Using OCDB snapshots will speed-up both the sim and reco initialization
1642 /// phases on each worker node, but takes time to produce...
1643 /// So using them is not always a win-win...
1645 fUseOCDBSnapshots = flag;
1648 SetVar("VAR_OCDB_SNAPSHOT","kTRUE");
1652 SetVar("VAR_OCDB_SNAPSHOT","kFALSE");
1655 UpdateLocalFileList();