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