]>
Commit | Line | Data |
---|---|---|
56199f2b | 1 | /** |
bd6f5206 | 2 | * @defgroup pwglf_forward_trains Trains |
56199f2b | 3 | * |
e01b1d30 | 4 | * Train specifications |
5 | * | |
bd6f5206 | 6 | * @ingroup pwglf_forward |
56199f2b | 7 | */ |
1d86b7ca | 8 | /** |
9 | * @file TrainSetup.C | |
10 | * @author Christian Holm Christensen <cholm@dalsgaard.hehi.nbi.dk> | |
11 | * @date Wed Mar 23 12:12:00 2011 | |
12 | * | |
13 | * @brief | |
14 | * | |
bd6f5206 | 15 | * @ingroup pwglf_forward_trains |
1d86b7ca | 16 | * |
17 | */ | |
18 | ||
19 | #ifndef __CINT__ | |
20 | #include <fstream> | |
21 | #include <iostream> | |
07ff2416 | 22 | #include <cstdlib> |
1d86b7ca | 23 | |
7684b64e | 24 | #include <TGridCollection.h> |
1d86b7ca | 25 | #include <TArrayI.h> |
26 | #include <TChain.h> | |
27 | #include <TDatime.h> | |
28 | #include <TEnv.h> | |
29 | #include <TFile.h> | |
30 | #include <TGrid.h> | |
31 | #include <TList.h> | |
32 | #include <TObjString.h> | |
33 | #include <TProof.h> | |
34 | #include <TString.h> | |
35 | #include <TSystem.h> | |
36 | #include <TSystemDirectory.h> | |
37 | #include <TSystemFile.h> | |
38 | #include <TROOT.h> | |
39 | ||
40 | #include <AliAODHandler.h> | |
41 | #include <AliAODInputHandler.h> | |
42 | #include <AliAnalysisDataContainer.h> | |
43 | #include <AliAnalysisManager.h> | |
44 | #include <AliAnalysisAlien.h> | |
45 | #include <AliESDInputHandler.h> | |
46 | #include <AliMCEventHandler.h> | |
47 | #include <AliVEventHandler.h> | |
48 | #include <AliPhysicsSelection.h> | |
49 | #include <AliCentralitySelectionTask.h> | |
50 | #else | |
51 | class TArrayI; | |
52 | class TChain; | |
53 | class AliAnalysisManager; | |
2a276c75 | 54 | class TDatime; |
e01b1d30 | 55 | class TString; |
56 | class TSystemDirectory; | |
1d86b7ca | 57 | #endif |
58 | ||
e01b1d30 | 59 | |
60 | ||
1d86b7ca | 61 | //==================================================================== |
62 | /** | |
63 | * Generic set-up of an analysis train using the grid-handler (AliEn plugin). | |
1d86b7ca | 64 | * |
e01b1d30 | 65 | * See also @ref train_setup_doc |
66 | * | |
bd6f5206 | 67 | * @ingroup pwglf_forward_trains |
1d86b7ca | 68 | * |
69 | */ | |
70 | struct TrainSetup | |
71 | { | |
e01b1d30 | 72 | // Forward declaration |
73 | class Runner; | |
1d86b7ca | 74 | /** |
75 | * Data type to process | |
76 | */ | |
77 | enum EType { | |
78 | /** Event Summary Data */ | |
79 | kESD, | |
80 | /** Analysis Object Data */ | |
e01b1d30 | 81 | kAOD, |
82 | /** User defined */ | |
83 | kUser | |
1d86b7ca | 84 | }; |
85 | /** | |
86 | * How to run the analysis | |
87 | * | |
88 | */ | |
89 | enum EMode { | |
90 | /** Locally */ | |
91 | kLocal = 1, | |
92 | /** In PROOF(-Lite) cluster */ | |
93 | kProof, | |
94 | /** On the Grid */ | |
95 | kGrid | |
96 | }; | |
97 | /** | |
98 | * What stage of the analysis to run | |
99 | * | |
100 | */ | |
101 | enum EOper { | |
102 | /** Testing. Local processing, a single copied from Grid */ | |
103 | kTest, | |
104 | /** Off-line */ | |
105 | kOffline, | |
106 | /** Submit to queue */ | |
107 | kSubmit, | |
108 | /** Merge and terminate */ | |
109 | kTerminate, | |
110 | /** Full run */ | |
e01b1d30 | 111 | kFull, |
112 | /** Only intialize */ | |
113 | kInitialize | |
1d86b7ca | 114 | }; |
115 | ||
f53fb4f6 | 116 | |
117 | //__________________________________________________________________ | |
118 | virtual ~TrainSetup() {} | |
119 | ||
1d86b7ca | 120 | //__________________________________________________________________ |
121 | /** | |
122 | * Constructor | |
123 | * | |
124 | * @param name Name of analysis (free-form) | |
e01b1d30 | 125 | */ |
126 | TrainSetup(const char* name) | |
1d86b7ca | 127 | : fName(name), |
2a276c75 | 128 | fEscapedName(name), |
1d86b7ca | 129 | fRootVersion("v5-28-00a"), |
130 | fAliRootVersion("v4-21-18-AN"), | |
131 | fAliEnAPIVersion("V1.1x"), | |
132 | fProofServer("alicecaf.cern.ch"), | |
133 | fDataDir("/alice/data/2010/LHC10c"), | |
e01b1d30 | 134 | fDataPattern("*"), |
1d86b7ca | 135 | fDataSet("/COMMON/COMMON/LHC09a4_run8100X#/esdTree"), |
136 | fXML(""), | |
2a276c75 | 137 | fNReplica(4), |
2a276c75 | 138 | fAllowOverwrite(kFALSE), |
139 | fUseGDB(kFALSE), | |
140 | fMaxSplit(50), | |
1d86b7ca | 141 | fRunNumbers(0), |
142 | fListOfPARs(), | |
143 | fListOfSources(), | |
144 | fListOfLibraries(), | |
145 | fListOfExtras(), | |
e01b1d30 | 146 | fDatime(1995, 0, 0, 0, 0, 0), |
147 | fExecType(kUser), | |
148 | fExecMode(kLocal), | |
149 | fExecOper(kFull), | |
150 | fUsePar(false), | |
151 | fMC(false), | |
152 | fPerRunMerge(false), | |
153 | fVerbose(0) | |
2a276c75 | 154 | { |
2a276c75 | 155 | fEscapedName = EscapeName(fName, fDatime); |
1d86b7ca | 156 | } |
1d86b7ca | 157 | //__________________________________________________________________ |
158 | /** | |
e01b1d30 | 159 | * @{ |
160 | * @name Software environment | |
161 | */ | |
162 | /** | |
163 | * Set ROOT version to use | |
1d86b7ca | 164 | * |
e01b1d30 | 165 | * @param v Version string of ROOT |
166 | */ | |
167 | void SetROOTVersion(const char* v) { fRootVersion = v; } | |
168 | /** | |
169 | * Set AliROOT version to use | |
1d86b7ca | 170 | * |
e01b1d30 | 171 | * @param v Version string of AliROOT |
1d86b7ca | 172 | */ |
e01b1d30 | 173 | void SetAliROOTVersion(const char* v) { fAliRootVersion = v; } |
1d86b7ca | 174 | /** |
e01b1d30 | 175 | * Set the AliEn API version to use |
1d86b7ca | 176 | * |
e01b1d30 | 177 | * @param v AliEn API version |
178 | */ | |
179 | void SetAliEnAPIVersion(const char* v) { fAliEnAPIVersion = v; } | |
180 | /** | |
181 | * Wether to use par files through-out. Mandetory and enforced in | |
182 | * case of a PROOF job, | |
1d86b7ca | 183 | * |
e01b1d30 | 184 | * @param usePar If true, use PAR files - even for base libraries |
1d86b7ca | 185 | */ |
e01b1d30 | 186 | void SetUsePar(Bool_t usePar) { fUsePar = usePar; } |
187 | /* @} */ | |
188 | ||
1d86b7ca | 189 | //__________________________________________________________________ |
190 | /** | |
e01b1d30 | 191 | * @{ |
192 | * @name Input data | |
193 | */ | |
194 | /** | |
195 | * Set the GRID/Local data dir | |
1d86b7ca | 196 | * |
e01b1d30 | 197 | * @param d Directory with data |
198 | */ | |
199 | void SetDataDir(const char* d) { fDataDir = d; } | |
200 | /** | |
201 | * Set the glob pattern to search input files in - Grid only | |
1d86b7ca | 202 | * |
e01b1d30 | 203 | * @param pattern Glob pattern |
1d86b7ca | 204 | */ |
e01b1d30 | 205 | void SetDataPattern(const char* pattern) { fDataPattern = pattern; } |
206 | /** | |
207 | * Set the PROOF data set | |
208 | * | |
209 | * @param d PROOF registered data set | |
210 | */ | |
211 | void SetDataSet(const char* d) { fDataSet = d; } | |
212 | /** | |
213 | * Set the XML file to use | |
214 | * | |
215 | * @param x XML file | |
216 | */ | |
217 | void SetXML(const char* x) { fXML = x; } | |
218 | /** | |
219 | * Wether to assume the input comes from MC. If this is set to | |
220 | * true, and the CreateMCHandler member function isn't overloaded to | |
221 | * return null, then the files @c galice.root, @c Kinematics.root, | |
222 | * and @c TrackRefs.root must be present for each input file (@c | |
223 | * AliESDs.root or @c AliAOD.root) | |
224 | * | |
225 | * @param isMC If true, assume MC input | |
226 | */ | |
227 | void SetMC(Bool_t isMC) { fMC = isMC; } | |
228 | /* @} */ | |
1d86b7ca | 229 | |
230 | //__________________________________________________________________ | |
231 | /** | |
e01b1d30 | 232 | * @{ |
233 | * @name Grid storage and splitting | |
234 | */ | |
235 | /** | |
236 | * Set how many replicas of the output we want | |
1d86b7ca | 237 | * |
e01b1d30 | 238 | * @param n Number of replicas requested |
1d86b7ca | 239 | */ |
e01b1d30 | 240 | void SetNReplica(Int_t n) { fNReplica = n; } |
241 | /** | |
242 | * Set the maximum number of files per sub-job. | |
243 | * | |
244 | * @param max Maximum number of files per sub-job | |
245 | */ | |
246 | void SetMaxSplit(UShort_t max=50) { fMaxSplit = max; } | |
247 | /* @} */ | |
248 | ||
1d86b7ca | 249 | //__________________________________________________________________ |
250 | /** | |
e01b1d30 | 251 | * @{ |
252 | * @name Name and local working directory | |
253 | */ | |
254 | /** | |
255 | * Set whether to allow overwritting existing files/directories | |
1d86b7ca | 256 | * |
e01b1d30 | 257 | * @param allow If true, allow overwritting files/directories |
258 | */ | |
259 | void SetAllowOverwrite(Bool_t allow) { fAllowOverwrite = allow; } | |
260 | /** | |
261 | * Set the date and time | |
1d86b7ca | 262 | * |
e01b1d30 | 263 | * @param year Year (>1994) |
264 | * @param month Month | |
265 | * @param day Day | |
266 | * @param hour Hour | |
267 | * @param minutes Minute | |
1d86b7ca | 268 | */ |
e01b1d30 | 269 | void SetDateTime(UShort_t year, UShort_t month, UShort_t day, |
270 | UShort_t hour, UShort_t minutes) | |
1d86b7ca | 271 | { |
e01b1d30 | 272 | fDatime.Set((year<1995?1995:year), month, day, hour, minutes, 0); |
273 | fEscapedName = EscapeName(fName, fDatime); | |
1d86b7ca | 274 | } |
1d86b7ca | 275 | /** |
e01b1d30 | 276 | * Set the date and time from a string. |
1d86b7ca | 277 | * |
e01b1d30 | 278 | * @param date Formatted like YYYY/MM/DD HH:MM:SS |
1d86b7ca | 279 | */ |
e01b1d30 | 280 | void SetDateTime(const TString& date) |
281 | { | |
282 | if (date.IsNull()) | |
283 | fDatime.Set(1985,0,0,0,0,0); | |
284 | else if (date.EqualTo("now", TString::kIgnoreCase)) | |
285 | fDatime.Set(); | |
286 | else | |
287 | fDatime.Set(date); | |
288 | fEscapedName = EscapeName(fName, fDatime); | |
289 | } | |
1d86b7ca | 290 | /** |
e01b1d30 | 291 | * Return the escaped name |
1d86b7ca | 292 | * |
e01b1d30 | 293 | * @return Escaped name |
1d86b7ca | 294 | */ |
e01b1d30 | 295 | const TString& EscapedName() const |
296 | { | |
297 | return fEscapedName; | |
298 | } | |
299 | /* @} */ | |
2a276c75 | 300 | //__________________________________________________________________ |
301 | /** | |
e01b1d30 | 302 | * @{ |
303 | * @name Execution parameters | |
2a276c75 | 304 | */ |
1d86b7ca | 305 | /** |
306 | * Set the PROOF server URL | |
307 | * | |
308 | * @param s PROOF server URL | |
309 | */ | |
310 | void SetProofServer(const char* s) { fProofServer = s; } | |
1d86b7ca | 311 | /** |
e01b1d30 | 312 | * Set the type of analysis |
1d86b7ca | 313 | * |
e01b1d30 | 314 | * @param type AOD or ESD |
1d86b7ca | 315 | */ |
e01b1d30 | 316 | void SetType(EType type) { fExecType = type; } |
1d86b7ca | 317 | /** |
e01b1d30 | 318 | * Set the type of analysis |
1d86b7ca | 319 | * |
e01b1d30 | 320 | * @param type AOD or ESD |
1d86b7ca | 321 | */ |
e01b1d30 | 322 | void SetType(const char* type) { SetType(ParseType(type)); } |
1d86b7ca | 323 | /** |
e01b1d30 | 324 | * Set the execution mode of analysis |
1d86b7ca | 325 | * |
e01b1d30 | 326 | * @param mode LOCAL, PROOF, GRID |
1d86b7ca | 327 | */ |
e01b1d30 | 328 | void SetMode(EMode mode) { fExecMode = mode; } |
1d86b7ca | 329 | /** |
e01b1d30 | 330 | * Set the execution mode of analysis |
1d86b7ca | 331 | * |
e01b1d30 | 332 | * @param mode LOCAL, PROOF, GRID |
1d86b7ca | 333 | */ |
e01b1d30 | 334 | void SetMode(const char* mode) { SetMode(ParseMode(mode)); } |
1d86b7ca | 335 | /** |
e01b1d30 | 336 | * Set the execution operation of analysis |
1d86b7ca | 337 | * |
e01b1d30 | 338 | * @param oper FULL, TERMINATE, INIT |
1d86b7ca | 339 | */ |
e01b1d30 | 340 | void SetOperation(EOper oper) { fExecOper = oper; } |
1d86b7ca | 341 | /** |
e01b1d30 | 342 | * Set the execution operation of analysis |
1d86b7ca | 343 | * |
e01b1d30 | 344 | * @param oper FULL, TERMINATE, INIT |
1d86b7ca | 345 | */ |
e01b1d30 | 346 | void SetOperation(const char* oper) { SetOperation(ParseOperation(oper)); } |
871a9ac1 | 347 | /** |
348 | * Use GDB to wrap PROOF slaves | |
349 | * | |
350 | * @param use Whether to use GDB or not | |
351 | */ | |
352 | void SetUseGDB(Bool_t use=kTRUE) { fUseGDB = use; } | |
e01b1d30 | 353 | /* @} */ |
354 | ||
871a9ac1 | 355 | //__________________________________________________________________ |
2a276c75 | 356 | /** |
e01b1d30 | 357 | * @{ |
358 | * @name Stuff to upload | |
359 | */ | |
1d86b7ca | 360 | /** |
361 | * Add a source file to be copied and byte compiled on slaves | |
362 | * | |
363 | * @param src Sources | |
364 | * @param addToExtra If false, do not copy | |
365 | */ | |
366 | void AddSource(const char* src, bool addToExtra=true) | |
367 | { | |
368 | fListOfSources.Add(new TObjString(src)); | |
369 | if (addToExtra) AddExtraFile(src); // Source code isn't copied! | |
370 | } | |
1d86b7ca | 371 | /** |
372 | * Add binary data to be uploaded to slaves | |
373 | * | |
374 | * @param lib Name of binary file | |
375 | */ | |
376 | void AddLibrary(const char* lib) { fListOfLibraries.Add(new TObjString(lib));} | |
e01b1d30 | 377 | /** |
378 | * Add an extra file to be uploaded to slave | |
379 | * | |
380 | * @param file Extra file to be uploaded | |
381 | */ | |
382 | void AddExtraFile(const char* file) | |
383 | { | |
384 | if (!file || file[0] == '\0') return; | |
385 | fListOfExtras.Add(new TObjString(file)); | |
386 | } | |
387 | /* @} */ | |
388 | ||
1d86b7ca | 389 | //__________________________________________________________________ |
e01b1d30 | 390 | /** |
391 | * @{ | |
392 | * @name Run numbers | |
393 | */ | |
1d86b7ca | 394 | /** |
395 | * Add a run to be analysed | |
396 | * | |
397 | * @param run Run number | |
398 | */ | |
399 | void AddRun(Int_t run) | |
400 | { | |
401 | Int_t i = fRunNumbers.fN; fRunNumbers.Set(i+1); fRunNumbers[i] = run; | |
402 | } | |
1d86b7ca | 403 | /** |
404 | * Read run numbers from a file | |
405 | * | |
406 | * @param filename File name | |
407 | */ | |
408 | void ReadRunNumbers(const char* filename) | |
409 | { | |
410 | std::ifstream file(filename); | |
411 | if (!file) | |
412 | Fatal("ReadRunNumbers", "Cannot read from %s", filename); | |
413 | ||
414 | while (!file.eof()) { | |
415 | Int_t run; | |
416 | file >> run; | |
417 | AddRun(run); | |
418 | Char_t c; | |
419 | file >> c; | |
420 | if (file.bad()) break; | |
421 | } | |
422 | file.close(); | |
423 | } | |
1d86b7ca | 424 | /** |
e01b1d30 | 425 | * Set the runs to read from a string. The parts should be |
426 | * delimited by a character in the string @a delim. If a non-number | |
427 | * part is seen, it is assumed to be the name of a file containing | |
428 | * run numbers. | |
1d86b7ca | 429 | * |
e01b1d30 | 430 | * @param runs String of runs |
431 | * @param delim Delimiters | |
1d86b7ca | 432 | */ |
e01b1d30 | 433 | void SetRuns(const TString& runs, const char* delim=":, \t") |
1d86b7ca | 434 | { |
e01b1d30 | 435 | TIter next(runs.Tokenize(delim)); |
436 | TObjString* os = 0; | |
437 | while ((os = static_cast<TObjString*>(next()))) { | |
438 | TString s(os->String()); | |
439 | if (s.IsNull()) continue; | |
440 | if (!s.IsDigit()) ReadRunNumbers(s); | |
441 | else AddRun(s.Atoi()); | |
442 | } | |
1d86b7ca | 443 | } |
1d86b7ca | 444 | /** |
e01b1d30 | 445 | * Whether final merge should be done over all runs (argument true), |
446 | * or for each run individually. | |
1d86b7ca | 447 | * |
e01b1d30 | 448 | * @param perRun If true, do final merge over all runs |
1d86b7ca | 449 | */ |
e01b1d30 | 450 | void SetPerRunMerge(Bool_t perRun) { fPerRunMerge = perRun; } |
451 | /* @} */ | |
1d86b7ca | 452 | //__________________________________________________________________ |
e01b1d30 | 453 | /** |
454 | * @{ | |
455 | * @name Execution | |
456 | */ | |
d23503ee | 457 | /** |
e01b1d30 | 458 | * Initialize the job |
f53fb4f6 | 459 | * |
460 | * @return true on success, false otherwise | |
461 | */ | |
e01b1d30 | 462 | Bool_t Init() |
4bcdcbc1 | 463 | { |
e01b1d30 | 464 | if (fExecMode == kProof) fUsePar = true; |
465 | ||
466 | // Info("Init", "Connecting in mode=%d", mode); | |
467 | if (!Connect()) return false; | |
4bcdcbc1 | 468 | |
f53fb4f6 | 469 | // --- Get current directory and set-up sub-directory ------------ |
4bcdcbc1 | 470 | TString cwd = gSystem->WorkingDirectory(); |
e01b1d30 | 471 | if (!SetupWorkingDirectory()) return false; |
472 | ||
f53fb4f6 | 473 | // --- Load the common libraries --------------------------------- |
e01b1d30 | 474 | if (!LoadCommonLibraries()) return false; |
4bcdcbc1 | 475 | |
476 | // --- Create analysis manager ----------------------------------- | |
477 | AliAnalysisManager *mgr = new AliAnalysisManager(fName,"Analysis Train"); | |
478 | ||
479 | // In test mode, collect system information on every event | |
480 | // if (oper == kTest) mgr->SetNSysInfo(1); | |
e01b1d30 | 481 | if (fVerbose > 0) mgr->SetDebugLevel(fVerbose); |
482 | if (fExecMode == kLocal) mgr->SetUseProgressBar(kTRUE, 100); | |
4bcdcbc1 | 483 | |
484 | // --- ESD input handler ------------------------------------------ | |
e01b1d30 | 485 | AliVEventHandler* inputHandler = CreateInputHandler(fExecType); |
4bcdcbc1 | 486 | if (inputHandler) mgr->SetInputEventHandler(inputHandler); |
487 | ||
488 | // --- Monte-Carlo ------------------------------------------------ | |
e01b1d30 | 489 | AliVEventHandler* mcHandler = CreateMCHandler(fExecType,fMC); |
4bcdcbc1 | 490 | if (mcHandler) mgr->SetMCtruthEventHandler(mcHandler); |
491 | ||
492 | // --- AOD output handler ----------------------------------------- | |
e01b1d30 | 493 | AliVEventHandler* outputHandler = CreateOutputHandler(fExecType); |
4bcdcbc1 | 494 | if (outputHandler) mgr->SetOutputEventHandler(outputHandler); |
495 | ||
496 | // --- Include analysis macro path in search path ---------------- | |
497 | gROOT->SetMacroPath(Form("%s:%s:$ALICE_ROOT/ANALYSIS/macros", | |
498 | cwd.Data(), gROOT->GetMacroPath())); | |
499 | ||
500 | // --- Physics selction - only for ESD --------------------------- | |
e01b1d30 | 501 | if (fExecType == kESD) CreatePhysicsSelection(fMC, mgr); |
4bcdcbc1 | 502 | |
503 | // --- Create centrality task ------------------------------------ | |
e01b1d30 | 504 | CreateCentralitySelection(fMC, mgr); |
4bcdcbc1 | 505 | |
506 | // --- Create tasks ---------------------------------------------- | |
e01b1d30 | 507 | CreateTasks(fExecMode, fUsePar, mgr); |
4bcdcbc1 | 508 | |
509 | // --- Create Grid handler ---------------------------------------- | |
510 | // _must_ be done after all tasks has been added | |
e01b1d30 | 511 | AliAnalysisAlien* gridHandler = CreateGridHandler(); |
4bcdcbc1 | 512 | if (gridHandler) mgr->SetGridHandler(gridHandler); |
6ff251d8 | 513 | |
514 | // --- Set debug level on defined tasks -------------------------- | |
515 | if (fVerbose > 0) { | |
516 | TIter next(mgr->GetTasks()); | |
517 | AliAnalysisTask* sub = 0; | |
518 | while ((sub = static_cast<AliAnalysisTask*>(next()))) { | |
519 | AliAnalysisTaskSE* se = dynamic_cast<AliAnalysisTaskSE*>(sub); | |
520 | if (!se) continue; | |
521 | se->SetDebugLevel(fVerbose); | |
522 | } | |
523 | } | |
4bcdcbc1 | 524 | |
525 | // --- Print setup ----------------------------------------------- | |
526 | Print(); | |
527 | // if (mode == kProof) { | |
528 | // Info("Run", "Exported environment variables to PROOF slaves:"); | |
529 | // TProof::GetEnvVars()->ls(); | |
530 | // Info("Run", "Environment variables for this session:"); | |
531 | // gSystem->Exec("printenv"); | |
532 | // } | |
533 | ||
534 | // --- Initialise the train -------------------------------------- | |
535 | if (!mgr->InitAnalysis()) { | |
536 | gSystem->ChangeDirectory(cwd.Data()); | |
537 | Error("Run","Failed to initialise train"); | |
538 | return false; | |
539 | } | |
540 | ||
541 | // --- Show status ----------------------------------------------- | |
542 | mgr->PrintStatus(); | |
543 | ||
544 | return true; | |
545 | } | |
e01b1d30 | 546 | //------------------------------------------------------------------ |
f53fb4f6 | 547 | /** |
e01b1d30 | 548 | * Run the analysis. |
f53fb4f6 | 549 | * |
e01b1d30 | 550 | * @param nEvents Number of events to analyse |
551 | * @param r Possible runner object | |
552 | * @param asShell Passed to SaveSetup | |
553 | */ | |
554 | virtual void Run(Int_t nEvents, Runner* r=0, Bool_t asShell=false) | |
4bcdcbc1 | 555 | { |
e01b1d30 | 556 | // Info("Exec", "Doing exec with type=%d, mode=%d, oper=%d, events=%d " |
557 | // "mc=%d, usePar=%d", type, mode, oper, nEvents, mc, usePar); | |
558 | ||
559 | TString cwd = gSystem->WorkingDirectory(); | |
560 | ||
0c4ed5fc | 561 | if (!Init()) { |
562 | Error("Run", "Failed to intialize the train"); | |
563 | return; | |
564 | } | |
e01b1d30 | 565 | if (r) SaveSetup(*r, nEvents, asShell); |
566 | if (fExecOper == kInitialize) return; | |
567 | ||
568 | // --- Create the chain ------------------------------------------ | |
569 | TChain* chain = CreateChain(); | |
0c4ed5fc | 570 | if (fExecMode == kLocal) { |
571 | if (!chain) { | |
572 | Error("Run", "No chain defined in local mode!"); | |
573 | return; | |
574 | } | |
575 | if (chain->GetListOfFiles()->GetEntries() < 1) { | |
576 | Error("Run", "Empty chain in local mode!"); | |
577 | return; | |
578 | } | |
e01b1d30 | 579 | } |
580 | ||
581 | // --- Get manager and execute ----------------------------------- | |
582 | AliAnalysisManager *mgr =AliAnalysisManager::GetAnalysisManager(); | |
583 | Long64_t ret = StartAnalysis(mgr, chain, nEvents); | |
584 | ||
585 | // Make sure we go back | |
586 | gSystem->ChangeDirectory(cwd.Data()); | |
587 | ||
588 | // Return. | |
589 | if (ret < 0) Error("Exec", "Analysis failed"); | |
4bcdcbc1 | 590 | } |
e01b1d30 | 591 | //------------------------------------------------------------------ |
592 | /** | |
593 | * Print the setup | |
594 | * | |
595 | */ | |
596 | virtual void Print() const | |
597 | { | |
598 | bool mc=AliAnalysisManager::GetAnalysisManager()->GetMCtruthEventHandler(); | |
599 | std::cout << fName << " train setup\n" | |
600 | << std::boolalpha; | |
601 | PrintField(std::cout, "Escaped name", fEscapedName); | |
602 | PrintField(std::cout, "ROOT version", fRootVersion); | |
603 | PrintField(std::cout, "AliROOT version", fAliRootVersion); | |
604 | PrintField(std::cout, "AliEn API version", fAliEnAPIVersion); | |
605 | PrintField(std::cout, "Name of proof server", fProofServer); | |
606 | PrintField(std::cout, "Input directory", fDataDir); | |
607 | PrintField(std::cout, "Data pattern", fDataPattern); | |
608 | PrintField(std::cout, "Proof data set name", fDataSet); | |
609 | PrintField(std::cout, "XML collection", fXML); | |
610 | PrintField(std::cout, "Storage replication", fNReplica); | |
611 | PrintField(std::cout, "Allow overwrite", fAllowOverwrite); | |
612 | PrintField(std::cout, "Do GDB debugging", fUseGDB); | |
613 | PrintField(std::cout, "Max # files per split", fMaxSplit); | |
614 | PrintField(std::cout, "Monte-Carlo input", fMC); | |
615 | PrintField(std::cout, "Monte-Carlo handler", mc); | |
616 | PrintField(std::cout, "Per run merge", fPerRunMerge); | |
617 | PrintFieldName(std::cout, "Run numbers"); | |
618 | for (Int_t i = 0; i < fRunNumbers.GetSize(); i++) | |
619 | std::cout << (i == 0 ? "" : ", ") << fRunNumbers.At(i); | |
620 | std::cout << std::endl; | |
621 | ||
622 | PrintFieldList(std::cout, "PAR files", fListOfPARs); | |
623 | PrintFieldList(std::cout, "Script sources", fListOfSources); | |
624 | PrintFieldList(std::cout, "Libraries", fListOfLibraries); | |
625 | PrintFieldList(std::cout, "Extras", fListOfExtras, "\n "); | |
626 | ||
627 | std::cout << std::noboolalpha << std::endl; | |
1d86b7ca | 628 | |
e01b1d30 | 629 | AliAnalysisGrid* plugin = |
630 | AliAnalysisManager::GetAnalysisManager()->GetGridHandler(); | |
631 | if (!plugin) return; | |
632 | ||
633 | } | |
634 | /** | |
635 | * Whether to be verbosity level. 0 means no messages, while higher | |
636 | * numbers increase the verbosity | |
637 | * | |
638 | * @param verb Verbosity level | |
639 | */ | |
640 | void SetVerbose(Int_t verb) { fVerbose = verb; } | |
641 | /* @} */ | |
1d86b7ca | 642 | protected: |
643 | //__________________________________________________________________ | |
e01b1d30 | 644 | /** |
645 | * @{ | |
646 | * @name Copying | |
647 | */ | |
1d86b7ca | 648 | /** |
649 | * Copy constructor | |
650 | * | |
651 | * @param o Object to copy from | |
652 | */ | |
653 | TrainSetup(const TrainSetup& o) | |
2a276c75 | 654 | : fName(o.fName), |
e01b1d30 | 655 | fEscapedName(o.fEscapedName), |
2a276c75 | 656 | fRootVersion(o.fRootVersion), |
657 | fAliRootVersion(o.fAliRootVersion), | |
e01b1d30 | 658 | fAliEnAPIVersion(o.fAliEnAPIVersion), |
2a276c75 | 659 | fProofServer(o.fProofServer), |
660 | fDataDir(o.fDataDir), | |
e01b1d30 | 661 | fDataPattern(o.fDataPattern), |
2a276c75 | 662 | fDataSet(o.fDataSet), |
663 | fXML(o.fXML), | |
664 | fNReplica(o.fNReplica), | |
2a276c75 | 665 | fAllowOverwrite(o.fAllowOverwrite), |
666 | fUseGDB(o.fUseGDB), | |
667 | fMaxSplit(o.fMaxSplit), | |
668 | fRunNumbers(o.fRunNumbers), | |
669 | fListOfPARs(), | |
670 | fListOfSources(), | |
671 | fListOfLibraries(), | |
672 | fListOfExtras(), | |
e01b1d30 | 673 | fDatime(o.fDatime), |
674 | fExecType(o.fExecType), | |
675 | fExecMode(o.fExecMode), | |
676 | fExecOper(o.fExecOper), | |
677 | fUsePar(o.fUsePar), | |
678 | fMC(o.fMC), | |
679 | fPerRunMerge(o.fPerRunMerge), | |
680 | fVerbose(o.fVerbose) | |
1d86b7ca | 681 | { |
682 | if (isdigit(fName[0])) { | |
683 | Warning("TrainSetup", "Name starts with a digit, prepending 'a' to name"); | |
684 | fName = Form("a%s", fName.Data()); | |
685 | } | |
686 | TObject* obj = 0; | |
687 | TIter nextPar(&o.fListOfPARs); | |
688 | while ((obj = nextPar())) fListOfPARs.Add(obj->Clone()); | |
689 | TIter nextSrc(&o.fListOfSources); | |
690 | while ((obj = nextSrc())) fListOfSources.Add(obj->Clone()); | |
691 | TIter nextLib(&o.fListOfLibraries); | |
692 | while ((obj = nextLib())) fListOfLibraries.Add(obj->Clone()); | |
693 | TIter nextExa(&o.fListOfExtras); | |
694 | while ((obj = nextExa())) fListOfExtras.Add(obj->Clone()); | |
695 | } | |
e01b1d30 | 696 | //------------------------------------------------------------------ |
1d86b7ca | 697 | /** |
698 | * Assignment operator | |
699 | * | |
700 | * @param o Object to assign from | |
701 | * | |
702 | * @return Reference to this object. | |
703 | */ | |
704 | TrainSetup& operator=(const TrainSetup& o) | |
705 | { | |
706 | fName = o.fName; | |
707 | fRootVersion = o.fRootVersion; | |
708 | fAliRootVersion = o.fAliRootVersion; | |
709 | fProofServer = o.fProofServer; | |
710 | fDataDir = o.fDataDir; | |
e01b1d30 | 711 | fDataPattern = o.fDataPattern; |
1d86b7ca | 712 | fDataSet = o.fDataSet; |
713 | fXML = o.fXML; | |
714 | fNReplica = o.fNReplica; | |
1d86b7ca | 715 | fRunNumbers = o.fRunNumbers; |
716 | TObject* obj = 0; | |
717 | TIter nextPar(&o.fListOfPARs); | |
718 | while ((obj = nextPar())) fListOfPARs.Add(obj->Clone()); | |
719 | TIter nextSrc(&o.fListOfSources); | |
720 | while ((obj = nextSrc())) fListOfSources.Add(obj->Clone()); | |
721 | TIter nextLib(&o.fListOfLibraries); | |
722 | while ((obj = nextLib())) fListOfLibraries.Add(obj->Clone()); | |
723 | TIter nextExa(&o.fListOfExtras); | |
724 | while ((obj = nextExa())) fListOfExtras.Add(obj->Clone()); | |
725 | ||
726 | return *this; | |
727 | } | |
e01b1d30 | 728 | /* @} */ |
1d86b7ca | 729 | |
730 | //__________________________________________________________________ | |
731 | /** | |
e01b1d30 | 732 | * @{ |
733 | * @name Utility functions | |
734 | */ | |
735 | /** | |
736 | * Escape bad elements of the name | |
737 | * | |
738 | * @param name Name to escape | |
739 | * @param datime Date and Time | |
740 | * | |
741 | * @return escaped name | |
742 | */ | |
743 | static TString EscapeName(const char* name, const TDatime& datime) | |
1d86b7ca | 744 | { |
e01b1d30 | 745 | TString escaped = name; |
746 | char c[] = { ' ', '/', '@', 0 }; | |
747 | char* p = c; | |
748 | while (*p) { | |
749 | escaped.ReplaceAll(Form("%c", *p), "_"); | |
750 | p++; | |
751 | } | |
752 | if (datime.GetYear() <= 1995 || | |
753 | datime.GetMonth() == 0 || | |
754 | datime.GetDay() == 0) return escaped; | |
755 | escaped.Append(Form("_%04d%02d%02d_%02d%02d", | |
756 | datime.GetYear(), | |
757 | datime.GetMonth(), | |
758 | datime.GetDay(), | |
759 | datime.GetHour(), | |
760 | datime.GetMinute())); | |
761 | return escaped; | |
762 | } | |
763 | //------------------------------------------------------------------ | |
764 | static void PrintFieldName(std::ostream& o, const char* name) | |
765 | { | |
766 | o << " " << std::left << std::setw(25) << name << ": " << std::flush; | |
1d86b7ca | 767 | } |
e01b1d30 | 768 | //------------------------------------------------------------------ |
769 | static void PrintFieldList(std::ostream& o, const char* name, | |
770 | const TCollection& c, const char* sep=", ") | |
771 | { | |
772 | PrintFieldName(o, name); | |
773 | Bool_t first = true; | |
774 | TObject* obj = 0; | |
775 | TIter next(&c); | |
776 | while ((obj = next())) { | |
777 | o << (first ? "" : sep) << obj->GetName(); | |
778 | first = false; | |
779 | } | |
780 | std::cout << std::endl; | |
781 | } | |
782 | //------------------------------------------------------------------ | |
783 | template <typename T> | |
784 | static void PrintField(std::ostream& o, const char* name, T& value) | |
785 | { | |
786 | PrintFieldName(o, name); | |
787 | o << value << std::endl; | |
788 | } | |
789 | //------------------------------------------------------------------ | |
1d86b7ca | 790 | /** |
e01b1d30 | 791 | * Return a string that reflects the passed operation |
792 | * | |
793 | * @param eOper Operation | |
794 | * | |
795 | * @return String representation of operation | |
796 | */ | |
797 | static const char* OperString(EOper eOper) | |
1d86b7ca | 798 | { |
e01b1d30 | 799 | switch (eOper) { |
800 | case kTest: return "TEST"; | |
801 | case kOffline: return "OFFLINE"; | |
802 | case kSubmit: return "SUBMIT"; | |
803 | case kTerminate: return "TERMINATE"; | |
804 | case kFull: return "FULL"; | |
805 | case kInitialize: return "INIT"; | |
1d86b7ca | 806 | } |
e01b1d30 | 807 | return 0; |
1d86b7ca | 808 | } |
e01b1d30 | 809 | //------------------------------------------------------------------ |
1d86b7ca | 810 | /** |
e01b1d30 | 811 | * Parse an operation string |
1d86b7ca | 812 | * |
e01b1d30 | 813 | * @param oper Operation |
814 | * | |
815 | * @return An EOper value | |
1d86b7ca | 816 | */ |
e01b1d30 | 817 | static EOper ParseOperation(const char* oper) |
1d86b7ca | 818 | { |
e01b1d30 | 819 | TString sOper(oper); |
820 | sOper.ToUpper(); | |
821 | EOper eOper = kFull; | |
822 | if (sOper.Contains("TEST")) eOper = kTest; | |
823 | else if (sOper.Contains("OFFLINE")) eOper = kOffline; | |
824 | else if (sOper.Contains("SUBMIT")) eOper = kSubmit; | |
825 | else if (sOper.Contains("TERMINATE")) eOper = kTerminate; | |
826 | else if (sOper.Contains("FULL")) eOper = kFull; | |
827 | else if (sOper.Contains("INIT")) eOper = kInitialize; | |
828 | else | |
829 | Fatal("Run", "unknown operation '%s'", oper); | |
830 | return eOper; | |
831 | } | |
832 | //------------------------------------------------------------------ | |
833 | /** | |
834 | * Return a string that reflects the passed mode | |
835 | * | |
836 | * @param eType Type of analysis | |
837 | * | |
838 | * @return String representation of execution type | |
839 | */ | |
840 | static const char* TypeString(EType eType) | |
841 | { | |
842 | switch (eType) { | |
843 | case kESD: return "ESD"; | |
844 | case kAOD: return "AOD"; | |
845 | case kUser: return "USER"; | |
1d86b7ca | 846 | } |
e01b1d30 | 847 | return 0; |
1d86b7ca | 848 | } |
e01b1d30 | 849 | //------------------------------------------------------------------ |
1d86b7ca | 850 | /** |
e01b1d30 | 851 | * Parse a string into a type enum |
1d86b7ca | 852 | * |
e01b1d30 | 853 | * @param type String to pass |
854 | * | |
855 | * @return Enumaration value | |
1d86b7ca | 856 | */ |
e01b1d30 | 857 | static EType ParseType(const char* type) |
1d86b7ca | 858 | { |
e01b1d30 | 859 | // mc = false; |
860 | TString sType(type); | |
861 | sType.ToUpper(); | |
862 | EType eType = kESD; | |
863 | // if (sType.Contains("MC")) mc = true; | |
864 | if (sType.Contains("ESD")) eType = kESD; | |
865 | else if (sType.Contains("AOD")) eType = kAOD; | |
866 | else | |
867 | Fatal("Run", "Unknown type '%s'", type); | |
868 | ||
869 | return eType; | |
870 | } | |
871 | //------------------------------------------------------------------ | |
872 | /** | |
873 | * Return a string that reflects the passed mode | |
874 | * | |
875 | * @param eMode Mode | |
876 | * | |
877 | * @return String representation of mode | |
878 | */ | |
879 | static const char* ModeString(EMode eMode) | |
880 | { | |
881 | switch (eMode) { | |
882 | case kLocal: return "LOCAL"; | |
883 | case kProof: return "PROOF"; | |
884 | case kGrid: return "GRID"; | |
885 | } | |
886 | return 0; | |
887 | } | |
888 | //------------------------------------------------------------------ | |
889 | /** | |
890 | * Parse a string for mode specifier | |
891 | * | |
892 | * @param mode Mode string | |
893 | * | |
894 | * @return EMode value | |
895 | */ | |
896 | static EMode ParseMode(const char* mode) | |
897 | { | |
898 | TString sMode(mode); | |
899 | sMode.ToUpper(); | |
900 | EMode eMode = kLocal; | |
901 | if (sMode.Contains("LOCAL")) eMode = kLocal; | |
902 | else if (sMode.Contains("PROOF")) eMode = kProof; | |
903 | else if (sMode.Contains("GRID")) eMode = kGrid; | |
904 | else | |
905 | Fatal("Run", "Unknown mode '%s'", mode); | |
906 | return eMode; | |
1d86b7ca | 907 | } |
e01b1d30 | 908 | /* @} */ |
909 | ||
910 | ||
1d86b7ca | 911 | //__________________________________________________________________ |
e01b1d30 | 912 | /** |
913 | * @{ | |
914 | * @name Overloadable creators | |
915 | */ | |
1d86b7ca | 916 | /** |
917 | * Create a grid handler | |
918 | * | |
1d86b7ca | 919 | * @return Grid handler |
920 | */ | |
921 | virtual AliAnalysisAlien* | |
e01b1d30 | 922 | CreateGridHandler() |
1d86b7ca | 923 | { |
e01b1d30 | 924 | if (fExecMode != kGrid) return 0; |
1d86b7ca | 925 | |
926 | TString name = EscapedName(); | |
927 | ||
928 | // Create the plug-in object, and set run mode | |
929 | AliAnalysisAlien* plugin = new AliAnalysisAlien(); | |
e01b1d30 | 930 | plugin->SetRunMode(OperString(fExecOper == kInitialize ? |
931 | kFull : fExecOper)); | |
1d86b7ca | 932 | |
933 | // Production mode - not used here | |
934 | // plugin->SetProductionMode(); | |
935 | ||
a76fb27d | 936 | // Do not test copying |
937 | plugin->SetCheckCopy(false); | |
938 | ||
1d86b7ca | 939 | // Set output to be per run |
e01b1d30 | 940 | plugin->SetOutputToRunNo(true); |
1d86b7ca | 941 | |
942 | // Set the job tag | |
943 | plugin->SetJobTag(fName); | |
944 | ||
945 | // Set number of test files - used in test mode only | |
946 | plugin->SetNtestFiles(1); | |
e01b1d30 | 947 | |
948 | // Set name of generated analysis macro | |
949 | plugin->SetAnalysisMacro(Form("%s.C", name.Data())); | |
1d86b7ca | 950 | |
e01b1d30 | 951 | // Maximum number of sub-jobs |
952 | // plugin->SetSplitMaxInputFileNumber(25); | |
953 | ||
954 | // Set the Time-To-Live | |
955 | plugin->SetTTL(70000); | |
956 | ||
957 | // Re-submit failed jobs as long as the ratio of failed jobs is | |
958 | // below this percentage. | |
959 | plugin->SetMasterResubmitThreshold(95); | |
1d86b7ca | 960 | |
e01b1d30 | 961 | // Set the input format |
962 | plugin->SetInputFormat("xml-single"); | |
963 | ||
964 | // Set the name of the generated jdl | |
965 | plugin->SetJDLName(Form("%s.jdl", name.Data())); | |
966 | ||
967 | // Set the name of the generated executable | |
968 | plugin->SetExecutable(Form("%s.sh", name.Data())); | |
969 | ||
970 | // Set the job price !? | |
971 | plugin->SetPrice(1); | |
972 | ||
973 | // Set whether to merge via JDL | |
974 | plugin->SetMergeViaJDL(true); | |
975 | ||
976 | // Fast read otion | |
977 | plugin->SetFastReadOption(false); | |
978 | ||
979 | // Whether to overwrite existing output | |
980 | plugin->SetOverwriteMode(true); | |
981 | ||
982 | // Set the executable binary name and options | |
983 | plugin->SetExecutableCommand("aliroot -b -q -x"); | |
984 | ||
985 | // Split by storage element - must be lower case! | |
986 | plugin->SetSplitMode("se"); | |
987 | plugin->SetSplitMaxInputFileNumber(fMaxSplit); | |
988 | ||
989 | // Disable default outputs | |
990 | plugin->SetDefaultOutputs(true); | |
991 | ||
992 | // Merge parameters | |
993 | plugin->SetMaxMergeFiles(20); | |
994 | plugin->SetMergeExcludes("AliAOD.root " | |
995 | "*EventStat*.root " | |
996 | "*event_stat*.root"); | |
997 | ||
998 | // Keep log files | |
999 | plugin->SetKeepLogs(); | |
1000 | ||
1001 | // Set the working directory to be the trains name (with special | |
1002 | // characters replaced by '_' and the date appended), and also set | |
1003 | // the output directory (relative to working directory) | |
1004 | plugin->SetGridWorkingDir(name.Data()); | |
1005 | plugin->SetGridOutputDir("output"); | |
1006 | ||
1007 | // Set required version of software | |
1008 | if (!fAliEnAPIVersion.IsNull()) plugin->SetAPIVersion(fAliEnAPIVersion); | |
1009 | if (!fRootVersion.IsNull()) plugin->SetROOTVersion(fRootVersion); | |
1010 | if (!fAliRootVersion.IsNull()) plugin->SetAliROOTVersion(fAliRootVersion); | |
1d86b7ca | 1011 | |
1012 | // Declare root of input data directory | |
f53fb4f6 | 1013 | TString dataDir(fDataDir); |
1014 | if (dataDir.BeginsWith("alien://")) | |
1015 | dataDir.ReplaceAll("alien://", ""); | |
1016 | plugin->SetGridDataDir(dataDir); | |
1d86b7ca | 1017 | |
1018 | // Data search patterns | |
1019 | TString pat; | |
e01b1d30 | 1020 | if (AliAnalysisManager::GetAnalysisManager()->GetMCtruthEventHandler()) |
1021 | plugin->SetRunPrefix(""); | |
1d86b7ca | 1022 | else { |
1d86b7ca | 1023 | plugin->SetRunPrefix("000"); |
1024 | } | |
e01b1d30 | 1025 | pat = fDataPattern; |
1026 | if (!pat.EndsWith("/")) pat.Append("/"); | |
1027 | pat.Append(Form("*%s.root", fExecType == kESD ? "ESDs" : "AOD")); | |
1d86b7ca | 1028 | plugin->SetDataPattern(pat); |
1029 | ||
1030 | // Add the run numbers | |
e01b1d30 | 1031 | Int_t nRun = 0; |
1d86b7ca | 1032 | for (Int_t i = 0; i < fRunNumbers.fN; i++) { |
1033 | if (fRunNumbers[i] < 0) continue; | |
1034 | plugin->AddRunNumber(fRunNumbers[i]); | |
e01b1d30 | 1035 | nRun++; |
1d86b7ca | 1036 | } |
e01b1d30 | 1037 | // Set number of runs per master - set to one to per run |
1038 | if (fPerRunMerge) plugin->SetNrunsPerMaster(1); | |
1039 | else plugin->SetNrunsPerMaster(nRun+1); | |
1d86b7ca | 1040 | |
1d86b7ca | 1041 | // Enable configured PARs |
1042 | TIter nextPar(&fListOfPARs); | |
1043 | TObject* parName; | |
1044 | while ((parName = nextPar())) | |
1045 | plugin->EnablePackage(parName->GetName()); | |
1046 | ||
1047 | // Add sources that need to be compiled on the workers using | |
1048 | // AcLIC. | |
1049 | TString addSources = SetupSources(); | |
1050 | if (!addSources.IsNull()) plugin->SetAnalysisSource(addSources.Data()); | |
1051 | ||
1052 | // Add binary libraries that should be uploaded to the workers | |
1053 | TString addLibs = SetupLibraries(); | |
1054 | if (!addLibs.IsNull()) plugin->SetAdditionalLibs(addLibs.Data()); | |
1055 | ||
1d86b7ca | 1056 | // Loop over defined containers in the analysis manager, |
1057 | // and declare these as outputs | |
1058 | TString listOfAODs = ""; | |
1059 | TString listOfHists = ""; | |
1060 | AliAnalysisManager* mgr = AliAnalysisManager::GetAnalysisManager(); | |
1061 | AliAnalysisDataContainer* cont = 0; | |
1062 | TIter nextCont(mgr->GetOutputs()); | |
1063 | while ((cont = static_cast<AliAnalysisDataContainer*>(nextCont()))) { | |
1064 | TString outName(cont->GetFileName()); | |
1065 | TString& list = (outName == "default" ? listOfAODs : listOfHists); | |
1066 | if (outName == "default") { | |
1067 | if (!mgr->GetOutputEventHandler()) continue; | |
1068 | ||
1069 | outName = mgr->GetOutputEventHandler()->GetOutputFileName(); | |
1070 | } | |
1071 | if (list.Contains(outName)) continue; | |
1072 | if (!list.IsNull()) list.Append(","); | |
1073 | list.Append(outName); | |
1074 | } | |
1075 | if (!mgr->GetExtraFiles().IsNull()) { | |
1076 | if (!listOfAODs.IsNull()) listOfAODs.Append("+"); | |
1077 | TString extra = mgr->GetExtraFiles(); | |
1078 | extra.ReplaceAll(" ", ","); | |
1079 | listOfAODs.Append(extra); | |
1080 | } | |
1081 | TString outArchive = Form("stderr, stdout@disk=%d", fNReplica); | |
1082 | if (!listOfHists.IsNull()) | |
1083 | outArchive.Append(Form(" hist_archive.zip:%s@disk=%d", | |
1084 | listOfHists.Data(), fNReplica)); | |
1085 | if (!listOfAODs.IsNull()) | |
1086 | outArchive.Append(Form(" aod_archive.zip:%s@disk=%d", | |
1087 | listOfAODs.Data(), fNReplica)); | |
1088 | if (listOfAODs.IsNull() && listOfHists.IsNull()) | |
1089 | Fatal("CreateGridHandler", "No outputs defined"); | |
1090 | // Disabled for now | |
1091 | // plugin->SetOutputArchive(outArchive); | |
1092 | ||
1d86b7ca | 1093 | |
1094 | return plugin; | |
1095 | } | |
e01b1d30 | 1096 | //------------------------------------------------------------------ |
1d86b7ca | 1097 | /** |
1098 | * Create input handler | |
1099 | * | |
1100 | * @param type | |
1101 | * | |
1102 | * @return | |
1103 | */ | |
1104 | virtual AliVEventHandler* CreateInputHandler(EType type) | |
1105 | { | |
1106 | switch (type) { | |
1107 | case kESD: return new AliESDInputHandler(); | |
1108 | case kAOD: return new AliAODInputHandler(); | |
e01b1d30 | 1109 | case kUser: return 0; |
1d86b7ca | 1110 | } |
1111 | return 0; | |
1112 | } | |
e01b1d30 | 1113 | //------------------------------------------------------------------ |
1d86b7ca | 1114 | /** |
1115 | * Create input handler | |
1116 | * | |
1117 | * @param type Run type (ESD or AOD) | |
1118 | * @param mc Assume monte-carlo input | |
1119 | * | |
1120 | * @return | |
1121 | */ | |
e01b1d30 | 1122 | virtual AliVEventHandler* CreateMCHandler(EType /*type*/, bool mc) |
1d86b7ca | 1123 | { |
1124 | if (!mc) return 0; | |
e01b1d30 | 1125 | // if (type != kESD) return 0; |
1d86b7ca | 1126 | Info("CreateMCHandler", "Making MC handler"); |
1127 | AliMCEventHandler* mcHandler = new AliMCEventHandler(); | |
1128 | mcHandler->SetReadTR(true); | |
1129 | return mcHandler; | |
1130 | } | |
e01b1d30 | 1131 | //------------------------------------------------------------------ |
1d86b7ca | 1132 | /** |
1133 | * Create output event handler | |
1134 | * | |
1135 | * @param type | |
1136 | * | |
1137 | * @return | |
1138 | */ | |
1139 | virtual AliVEventHandler* CreateOutputHandler(EType type) | |
1140 | { | |
1141 | AliAODHandler* ret = new AliAODHandler(); | |
1142 | switch (type) { | |
1143 | case kESD: | |
1144 | ret->SetOutputFileName("AliAOD.root"); | |
1145 | break; | |
1146 | case kAOD: | |
1147 | ret->SetOutputFileName("AliAOD.pass2.root"); | |
1148 | break; | |
e01b1d30 | 1149 | case kUser: |
1150 | break; | |
1d86b7ca | 1151 | } |
e01b1d30 | 1152 | |
1d86b7ca | 1153 | return ret; |
1154 | } | |
e01b1d30 | 1155 | //------------------------------------------------------------------ |
1d86b7ca | 1156 | /** |
e01b1d30 | 1157 | * Create physics selection, and add to manager |
1d86b7ca | 1158 | * |
1159 | * @param mc Whether this is for MC | |
1160 | * @param mgr Manager | |
1161 | */ | |
1162 | virtual void CreatePhysicsSelection(Bool_t mc, | |
1163 | AliAnalysisManager* mgr) | |
1164 | { | |
1165 | gROOT->Macro(Form("AddTaskPhysicsSelection.C(%d)", mc)); | |
1166 | mgr->RegisterExtraFile("event_stat.root"); | |
1167 | } | |
e01b1d30 | 1168 | //------------------------------------------------------------------ |
1d86b7ca | 1169 | /** |
e01b1d30 | 1170 | * Create centrality selection, and add to manager |
1d86b7ca | 1171 | * |
1172 | * @param mc Whether this is for MC | |
1173 | * @param mgr Manager | |
1174 | */ | |
1175 | virtual void CreateCentralitySelection(Bool_t mc, AliAnalysisManager* mgr) | |
1176 | { | |
1177 | gROOT->Macro("AddTaskCentrality.C"); | |
2a276c75 | 1178 | const char* name = "CentralitySelection"; |
1d86b7ca | 1179 | AliCentralitySelectionTask* ctask = |
2a276c75 | 1180 | dynamic_cast<AliCentralitySelectionTask*>(mgr->GetTask(name)); |
1d86b7ca | 1181 | if (!ctask) return; |
1d86b7ca | 1182 | if (mc) ctask->SetMCInput(); |
1183 | } | |
e01b1d30 | 1184 | //------------------------------------------------------------------ |
1d86b7ca | 1185 | /** |
e01b1d30 | 1186 | * Create analysis tasks. Must be overloaded by sub-class |
1d86b7ca | 1187 | * |
1188 | * @param mode Run mode | |
1189 | * @param mgr Manager | |
1190 | * @param par Whether to use pars | |
1191 | */ | |
1192 | virtual void CreateTasks(EMode mode, Bool_t par, AliAnalysisManager* mgr)=0; | |
e01b1d30 | 1193 | /* @} */ |
1194 | ||
1d86b7ca | 1195 | //__________________________________________________________________ |
e01b1d30 | 1196 | /** |
1197 | * @{ | |
1198 | * @name Library loading | |
1199 | */ | |
1200 | //------------------------------------------------------------------ | |
1201 | /** | |
1202 | * Load common libraries | |
1203 | * | |
1204 | * @return true on success | |
1205 | */ | |
1206 | Bool_t LoadCommonLibraries() | |
1207 | { | |
1208 | if (!gSystem->Getenv("ALICE_ROOT")) { | |
1209 | Error("LoadCommonLibraries", "Local AliROOT not available"); | |
1210 | return false; | |
1211 | } | |
1212 | gSystem->Load("libTree.so"); | |
1213 | gSystem->Load("libGeom.so"); | |
1214 | gSystem->Load("libVMC.so"); | |
1215 | gSystem->Load("libPhysics.so"); | |
1216 | gSystem->Load("libMinuit.so"); | |
1217 | if (fExecMode == kProof) { | |
1218 | gProof->Exec("gSystem->Load(\"libTree.so\");"); | |
1219 | gProof->Exec("gSystem->Load(\"libGeom.so\");"); | |
1220 | gProof->Exec("gSystem->Load(\"libMinuit.so\");"); | |
1221 | gProof->Exec("gSystem->Load(\"libVMC.so\");"); | |
1222 | ||
1223 | ||
1224 | } | |
1225 | ||
1226 | Bool_t ret = true; | |
1227 | Bool_t basic = fExecMode == kGrid ? false : fUsePar; | |
1228 | ||
1229 | ret &= LoadLibrary("STEERBase", basic, false); | |
1230 | ret &= LoadLibrary("ESD", basic, false); | |
1231 | ret &= LoadLibrary("AOD", basic, false); | |
1232 | ret &= LoadLibrary("ANALYSIS", basic, true); | |
1233 | ret &= LoadLibrary("OADB", basic, true); | |
1234 | ret &= LoadLibrary("ANALYSISalice", basic, true); | |
1235 | ||
1236 | return ret; | |
1237 | } | |
1238 | //------------------------------------------------------------------ | |
1239 | /** | |
1240 | * Load a library | |
1241 | * | |
1242 | * @param what What library to load | |
1243 | * @param par If true, load as PAR | |
1244 | * @param rec If true, also load on slaves | |
1245 | * | |
1246 | * @return true on success | |
1247 | */ | |
1248 | Bool_t LoadLibrary(const char* what, Bool_t par, Bool_t rec=false) | |
1249 | { | |
1250 | if (!what || what[0] == '\0') return true; | |
1251 | ||
1252 | TString module(what); | |
1253 | TString libName(what); | |
1254 | if (!libName.BeginsWith("lib")) { | |
1255 | // Check if the library corresponds to a compiled macro | |
1256 | if (!gSystem->AccessPathName(Form("%s_C.so", libName.Data()))) { | |
1257 | libName.Append("_C"); | |
1258 | } | |
1259 | else if (!gSystem->AccessPathName(Form("../%s_C.so", libName.Data()))) { | |
1260 | libName = Form("../%s_C", what); | |
1261 | } | |
1262 | else | |
1263 | libName = Form("lib%s", libName.Data()); | |
1264 | } | |
1265 | if (!libName.EndsWith(".so")) libName.Append(".so"); | |
1266 | ||
1267 | Int_t ret = 0; | |
1268 | ||
1269 | switch (fExecMode) { | |
1270 | case kLocal: // Just load and exit | |
1271 | if (gSystem->Load(libName.Data()) < 0) { | |
1272 | Error("LoadLibrary", "Failed to load library %s", libName.Data()); | |
1273 | return false; | |
1274 | } | |
1275 | break; | |
1276 | case kGrid: | |
1277 | if (par) { | |
1278 | ret = SetupPAR(what) ? 0 : -1; | |
1279 | if (rec) fListOfPARs.Add(new TObjString(what)); | |
1280 | } else { | |
1281 | ret = gSystem->Load(libName.Data()); | |
1282 | if (rec) fListOfLibraries.Add(new TObjString(libName)); | |
1283 | } | |
1284 | break; | |
1285 | case kProof: | |
1286 | Info("LoadLibrary", "Uploading %s", what); | |
1287 | ret = gProof->UploadPackage(what, TProof::kRemoveOld); | |
1288 | if (ret < 0) { | |
1289 | ret = gProof->UploadPackage(gSystem->ExpandPathName(Form("../%s.par", | |
1290 | what))); | |
1291 | if (ret < 0) { | |
1292 | ret = | |
1293 | gProof->UploadPackage(gSystem | |
1294 | ->ExpandPathName(Form("$ALICE_ROOT/%s.par", | |
1295 | what))); | |
1296 | if (ret < 0) { | |
1297 | Error("LoadLibrary", | |
1298 | "Could not find module %s.par in current directory nor " | |
1299 | "in $ALICE_ROOT", module.Data()); | |
1300 | return false; | |
1301 | } | |
1302 | } | |
1303 | } | |
1304 | Info("LoadLibrary", "Enabling package %s", what); | |
1305 | ret = gProof->EnablePackage(what); | |
1306 | break; | |
1307 | } | |
1308 | if (ret < 0) { | |
1309 | Error("LoadLibrary", "Couldn't load %s", what); | |
1310 | return false; | |
1311 | } | |
1312 | return true; | |
1313 | } | |
1314 | /* @} */ | |
1315 | ||
1316 | //__________________________________________________________________ | |
1317 | /** | |
1318 | * @{ | |
1319 | * @name PAR generation from script | |
1320 | */ | |
1321 | /** | |
1322 | * Service function to make a PAR out of a script. | |
1323 | * | |
1324 | * The script should contain can contain a sub-class of AliAnalysisTask. | |
1325 | * The script will be compiled on the slaves before loading the | |
1326 | * AliAnalysisManager. Parts to (not) be compiled can be protected like | |
1327 | * | |
1328 | * @code | |
1329 | * #ifdef BUILD_PAR | |
1330 | * // This will _only_ be compiled in the servers | |
1331 | * #endif | |
1332 | * #ifndef BUILD_PAR | |
1333 | * // This will not be compiled in the servers | |
1334 | * #endif | |
1335 | * @endcode | |
1336 | * | |
1337 | * @param mode Execution mode (Grid, PROOF, Local) | |
1338 | * @param script Script to upload and compile in the PAR | |
1339 | * @param deps Dependency pars | |
1340 | * | |
1341 | * @return true on success. | |
1342 | */ | |
1343 | static Bool_t MakeScriptPAR(EMode mode, const char* script, const char* deps) | |
1344 | { | |
1345 | // Get the base name | |
1346 | Info("MakeScriptPAR", "Making par file for %s", script); | |
1347 | TString base(gSystem->BaseName(script)); | |
1348 | Int_t idx = base.Last('.'); | |
1349 | if (idx != kNPOS) base.Remove(idx); | |
1350 | Bool_t retval = true; | |
1351 | // Info("MakeScriptPAR", "script=%s, base=%s", script, base.Data()); | |
1352 | ||
1353 | if (mode == kLocal) { | |
1354 | if (gROOT->LoadMacro(Form("%s.C++g", base.Data())) < 0) | |
1355 | return false; | |
1356 | return true; | |
1357 | } | |
1358 | ||
1359 | TString tmpdir(gSystem->TempDirectory()); | |
1360 | int ltempl = tmpdir.Length() + 1 + 5 + 6 + 1; | |
1361 | char* templ = new char[ltempl]; | |
1362 | snprintf(templ, ltempl, "%s/trainXXXXXX", tmpdir.Data()); | |
1363 | if (!mkdtemp(templ)) { | |
1364 | Error("MakeScriptPAR", | |
1365 | "Failed to generate temporary directory from template %s", | |
1366 | templ); | |
1367 | return false; | |
1368 | } | |
1369 | ||
1370 | try { | |
1371 | // Check name of script file | |
1372 | TString scr(script); | |
1373 | TString ext; | |
1374 | if (scr.EndsWith(".C")) ext = "C"; | |
1375 | else if (scr.EndsWith(".cxx")) ext = "cxx"; | |
1376 | else { ext = "C"; scr.Append(".C"); } | |
1377 | ||
1378 | // Check if we can access the file | |
1379 | TString path = TString::Format(".:%s", TROOT::GetMacroPath()); | |
1380 | char* loc = gSystem->Which(path, scr); | |
1381 | if (!loc) throw TString::Format("Script %s not found in %s", | |
1382 | scr.Data(), path.Data()); | |
1383 | TString full(loc); | |
1384 | ||
1385 | TString dir = TString::Format("%s/%s", templ, base.Data()); | |
1386 | // Set-up directories | |
1387 | if (gSystem->MakeDirectory(dir) < 0) | |
1388 | throw TString::Format("Could not make directory '%s'", base.Data()); | |
1389 | ||
1390 | if (gSystem->MakeDirectory(Form("%s/PROOF-INF", dir.Data()))) | |
1391 | throw TString::Format("Could not make directory %s/PROOF-INF", | |
1392 | base.Data()); | |
1393 | ||
1394 | // Copy the script to the setup directory | |
1395 | TString dest = TString::Format("%s/%s.%s", dir.Data(), | |
1396 | base.Data(), ext.Data()); | |
1397 | Int_t ret = gSystem->CopyFile(full, dest, true); | |
1398 | switch (ret) { | |
1399 | case -1: throw TString::Format("Couldn't open %s for copy", scr.Data()); | |
1400 | case -2: throw TString::Format("File %s exists", dest.Data()); | |
1401 | case -3: throw TString::Format("Error while copying %s", scr.Data()); | |
1402 | } | |
1403 | ||
1404 | // Make our build file | |
1405 | // Info("MakeScriptPAR", "Making build script %s/PROOF-INF/BUILD.sh", dir.Data()); | |
1406 | std::ofstream b(Form("%s/PROOF-INF/BUILD.sh", dir.Data())); | |
1407 | if (!b) | |
1408 | throw TString::Format("Failed to open b shell script"); | |
1409 | b << "#!/bin/sh\n" | |
1410 | << "echo BUILD.sh@`hostname`: Building " << base << "\n" | |
1411 | << "root.exe -l -b -q PROOF-INF/BUILD.C 2>&1 | tee " << base << ".log\n" | |
1412 | << "echo BUILD.sh@`hostname`: done: $?\n" | |
1413 | << std::endl; | |
1414 | b.close(); | |
1415 | if (gSystem->Chmod(Form("%s/PROOF-INF/BUILD.sh", dir.Data()), 0755) != 0) | |
1416 | throw TString::Format("Failed to set exectuable flags on " | |
1417 | "%s/PROOF-INF/BUILD.sh", dir.Data()); | |
1418 | ||
1419 | // Info("MakeScriptPAR", "Making utility script %s/PROOF-INF/UTIL.C", dir.Data()); | |
1420 | std::ofstream u(Form("%s/PROOF-INF/UTIL.C", dir.Data())); | |
1421 | if (!u) | |
1422 | throw TString::Format("Failed to open utility script"); | |
1423 | u << "void LoadROOTLibs() {\n" | |
1424 | << " gSystem->Load(\"libVMC\");\n" | |
1425 | << " gSystem->Load(\"libNet\");\n" | |
1426 | << " gSystem->Load(\"libTree\");\n" | |
1427 | << " gSystem->Load(\"libPhysics\");\n" | |
1428 | << " gSystem->Load(\"libMinuit\");\n" | |
1429 | << "}\n\n" | |
1430 | << "void AddAliROOT() {\n" | |
1431 | << " TString val(gSystem->Getenv(\"ALICE_ROOT\"));\n" | |
1432 | << " if (val.IsNull())\n" | |
1433 | << " Warning(\"Add\",\"ALICE_ROOT not defined\");\n" | |
1434 | << " else\n" | |
1435 | << " gSystem->AddIncludePath(Form(\"-I%s/include\",val.Data()));\n" | |
1436 | << "}\n\n" | |
1437 | << "void AddDep(const char* env) {\n" | |
1438 | << " TString val(gSystem->Getenv(Form(\"%s_INCLUDE\",env)));\n" | |
1439 | << " if (val.IsNull())\n" | |
1440 | << " Warning(\"Add\",\"%s_INCLUDE not defined\", env);\n" | |
1441 | << " else {\n" | |
1442 | << " gSystem->AddIncludePath(Form(\"-I../%s\",val.Data()));\n" | |
1443 | << " }\n" | |
1444 | << "}\n\n" | |
1445 | << "void LoadDep(const char* name) {\n" | |
1446 | << " gSystem->AddDynamicPath(Form(\"../%s\",name));\n" | |
1447 | << " char* full = gSystem->DynamicPathName(name,true);\n" | |
1448 | << " if (!full) \n" | |
1449 | << " full = gSystem->DynamicPathName(Form(\"lib%s\",name),true);\n" | |
1450 | << " if (!full) \n" | |
1451 | << " full = gSystem->DynamicPathName(Form(\"lib%s.so\",name),true);\n" | |
1452 | << " if (!full) {\n" | |
1453 | << " Warning(\"LoadDep\",\"Module %s not found\", name);\n" | |
1454 | << " return;\n" | |
1455 | << " }\n" | |
1456 | << " gSystem->Load(full);\n" | |
1457 | << "}\n" | |
1458 | << std::endl; | |
1459 | u.close(); | |
1460 | ||
1461 | // Info("MakeScriptPAR", "Making utility script %s/PROOF-INF/BUILD.C", dir.Data()); | |
1462 | std::ofstream cbuild(Form("%s/PROOF-INF/BUILD.C", dir.Data())); | |
1463 | if (!cbuild) | |
1464 | throw TString::Format("Failed to open build script"); | |
1465 | cbuild << "void BUILD() {\n" | |
1466 | << " gSystem->AddIncludePath(\"-DBUILD_PAR=1\");\n" | |
1467 | << " gROOT->LoadMacro(\"PROOF-INF/UTIL.C\");\n" | |
1468 | << " LoadROOTLibs();\n" | |
1469 | << " AddAliROOT();\n"; | |
1470 | TObjArray* depList = TString(deps).Tokenize(","); | |
1471 | TIter next(depList); | |
1472 | TObject* dep = 0; | |
1473 | while ((dep = next())) { | |
1474 | cbuild << " AddDep(\"" << dep->GetName() << "\");\t" | |
1475 | << " LoadDep(\"" << dep->GetName() << "\");\n"; | |
1476 | } | |
1477 | cbuild << " // gDebug = 5;\n" | |
1478 | << " int ret = gROOT->LoadMacro(\"" | |
1479 | << base << "." << ext << "++g\");\n" | |
1480 | << " if (ret != 0) Fatal(\"BUILD\",\"Failed to build\");\n" | |
1481 | << " // else Info(\"BUILD\", \"Made " << base << "\");\n" | |
1482 | << "}\n" | |
1483 | << std::endl; | |
1484 | cbuild.close(); | |
1485 | ||
1486 | // Make our set-up script | |
1487 | // Info("MakeScriptPAR", "Making setup script %s/PROOF-INF/SETUP.C", dir.Data()); | |
1488 | std::ofstream setup(Form("%s/PROOF-INF/SETUP.C", dir.Data())); | |
1489 | if (!setup) | |
1490 | throw TString::Format("Failed to open setup script"); | |
1491 | setup << "void SETUP() {\n" | |
1492 | << " gROOT->LoadMacro(\"PROOF-INF/UTIL.C\");\n" | |
1493 | << " LoadROOTLibs();\n" | |
1494 | << " // Info(\"SETUP\",\"Loading libraries\");\n"; | |
1495 | next.Reset(); | |
1496 | dep = 0; | |
1497 | while ((dep = next())) | |
1498 | setup << " LoadDep(\"" << dep->GetName() << "\");\n"; | |
1499 | setup << " // gDebug = 5;\n" | |
1500 | << " // Info(\"SETUP\",\"Loading " << base << "_" << ext << ".so\");\n" | |
1501 | << " gSystem->Load(\"" << base << "_" << ext << ".so\");\n" | |
1502 | << " // gDebug = 0;\n" | |
1503 | << " gROOT->ProcessLine(\".include " << base << "\");\n" | |
1504 | << " gSystem->Setenv(\"" << base << "_INCLUDE\",\"" | |
1505 | << base << "\");\n" | |
1506 | << " // Info(\"SETUP\", \"Done\");\n" | |
1507 | << "}\n" | |
1508 | << std::endl; | |
1509 | setup.close(); | |
1510 | ||
1511 | // Info("MakeScriptPAR", "Packing up tar-archive"); | |
1512 | ret = gSystem->Exec(Form("(cd %s && tar -czf %s.par %s)", | |
1513 | templ, base.Data(),base.Data())); | |
1514 | if (ret != 0) | |
1515 | throw TString::Format("Failed to create PAR file %s.PAR from %s", | |
1516 | base.Data(), dir.Data()); | |
1517 | ||
1518 | // Info("MakeScriptPAR", "Moving PAR archive"); | |
1519 | ret = gSystem->Exec(Form("mv -f %s/%s.par %s.par", templ, base.Data(), | |
1520 | base.Data())); | |
1521 | if (ret != 0) | |
1522 | throw TString::Format("Failed to rename %s/%s.par to %s.par: %s", | |
1523 | templ, base.Data(), base.Data(), | |
1524 | gSystem->GetError()); | |
1525 | } | |
1526 | catch (TString& e) { | |
1527 | Error("MakeScriptPAR", "%s", e.Data()); | |
1528 | retval = false; | |
1529 | } | |
1530 | // Info("MakeScriptPAR", "Removing temperary directory %s", templ); | |
1531 | gSystem->Exec(Form("rm -rf %s", templ)); | |
1532 | return retval; | |
1533 | } | |
1534 | /* @} */ | |
1535 | ||
1536 | //__________________________________________________________________ | |
1537 | /** | |
1538 | * @{ | |
1539 | * @name Execution implementation | |
1540 | */ | |
1541 | /** | |
1542 | * Start the analysis | |
1543 | * | |
1544 | * @param mgr Analysis manager | |
1545 | * @param chain Input data (local and proof only) | |
1546 | * @param nEvents Number of events to analyse | |
1547 | */ | |
1548 | Long64_t StartAnalysis(AliAnalysisManager* mgr, | |
1549 | TChain* chain, | |
1550 | Int_t nEvents) | |
1551 | { | |
1552 | // --- Run the analysis ------------------------------------------ | |
1553 | TString mode = ModeString(fExecMode); | |
1554 | switch (fExecMode) { | |
1555 | case kLocal: | |
1556 | if (!chain) { | |
1557 | Error("StartAnalysis", "No chain defined"); | |
1558 | return -1; | |
1559 | } | |
1560 | if (nEvents < 0) nEvents = chain->GetEntries(); | |
1561 | return mgr->StartAnalysis(mode, chain, nEvents); | |
1562 | case kProof: | |
1563 | if (fDataSet.IsNull()) { | |
1564 | if (!chain) { | |
1565 | Error("StartAnalysis", "No chain defined"); | |
1566 | return -1; | |
1567 | } | |
1568 | if (nEvents < 0) nEvents = chain->GetEntries(); | |
1569 | return mgr->StartAnalysis(mode, chain, nEvents); | |
1570 | } | |
1571 | return mgr->StartAnalysis(mode, fDataSet); | |
1572 | case kGrid: | |
1573 | if (nEvents < 0) | |
1574 | return mgr->StartAnalysis(mode); | |
1575 | return mgr->StartAnalysis(mode, nEvents); | |
1576 | } | |
1577 | // We should never get here | |
1578 | return -1; | |
1579 | } | |
1580 | //------------------------------------------------------------------ | |
1d86b7ca | 1581 | /** |
1582 | * Connect to external services (Proof and/or grid) | |
1583 | * | |
1d86b7ca | 1584 | * @return true on success |
1585 | */ | |
e01b1d30 | 1586 | virtual Bool_t Connect() |
1d86b7ca | 1587 | { |
e01b1d30 | 1588 | if (fExecMode == kLocal) return true; |
1d86b7ca | 1589 | |
1590 | // --- Set-up connections to Proof cluster and alien ------------- | |
e01b1d30 | 1591 | if (fExecMode == kProof) { |
d23503ee | 1592 | Info("Connect", "Opening connection to proof server"); |
1d86b7ca | 1593 | // --- Find user name ------------------------------------------ |
1594 | TString userName(gSystem->Getenv("alien_API_USER")); | |
1595 | if (userName.IsNull()) { | |
1596 | userName = gSystem->GetUserInfo()->fUser; | |
1597 | Warning("Connect", | |
1598 | "environment variable 'alien_API_USER' not set, using %s", | |
1599 | userName.Data()); | |
1600 | } | |
1601 | ||
1602 | // --- Set prefered GSI method --------------------------------- | |
1603 | gEnv->SetValue("XSec.GSI.DelegProxy", "2"); | |
36619b75 | 1604 | |
1605 | // --- Figure out some server settings ------------------------- | |
1d86b7ca | 1606 | TString serv = ""; |
1607 | Bool_t lite = false; | |
1608 | if (fProofServer.BeginsWith("workers=") || fProofServer.IsNull()) { | |
1609 | lite = true; | |
1610 | serv = fProofServer; | |
1611 | } | |
1612 | else | |
1613 | serv = Form("%s@%s", userName.Data(), fProofServer.Data()); | |
36619b75 | 1614 | |
1615 | // --- Possibly debug slave sessions with GDB ------------------ | |
1616 | if (fUseGDB) { | |
07ff2416 | 1617 | TString gdbCmd("/usr/bin/gdb --batch -ex run -ex bt --args"); |
1618 | // TString gdbCmd("\"gdb --batch -ex run -ex bt --args\""); | |
36619b75 | 1619 | Info("Connect", "Using GDB to wrap slaves: %s", gdbCmd.Data()); |
1620 | TProof::AddEnvVar("PROOF_WRAPPERCMD", gdbCmd); | |
1621 | } | |
1622 | ||
1623 | // --- Add ALICE_ROOT directory to search path for packages ---- | |
d23503ee | 1624 | Info("Connect", "Set location of packages"); |
36619b75 | 1625 | gEnv->SetValue("Proof.GlobalPackageDirs", |
1626 | Form("%s:%s", | |
1627 | gEnv->GetValue("Proof.GlobalPackageDirs", "."), | |
1628 | gSystem->Getenv("ALICE_ROOT"))); | |
1629 | ||
1630 | // --- Set OADB path on workers -------------------------------- | |
1631 | const char* oadbPath = AliAnalysisManager::GetOADBPath(); | |
1632 | TProof::AddEnvVar("OADB_PATH", oadbPath); | |
1633 | // if (lite) gSystem->Setenv("OADB_PATH", oadbPath); | |
1634 | // Info("Connect", "OADB_PATH=%s", gSystem->Getenv("OADB_PATH")); | |
1635 | ||
1636 | // --- Now open connection to PROOF cluster -------------------- | |
1d86b7ca | 1637 | TProof::Open(serv); |
1638 | if (!gProof) { | |
1639 | Error("Connect", "Failed to connect to Proof cluster %s as %s", | |
1640 | fProofServer.Data(), userName.Data()); | |
1641 | return false; | |
1642 | } | |
d23503ee | 1643 | Info("Connect", "Now connected to Proof"); |
1644 | // gProof->SetParameter("PROOF_LookupOpt", "all"); | |
1d86b7ca | 1645 | if (lite) return true; |
1646 | } | |
1647 | ||
1648 | // --- Open a connection to the grid ----------------------------- | |
e01b1d30 | 1649 | |
1d86b7ca | 1650 | TGrid::Connect("alien://"); |
1651 | if (!gGrid || !gGrid->IsConnected()) { | |
1652 | // This is only fatal in grid mode | |
1653 | Error("Connect", "Failed to connect to AliEN"); | |
e01b1d30 | 1654 | if (fExecMode == kGrid) return false; |
1d86b7ca | 1655 | return true; |
1656 | } | |
e01b1d30 | 1657 | if (fExecMode == kGrid) return true; |
1d86b7ca | 1658 | |
1d86b7ca | 1659 | // --- Set and make output directory ----------------------------- |
1660 | TString name = EscapedName(); | |
1661 | TString homeDir(gGrid->GetHomeDirectory()); | |
1662 | TString workDir(homeDir); | |
1663 | workDir.Append("/"); | |
1664 | workDir.Append(name); | |
1665 | ||
1666 | // Make working directory | |
1667 | if (!gGrid->Cd(workDir)) { | |
1668 | gGrid->Cd(homeDir); | |
1669 | if (gGrid->Mkdir(workDir)) { | |
1670 | gGrid->Cd(name); | |
1671 | Info("Connect", "Directory %s created", workDir.Data()); | |
1672 | } | |
1673 | } | |
1674 | // Make output directory | |
1675 | gGrid->Mkdir("proof_output"); | |
1676 | gGrid->Cd("proof_output"); | |
e01b1d30 | 1677 | |
1d86b7ca | 1678 | return true; |
1679 | } | |
e01b1d30 | 1680 | //------------------------------------------------------------------ |
1d86b7ca | 1681 | /** |
e01b1d30 | 1682 | * Get the output directory (local or Grid) |
1d86b7ca | 1683 | * |
e01b1d30 | 1684 | * @param mode Mode of execution |
1d86b7ca | 1685 | * |
e01b1d30 | 1686 | * @return Path to output directory |
1d86b7ca | 1687 | */ |
e01b1d30 | 1688 | TString GetOutputDirectory(EMode mode) const |
1d86b7ca | 1689 | { |
e01b1d30 | 1690 | TString ret(fEscapedName); |
1691 | if (mode != kGrid) return ret; | |
1692 | ||
1693 | AliAnalysisManager* am = AliAnalysisManager::GetAnalysisManager(); | |
1694 | if (!am) { | |
1695 | Warning("GetOutputDirectory", "No analysis manager defined yet"); | |
1696 | return ret; | |
1d86b7ca | 1697 | } |
e01b1d30 | 1698 | AliAnalysisGrid* ag = am->GetGridHandler(); |
1699 | if (!ag) { | |
1700 | Warning("GetOutputDirectory", "No grid handler defined yet"); | |
1701 | return ret; | |
1702 | } | |
1703 | AliAnalysisAlien* aa = dynamic_cast<AliAnalysisAlien*>(ag); | |
1704 | if (!aa) { | |
1705 | Warning("GetOutputDirectory", "Grid handler isn't for AliEn"); | |
1706 | return ret; | |
1707 | } | |
1708 | ret = aa->GetGridOutputDir(); | |
1709 | if (!ret.BeginsWith("/")) { | |
1710 | if (gGrid) | |
1711 | ret = Form("%s/%s/%s", gGrid->GetHomeDirectory(), | |
1712 | fEscapedName.Data(), aa->GetGridOutputDir()); | |
1713 | else | |
1714 | ret = Form("%s/%s", fEscapedName.Data(), aa->GetGridOutputDir()); | |
36619b75 | 1715 | } |
1d86b7ca | 1716 | return ret; |
1717 | } | |
e01b1d30 | 1718 | /* @} */ |
1719 | ||
1d86b7ca | 1720 | //__________________________________________________________________ |
1721 | /** | |
e01b1d30 | 1722 | * @{ |
1723 | * @name Setup | |
1724 | */ | |
1725 | /** | |
1726 | * Make our working directory if so requested | |
1d86b7ca | 1727 | * |
e01b1d30 | 1728 | * @return true on success |
1d86b7ca | 1729 | */ |
e01b1d30 | 1730 | Bool_t SetupWorkingDirectory() |
1d86b7ca | 1731 | { |
e01b1d30 | 1732 | TString nam = EscapedName(); |
1733 | //Info("Init","Current dir=%s, escaped name=%s",cwd.Data(),nam.Data()); | |
1734 | Bool_t exists = gSystem->AccessPathName(nam.Data()) == 0; | |
1735 | if (fExecOper == kTerminate && !exists) { | |
1736 | Error("SetupWorkingDirectory", "File/directory %s does not exists", | |
1737 | nam.Data()); | |
1738 | return false; | |
1739 | } | |
1d86b7ca | 1740 | |
e01b1d30 | 1741 | |
1742 | if (!fAllowOverwrite && exists) { | |
1743 | Error("SetupWorkingDirectory", "File/directory %s already exists", | |
1744 | nam.Data()); | |
1745 | return false; | |
1746 | } | |
1d86b7ca | 1747 | |
e01b1d30 | 1748 | if (!exists) { |
1749 | if (gSystem->MakeDirectory(nam.Data())) { | |
1750 | Error("SetupWorkingDirectory", "Failed to make directory '%s'", | |
1751 | nam.Data()); | |
1752 | return false; | |
1d86b7ca | 1753 | } |
1d86b7ca | 1754 | } |
e01b1d30 | 1755 | |
1756 | if (!gSystem->ChangeDirectory(nam.Data())) { | |
1757 | Error("SetupWorkingDirectory", "Failed to change directory to %s", | |
1758 | nam.Data()); | |
1d86b7ca | 1759 | return false; |
1760 | } | |
e01b1d30 | 1761 | Info("SetupWorkingDirectory", "Made subdirectory %s, and cd'ed there", |
1762 | nam.Data()); | |
1d86b7ca | 1763 | return true; |
1764 | } | |
e01b1d30 | 1765 | //------------------------------------------------------------------ |
1766 | /** | |
1767 | * Set-up a PAR file | |
1768 | * | |
1769 | * @param what PAR file | |
1770 | * | |
1771 | * @return true on success | |
1772 | */ | |
1d86b7ca | 1773 | Bool_t SetupPAR(const char* what) |
1774 | { | |
1775 | if (!what || what[0] == '\0') return -1; | |
1776 | ||
1777 | TString parFile(Form("%s.par", what)); | |
1778 | if (gSystem->AccessPathName(parFile.Data())) { | |
1779 | if (gSystem->AccessPathName(Form("../%s.par", what))) { | |
1780 | // If not found | |
1781 | TString aliParFile = | |
1782 | gSystem->ExpandPathName(Form("$(ALICE_ROOT)/%s.par", what)); | |
1783 | if (gSystem->AccessPathName(aliParFile.Data())) { | |
1784 | Error("SetupPAR", "PAR file %s not found in current directory or " | |
1785 | "$(ALICE_ROOT)", what); | |
1786 | return false; | |
1787 | } | |
1788 | // Copy to current directory | |
1789 | TFile::Cp(aliParFile, parFile); | |
1790 | } | |
1791 | else | |
1792 | gSystem->Exec(Form("ln -s ../%s.par .", what)); | |
1793 | } | |
1794 | ||
1795 | // Extract archive | |
2a276c75 | 1796 | gSystem->Exec(Form("tar xzf %s", parFile.Data())); |
1d86b7ca | 1797 | |
1798 | // Change directory into par archive | |
1799 | TString cwd = gSystem->WorkingDirectory(); | |
1800 | ||
1801 | if (!gSystem->ChangeDirectory(what)) { | |
1802 | Error("SetupPAR", "Failed to change directory to %s", what); | |
1803 | return false; | |
1804 | } | |
1805 | ||
1806 | // Test the build | |
1807 | if (!gSystem->AccessPathName("PROOF-INF/BUILD.sh")) { | |
1808 | Info("SetupPar", "Building in PAR archive %s", what); | |
1809 | if (gSystem->Exec("PROOF-INF/BUILD.sh")) { | |
1810 | Error("SetupPar", "Failed to build in PAR directory %s", what); | |
1811 | gSystem->ChangeDirectory(cwd.Data()); | |
1812 | return false; | |
1813 | } | |
1814 | } | |
1815 | ||
1816 | // Check for setup script | |
1817 | if (!gSystem->AccessPathName("PROOF-INF/SETUP.C")) { | |
e01b1d30 | 1818 | // Info("SetupPAR", "Setting up for PAR %s", what); |
1d86b7ca | 1819 | gROOT->Macro("PROOF-INF/SETUP.C"); |
1820 | } | |
1821 | if (!gSystem->ChangeDirectory(cwd.Data())) return false; | |
1822 | ||
1823 | return true; | |
1824 | } | |
e01b1d30 | 1825 | //------------------------------------------------------------------ |
1826 | /** | |
1827 | * Set-up extra sources. | |
1828 | * | |
1829 | * @return true on success | |
1830 | */ | |
1d86b7ca | 1831 | TString SetupExtras() |
1832 | { | |
1833 | TString ret; | |
1834 | TIter next(&fListOfExtras); | |
1835 | TObjString* obj = 0; | |
1836 | while ((obj = static_cast<TObjString*>(next()))) { | |
1837 | TString path = gSystem->ExpandPathName(obj->GetName()); | |
1838 | if (!path.BeginsWith("/")) | |
1839 | // If not an absolute path, prepend to up-one | |
1840 | path = Form("../%s", path.Data()); | |
1841 | if (gSystem->AccessPathName(path.Data())) { | |
1842 | // File not accessible | |
1843 | Warning("SetupExtras", "File %s not accessible", path.Data()); | |
1844 | continue; | |
1845 | } | |
1846 | ret.Append(Form("%s ", gSystem->BaseName(obj->GetName()))); | |
1847 | gSystem->Exec(Form("ln -s %s .", path.Data())); | |
1848 | } | |
1849 | ret = ret.Strip(); | |
1850 | return ret; | |
1851 | } | |
e01b1d30 | 1852 | //------------------------------------------------------------------ |
1853 | /** | |
1854 | * Set-up sources for upload | |
1855 | * | |
1856 | * | |
1857 | * @return String of sources | |
1858 | */ | |
1d86b7ca | 1859 | TString SetupSources() |
1860 | { | |
1861 | TString nam = EscapedName(); | |
1862 | TString ret; | |
1863 | TIter next(&fListOfSources); | |
1864 | TObject* src; | |
1865 | while ((src = next())) { | |
1866 | TString path = gSystem->ExpandPathName(src->GetName()); | |
1867 | if (!path.BeginsWith("/")) | |
1868 | // If not an absolute path, prepend to up-one | |
1869 | path = Form("../%s", path.Data()); | |
1870 | if (gSystem->AccessPathName(path.Data())) { | |
1871 | // File not accessible | |
1872 | Warning("SetupSources", "File %s not accessible", path.Data()); | |
1873 | continue; | |
1874 | } | |
1875 | ret.Append(Form("%s ", gSystem->BaseName(src->GetName()))); | |
1876 | gSystem->Exec(Form("ln -s %s .", path.Data())); | |
1877 | } | |
1878 | ret = ret.Strip(); | |
1879 | return ret; | |
1880 | } | |
e01b1d30 | 1881 | //------------------------------------------------------------------ |
1882 | /** | |
1883 | * Set-up extra libraries to upload | |
1884 | * | |
1885 | * @return String of libraries | |
1886 | */ | |
1d86b7ca | 1887 | TString SetupLibraries() |
1888 | { | |
1889 | TString ret; | |
1890 | TIter next(&fListOfLibraries); | |
1891 | TObject* lib; | |
1892 | while ((lib = next())) { | |
1893 | ret.Append(lib->GetName()); | |
1894 | ret.Append(" "); | |
1895 | } | |
1896 | // Also add extra files to this variable | |
1897 | ret.Append(SetupExtras()); | |
1898 | ret = ret.Strip(); | |
1899 | return ret; | |
1900 | } | |
e01b1d30 | 1901 | /* @} */ |
1902 | ||
1d86b7ca | 1903 | //__________________________________________________________________ |
e01b1d30 | 1904 | /** |
1905 | * @{ | |
1906 | * @name Chain building | |
1907 | */ | |
0c4ed5fc | 1908 | /** |
1909 | * Check if we can add a file to the chain | |
1910 | * | |
1911 | * @param path Full path to file | |
1912 | * @param chain Chain | |
1913 | * | |
1914 | * @return true on success, false otherwise | |
1915 | */ | |
1916 | Bool_t CheckFile(const TString& path, TChain* chain) | |
1917 | { | |
1918 | TFile* test = TFile::Open(path, "READ"); | |
1919 | if (!test) { | |
1920 | Warning("CheckFile", "Failed to open %s", path.Data()); | |
1921 | return false; | |
1922 | } | |
1923 | ||
1924 | Bool_t ok = false; // Assume failure | |
1925 | TObject* o = test->Get(chain->GetName()); | |
1926 | if (!o) | |
1927 | Warning("CheckFile", "The file %s does not contain the object %s", | |
1928 | path.Data(), chain->GetName()); | |
1929 | else if (!dynamic_cast<TTree*>(o)) | |
1930 | Warning("CheckFile", "Object %s found in %s is not a TTree", | |
1931 | o->GetName(), path.Data()); | |
1932 | else | |
1933 | ok = true; | |
1934 | test->Close(); | |
1935 | if (ok) chain->AddFile(path); | |
1936 | ||
1937 | return ok; | |
1938 | } | |
1d86b7ca | 1939 | /** |
1940 | * Scan directory @a dir (possibly recursive) for tree files to add | |
1941 | * to the chain. This does not follow sym-links | |
1942 | * | |
1943 | * @param dir Directory to scan | |
1944 | * @param chain Chain to add to | |
1d86b7ca | 1945 | * @param recursive Whether to scan recursively |
1d86b7ca | 1946 | * |
1947 | * @return true if any files where added | |
1948 | */ | |
1949 | Bool_t ScanDirectory(TSystemDirectory* dir, TChain* chain, | |
e01b1d30 | 1950 | bool recursive) |
1d86b7ca | 1951 | { |
1952 | TString fnPattern; | |
e01b1d30 | 1953 | switch (fExecType) { |
1d86b7ca | 1954 | case kESD: fnPattern = "AliESD"; break; |
1955 | case kAOD: fnPattern = "AliAOD"; break; | |
e01b1d30 | 1956 | case kUser: fnPattern = ""; break; |
1d86b7ca | 1957 | } |
1958 | ||
1959 | // Assume failure | |
1960 | Bool_t ret = false; | |
1961 | ||
1962 | // Get list of files, and go back to old working directory | |
1963 | TString oldDir(gSystem->WorkingDirectory()); | |
1964 | TList* files = dir->GetListOfFiles(); | |
1965 | if (!gSystem->ChangeDirectory(oldDir)) { | |
1966 | Error("ScanDirectory", "Failed to go back to %s", oldDir.Data()); | |
1967 | return false; | |
1968 | } | |
1969 | if (!files) return false; | |
1970 | ||
1971 | TList toAdd; | |
1972 | toAdd.SetOwner(); | |
3112bd03 | 1973 | Bool_t hasGAlice = (!(fMC || fExecType == kAOD) ? true : false); |
1974 | Bool_t hasKine = (!(fMC || fExecType == kAOD) ? true : false); | |
1975 | Bool_t hasTrRef = (!(fMC || fExecType == kAOD) ? true : false); | |
1d86b7ca | 1976 | |
1977 | // Sort list of files and check if we should add it | |
1978 | files->Sort(); | |
1979 | TIter next(files); | |
1980 | TSystemFile* file = 0; | |
1981 | while ((file = static_cast<TSystemFile*>(next()))) { | |
1982 | TString name(file->GetName()); | |
1983 | TString title(file->GetTitle()); | |
1984 | TString full(gSystem->ConcatFileName(file->GetTitle(), name.Data())); | |
1985 | if (dynamic_cast<TSystemDirectory*>(file)) full = title; | |
1986 | // Ignore special links | |
1987 | if (name == "." || name == "..") { | |
1988 | // Info("ScanDirectory", "Ignoring %s", name.Data()); | |
1989 | continue; | |
1990 | } | |
1991 | ||
1992 | FileStat_t fs; | |
1993 | if (gSystem->GetPathInfo(full.Data(), fs)) { | |
1994 | Warning("ScanDirectory", "Cannot stat %s (%s)", full.Data(), | |
1995 | gSystem->WorkingDirectory()); | |
1996 | continue; | |
1997 | } | |
1998 | // Check if this is a directory | |
1999 | if (file->IsDirectory(full)) { | |
2000 | if (recursive) { | |
2001 | // if (title[0] == '/') | |
2002 | TSystemDirectory* d = new TSystemDirectory(file->GetName(), | |
2003 | full.Data()); | |
e01b1d30 | 2004 | if (ScanDirectory(d,chain,recursive)) |
1d86b7ca | 2005 | ret = true; |
2006 | delete d; | |
2007 | } | |
2008 | continue; | |
2009 | } | |
2010 | ||
2011 | // If this is not a root file, ignore | |
2012 | if (!name.EndsWith(".root")) continue; | |
2013 | ||
2014 | // If this file does not contain AliESDs, ignore | |
2015 | if (!name.Contains(fnPattern)) { | |
2016 | // Info("ScanDirectory", "%s does not match pattern %s", | |
2017 | // name.Data(), fnPattern.Data()); | |
3112bd03 | 2018 | if (fMC && fExecType == kESD) { |
1d86b7ca | 2019 | if (name.CompareTo("galice.root") == 0) hasGAlice = true; |
2020 | if (name.CompareTo("Kinematics.root") == 0) hasKine = true; | |
2021 | if (name.CompareTo("TrackRefs.root") == 0) hasTrRef = true; | |
2022 | } | |
2023 | continue; | |
2024 | } | |
2025 | ||
2026 | // Add | |
2027 | // Info("ScanDirectory", "Adding %s", full.Data()); | |
2028 | toAdd.Add(new TObjString(full)); | |
2029 | } | |
2030 | ||
3112bd03 | 2031 | if (fMC && fExecType == kESD && toAdd.GetEntries() > 0 && |
1d86b7ca | 2032 | (!hasGAlice || !hasKine || !hasTrRef)) { |
2033 | Warning("ScanDirectory", | |
2034 | "one or more of {galice,Kinematics,TrackRefs}.root missing from " | |
2035 | "%s, not adding anything from this directory", | |
2036 | dir->GetTitle()); | |
2037 | toAdd.Delete(); | |
2038 | } | |
2039 | ||
2040 | TIter nextAdd(&toAdd); | |
2041 | TObjString* s = 0; | |
0c4ed5fc | 2042 | Int_t added = 0; |
1d86b7ca | 2043 | while ((s = static_cast<TObjString*>(nextAdd()))) { |
2044 | // Info("ScanDirectory", "Adding %s", s->GetString().Data()); | |
0c4ed5fc | 2045 | TString fn = s->GetString(); |
2046 | if (!CheckFile(fn, chain)) continue; | |
2047 | ||
2048 | added++; | |
1d86b7ca | 2049 | } |
0c4ed5fc | 2050 | if (added > 0) ret = true; |
1d86b7ca | 2051 | |
2052 | gSystem->ChangeDirectory(oldDir); | |
2053 | return ret; | |
2054 | } | |
e01b1d30 | 2055 | //------------------------------------------------------------------ |
1d86b7ca | 2056 | /** |
2057 | * Create a chain from an XML containing an collection | |
2058 | * | |
2059 | * @param treeName Name of tree's | |
2060 | * @param xmlFile XML collection | |
2061 | * | |
2062 | * @return Newly allocated chain or null | |
2063 | */ | |
2064 | TChain* CreateChainFromXML(const char* treeName, | |
2065 | const char* xmlFile) | |
2066 | { | |
7684b64e | 2067 | Long_t ret = gROOT->ProcessLine(Form("TAlienCollection(\"%s\")", |
2068 | xmlFile)); | |
2069 | if (!ret) { | |
2070 | Error("CreateChainFromXML", "Cannot create AliEn collection from " | |
2071 | "XML file %s", xmlFile); | |
2072 | return 0; | |
2073 | } | |
2074 | ||
2075 | TGridCollection* collection = reinterpret_cast<TGridCollection*>(ret); | |
1d86b7ca | 2076 | if (!collection) { |
2077 | Error("CreateChainFromXML", "Cannot create AliEn collection from " | |
2078 | "XML file %s", xmlFile); | |
2079 | return 0; | |
2080 | } | |
2081 | ||
2082 | TChain* chain = new TChain(treeName); | |
2083 | collection->Reset(); | |
2084 | while (collection->Next()) chain->Add(collection->GetTURL("")); | |
2085 | ||
2086 | return chain; | |
2087 | } | |
e01b1d30 | 2088 | //------------------------------------------------------------------ |
1d86b7ca | 2089 | /** |
2090 | * Create a chain of data | |
1d86b7ca | 2091 | * |
2092 | * @return TChain of data | |
2093 | */ | |
e01b1d30 | 2094 | TChain* CreateChain() |
1d86b7ca | 2095 | { |
2096 | TString treeName; | |
e01b1d30 | 2097 | switch (fExecType) { |
1d86b7ca | 2098 | case kESD: treeName = "esdTree"; break; |
2099 | case kAOD: treeName = "aodTree"; break; | |
e01b1d30 | 2100 | case kUser: treeName = ""; break; |
1d86b7ca | 2101 | } |
2102 | ||
2103 | TChain* chain = 0; | |
e01b1d30 | 2104 | switch (fExecMode) { |
1d86b7ca | 2105 | case kProof: |
2106 | if (!fDataSet.IsNull()) break; | |
2107 | // Otherwise fall through | |
2108 | case kLocal: | |
2109 | if (fXML.IsNull()) { | |
2110 | chain = new TChain(treeName.Data()); | |
2111 | TString dir(fDataDir); | |
2112 | if (dir == ".") dir = ""; | |
2113 | if (!dir.BeginsWith("/")) dir = Form("../%s", dir.Data()); | |
0c4ed5fc | 2114 | FileStat_t stat; |
2115 | gSystem->GetPathInfo(dir, stat); | |
2116 | if (!R_ISDIR(stat.fMode)) { // A file, check it | |
2117 | if (!CheckFile(dir, chain)) { | |
2118 | delete chain; | |
2119 | chain = 0; | |
2120 | } | |
2121 | break; | |
2122 | } | |
1d86b7ca | 2123 | TString savdir(gSystem->WorkingDirectory()); |
2124 | TSystemDirectory d(gSystem->BaseName(dir.Data()), dir.Data()); | |
e01b1d30 | 2125 | if (!ScanDirectory(&d, chain, true)) { |
1d86b7ca | 2126 | delete chain; |
2127 | chain = 0; | |
2128 | } | |
2129 | gSystem->ChangeDirectory(savdir); | |
2130 | } | |
2131 | else | |
2132 | chain = CreateChainFromXML(treeName.Data(), fXML.Data()); | |
2133 | break; | |
2134 | case kGrid: break; // Do nothing - we use plugin | |
2135 | } | |
2136 | ||
2137 | if (chain && chain->GetNtrees() <= 0) { | |
2138 | delete chain; | |
2139 | return 0; | |
2140 | } | |
2141 | return chain; | |
2142 | } | |
e01b1d30 | 2143 | /* @} */ |
2144 | ||
2145 | public: | |
2146 | //==================================================================== | |
2147 | /** | |
2148 | * Option class | |
2149 | * | |
2150 | */ | |
2151 | struct Option | |
2a276c75 | 2152 | { |
e01b1d30 | 2153 | /** |
2154 | * Constructor | |
2155 | * | |
2156 | * @param name Option name | |
2157 | * @param desc Option description | |
2158 | * @param arg Option argument, if any | |
2159 | */ | |
2160 | Option(const char* name, const char* desc, const char* arg="") | |
2161 | : fName(name), | |
2162 | fDesc(desc), | |
2163 | fArg(arg), | |
2164 | fIsSet(false), | |
2165 | fValue("") | |
2166 | {} | |
2167 | /** | |
2168 | * Process an option string. | |
2169 | * | |
2170 | * @param opt String to process | |
2171 | * | |
2172 | * @return true, if this handled the option, false otherwise | |
2173 | */ | |
2174 | Bool_t Process(const TString& opt) | |
2175 | { | |
2176 | // Info("Option::Process", "Option %s processing %s", | |
2177 | // fName.Data(), opt.Data()); | |
2178 | if (!opt.BeginsWith(fName, TString::kIgnoreCase)) return false; | |
2179 | ||
2180 | // We've got a value | |
2181 | fIsSet = true; | |
2a276c75 | 2182 | |
e01b1d30 | 2183 | // No argument options shouldn't set a value |
2184 | if (fArg.IsNull()) return true; | |
2185 | ||
2186 | // Parse out value | |
2187 | Int_t eq = opt.Index("="); | |
2188 | ||
2189 | // Empty string is an OK value | |
2190 | if (eq == kNPOS) return true; | |
2191 | ||
2192 | TString tmp = opt(eq+1,opt.Length()-eq-1); | |
2193 | fValue = tmp.Strip(); | |
2194 | ||
2195 | return true; | |
2a276c75 | 2196 | } |
e01b1d30 | 2197 | /** |
2198 | * Get option value as a string | |
2199 | * | |
2200 | * @return Option value | |
2201 | */ | |
2202 | const TString& AsString() const { return fValue; } | |
2203 | /** | |
2204 | * Get option value as a double | |
2205 | * | |
2206 | * @return Option value | |
2207 | */ | |
2208 | Double_t AsDouble() const { return fValue.Atof(); } | |
2209 | /** | |
2210 | * Get option value as an integer | |
2211 | * | |
2212 | * @return Option value | |
2213 | */ | |
2214 | Int_t AsInt() const { return fValue.Atoi(); } | |
2215 | /** | |
2216 | * Get option value as a boolean | |
2217 | * | |
2218 | * @return Option value | |
2219 | */ | |
2220 | Bool_t AsBool() const { return fIsSet; } | |
2221 | /** | |
2222 | * Test if the option has been set. | |
2223 | * | |
2224 | * @return True if the option was given | |
2225 | */ | |
2226 | Bool_t IsSet() const { return fIsSet; } | |
2227 | /** | |
2228 | * Print help. | |
2229 | * | |
2230 | * @param o Stream to write on | |
2231 | * @param prefix Prefix | |
2232 | */ | |
2233 | void PrintHelp(std::ostream& o, const char* prefix) const | |
2234 | { | |
2235 | TString arg(fName); | |
2236 | if (!fArg.IsNull()) arg.Append(Form("=%s", fArg.Data())); | |
2237 | o << " " << (prefix ? prefix : "") | |
2238 | << std::left << std::setw(30) << arg | |
a76fb27d | 2239 | << " " << std::setw(30) << fDesc |
2240 | << " [" << std::right << fValue << "]" << std::endl; | |
2a276c75 | 2241 | } |
e01b1d30 | 2242 | /** |
2243 | * Print the setting | |
2244 | * | |
2245 | * @param o Stream to write on | |
2246 | */ | |
2247 | void PrintSettings(std::ostream& o) const | |
2248 | { | |
2249 | o << " " << std::left << std::setw(30) << fName << ": "; | |
2250 | if (fArg.IsNull()) o << (IsSet() ? "true" : "false"); | |
2251 | else o << fValue; | |
2252 | o << std::endl; | |
2a276c75 | 2253 | } |
e01b1d30 | 2254 | /** |
2255 | * Save the setting | |
2256 | * | |
2257 | * @param str object nmae | |
2258 | * @param val Value | |
2259 | * @param o Stream to write on | |
2260 | */ | |
2261 | void Save(std::ostream& o, const char* str, bool val) | |
2262 | { | |
2263 | if (!val) return; | |
2264 | if (str[0] == '-') { | |
2265 | o << " " << str << fName << " \\" << std::endl; | |
2266 | return; | |
2267 | } | |
2268 | o << " " << str << ".Append(\"" << fName << ",\");" << std::endl; | |
2a276c75 | 2269 | } |
e01b1d30 | 2270 | /** |
2271 | * Save the setting | |
2272 | * | |
2273 | * @param str object nmae | |
2274 | * @param val Value | |
2275 | * @param o Stream to write on | |
2276 | */ | |
2277 | void Save(std::ostream& o, const char* str, Int_t val) | |
2278 | { | |
2279 | if (str[0] == '-') { | |
2280 | o << " " << str << fName << "=" << val << " \\" << std::endl; | |
2281 | return; | |
2282 | } | |
2283 | o << " " << str << ".Append(\"" << fName << "=" << val | |
2284 | << ",\");" << std::endl; | |
2285 | } | |
2286 | /** | |
2287 | * Save the setting | |
2288 | * | |
2289 | * @param str object nmae | |
2290 | * @param val Value | |
2291 | * @param o Stream to write on | |
2292 | */ | |
2293 | void Save(std::ostream& o, const char* str, Double_t val) | |
2294 | { | |
2295 | if (str[0] == '-') { | |
2296 | o << " " << str << fName << "=" << val << " \\" << std::endl; | |
2297 | return; | |
2298 | } | |
2299 | o << " " << str << ".Append(\"" << fName << "=" << val | |
2300 | << ",\");" << std::endl; | |
2301 | } | |
2302 | /** | |
2303 | * Save the setting | |
2304 | * | |
2305 | * @param str object nmae | |
2306 | * @param val Value | |
2307 | * @param o Stream to write on | |
2308 | */ | |
2309 | void Save(std::ostream& o, const char* str, const char* val) | |
2310 | { | |
2311 | if (str[0] == '-') { | |
2312 | TString sval(val); | |
2313 | sval.ReplaceAll(" ", "\\ "); | |
2314 | o << " " << str << fName << "=" << sval << " \\" << std::endl; | |
2315 | return; | |
2316 | } | |
2317 | o << " " << str << ".Append(\"" << fName << "=" << val | |
2318 | << ",\");" << std::endl; | |
2319 | } | |
2320 | ||
2321 | TString fName; // Name of the option | |
2322 | TString fDesc; // Decription | |
2323 | TString fArg; // Argument, if any | |
2324 | Bool_t fIsSet; // Whether the option has been set. | |
2325 | TString fValue; // Value of the option. | |
2326 | }; | |
2327 | //==================================================================== | |
2328 | /** | |
2329 | * Run a train setup | |
2330 | * | |
2331 | */ | |
2332 | struct Runner | |
2a276c75 | 2333 | { |
e01b1d30 | 2334 | /** |
2335 | * Constructor | |
2336 | * | |
2337 | * @param train Train to run | |
2338 | * @param max Maximum number of options | |
2339 | */ | |
2340 | Runner(TrainSetup& train, UShort_t max=30) | |
2341 | : fTrain(&train), fOptions(0), fN(0), fMax(max) | |
2342 | { | |
2343 | fOptions = new Option*[fMax]; | |
2344 | for (Int_t i = 0; i < fMax; i++) fOptions[i] = 0; | |
2345 | } | |
2346 | /** | |
2347 | * Add an option | |
2348 | * | |
2349 | * @param opt Option to add | |
2350 | */ | |
2351 | void Add(Option* opt) | |
2352 | { | |
2353 | if (fN >= fMax) { | |
2354 | Warning("AddOption", "No room for option %s", opt->fName.Data()); | |
2355 | return; | |
2356 | } | |
2357 | fOptions[fN++] = opt; | |
2358 | } | |
2359 | /** | |
2360 | * Remove an option | |
2361 | * | |
2362 | * @param name | |
2363 | */ | |
2364 | void Remove(const TString& name) | |
2365 | { | |
2366 | Option** ptr = fOptions; | |
2367 | Option** tmp = 0; | |
2368 | while (*ptr) { | |
2369 | if (name.EqualTo((*ptr)->fName)) { | |
2370 | tmp = ptr; | |
2371 | break; | |
2372 | } | |
2373 | ptr++; | |
2374 | } | |
2375 | if (!tmp) // nothing found, returning | |
2376 | return; | |
2377 | ||
2378 | ptr = tmp; | |
2379 | delete *tmp; | |
2380 | tmp++; | |
2381 | fN--; | |
2382 | while (*tmp) { | |
2383 | *ptr = *tmp; | |
2384 | ptr++; | |
2385 | tmp++; | |
2386 | } | |
2387 | *ptr = 0; | |
2388 | } | |
2389 | ||
2390 | /** | |
2391 | * Parse option string | |
2392 | * | |
2393 | * @param options Option string. | |
2394 | * @param delim Delimiters | |
2395 | * | |
2396 | * @return true on success. | |
2397 | */ | |
2398 | Bool_t Parse(const TString& options, const char* delim=",;") | |
2399 | { | |
2400 | TObjArray* a = options.Tokenize(delim); | |
2401 | return Parse(*a); | |
2402 | } | |
2403 | /** | |
2404 | * Parse options | |
2405 | * | |
2406 | * @param options | |
2407 | * | |
2408 | * @return true on success | |
2409 | */ | |
2410 | Bool_t Parse(TObjArray& options) | |
2411 | { | |
2412 | TIter next(&options); | |
2413 | TObjString* os = 0; | |
2414 | while ((os = static_cast<TObjString*>(next()))) { | |
2415 | TString s(os->String()); | |
2416 | // Info("Runner::Parse", "Processing option %s", s.Data()); | |
2417 | if (s.IsNull()) continue; | |
2418 | ||
2419 | Bool_t ok = false; | |
2420 | Option** ptr = fOptions; | |
2421 | while (*ptr && !ok) { | |
2422 | Option* o = *ptr; | |
2423 | if (o->Process(s)) ok = true; | |
2424 | ptr++; | |
2425 | } | |
2426 | ||
2427 | if (!ok) | |
2428 | Warning("Parse", "Unknown option %s", s.Data()); | |
2429 | } | |
2430 | return true; | |
2431 | } | |
2432 | /** | |
2433 | * Check if we asked for help | |
2434 | * | |
2435 | * | |
2436 | * @return | |
2437 | */ | |
2438 | Bool_t IsHelpAsked() const | |
2439 | { | |
2440 | Option* help = FindOption("help"); | |
2441 | return (help && help->IsSet()); | |
2442 | } | |
2443 | /** | |
2444 | * Print help | |
2445 | * | |
2446 | * @param out Stream to write on | |
2447 | * @param prefix Prefix | |
2448 | */ | |
2449 | void PrintHelp(std::ostream& out, const char* prefix="") const | |
2450 | { | |
2451 | Option** ptr = fOptions; | |
a76fb27d | 2452 | if (fTrain) fTrain->SetOptionDefaults(const_cast<Runner&>(*this)); |
e01b1d30 | 2453 | while (*ptr) { |
2454 | (*ptr)->PrintHelp(out, prefix); | |
2455 | ptr++; | |
2456 | } | |
2457 | } | |
2458 | /** | |
2459 | * Print the settings | |
2460 | * | |
2461 | * @param out Stream to write on. | |
2462 | */ | |
2463 | void PrintSettings(std::ostream& out) const | |
2464 | { | |
2465 | Option** ptr = fOptions; | |
2466 | while (*ptr) { | |
2467 | (*ptr)->PrintSettings(out); | |
2468 | ptr++; | |
2469 | } | |
2470 | } | |
2471 | /** | |
2472 | * Find an option by name | |
2473 | * | |
2474 | * @param name Name of option to find | |
2475 | * | |
2476 | * @return Pointer to option, or null | |
2477 | */ | |
2478 | Option* FindOption(const TString& name) const | |
2479 | { | |
2480 | Option** ptr = fOptions; | |
2481 | while (*ptr) { | |
2482 | if (name.EqualTo((*ptr)->fName)) return *ptr; | |
2483 | ptr++; | |
2484 | } | |
2485 | return 0; | |
2486 | } | |
2487 | /** | |
2488 | * Initialize the train | |
2489 | * | |
2490 | * @param options Execution options | |
2491 | * | |
2492 | * @return true on success | |
2493 | */ | |
2494 | Bool_t Init(const TString& options) | |
2495 | { | |
2496 | fTrain->MakeOptions(*this); | |
2497 | if (!Parse(options)) return false; | |
2498 | return true; | |
2499 | } | |
2500 | /** | |
2501 | * Run the train | |
2502 | * | |
2503 | * @param runs Run numbers | |
2504 | * @param nEvents Number of events | |
2505 | * @param asShell Save set-up as shell script | |
2506 | * | |
2507 | * @return | |
2508 | */ | |
2509 | Bool_t Run(const TString& runs, Int_t nEvents, Bool_t asShell=false) | |
2510 | { | |
2511 | PrintSettings(std::cout); | |
2512 | ||
2513 | fTrain->SetOptions(*this); | |
2514 | fTrain->SetRuns(runs); | |
2515 | // fTrain->SaveSetup(*this, nEvents, asShell); | |
2516 | ||
2517 | fTrain->Run(nEvents, this, asShell); | |
2518 | return true; | |
2519 | } | |
2520 | ||
2521 | TrainSetup* fTrain; | |
2522 | Option** fOptions; // Our options | |
2523 | UShort_t fN; // Current number of options | |
2524 | UShort_t fMax; // Maximum number of options | |
2525 | }; | |
2526 | protected: | |
2a276c75 | 2527 | //__________________________________________________________________ |
e01b1d30 | 2528 | /** |
2529 | * @{ | |
2530 | * @name Options | |
2531 | */ | |
2532 | /** | |
2533 | * Class name of this train setup. Sub-classes must define this. | |
2534 | * | |
2535 | * @return Class name of this setup | |
2536 | */ | |
2537 | virtual const char* ClassName() const = 0; | |
2538 | //------------------------------------------------------------------ | |
2539 | /** | |
2540 | * Make the options for this train. Sub-classes can overload this | |
2541 | * to define new options, or append to the set of default option. | |
2542 | */ | |
2543 | virtual void MakeOptions(Runner& r) | |
2a276c75 | 2544 | { |
e01b1d30 | 2545 | r.Add(new Option("help", "Show this help")); |
2546 | r.Add(new Option("par", "Use PAR files (PROOF and Grid)")); | |
2547 | r.Add(new Option("mc", "Assume simulation input")); | |
2548 | r.Add(new Option("debug", "Execute in debugger")); | |
2549 | r.Add(new Option("type", "Type of train", "AOD|ESD")); | |
2550 | r.Add(new Option("mode", "Execution mode", "LOCAL|PROOF|GRID")); | |
2551 | r.Add(new Option("oper", "Operation mode", "TEST|TERMINATE|FULL|INIT")); | |
2552 | r.Add(new Option("date", "Set date string", "YYYY-MM-DD HH:MM:SS")); | |
2553 | r.Add(new Option("cluster","PROOF cluster", "HOST")); | |
2554 | r.Add(new Option("dataSet","Data set (PROOF only)", "NAME")); | |
2555 | r.Add(new Option("dataDir","Data directory", "DIRECTORY")); | |
2556 | r.Add(new Option("pattern","Data pattern (grid only)", "GLOB")); | |
2557 | r.Add(new Option("verb", "Verbosity", "NUMBER")); | |
2558 | r.Add(new Option("root", "ROOT version (Grid)", "TAG")); | |
2559 | r.Add(new Option("aliroot","AliROOT version (Grid)","TAG")); | |
2560 | r.Add(new Option("alien", "AliEn API version (Grid)","TAG")); | |
2561 | r.Add(new Option("overwrite", "Allow overwrite")); | |
2562 | r.Add(new Option("per-run", "Per run merge")); | |
2a276c75 | 2563 | } |
e01b1d30 | 2564 | //------------------------------------------------------------------ |
2565 | /** | |
2566 | * Set the option values on the train. Sub-classes can overload | |
a76fb27d | 2567 | * this to set custom options on the train. |
2568 | */ | |
2569 | virtual void SetOptionDefaults(Runner& r) | |
2570 | { | |
2571 | Option* debug = r.FindOption("debug"); | |
2572 | Option* date = r.FindOption("date"); | |
2573 | Option* cluster = r.FindOption("cluster"); | |
2574 | Option* dataSet = r.FindOption("dataSet"); | |
2575 | Option* dataDir = r.FindOption("dataDir"); | |
2576 | Option* pattern = r.FindOption("pattern"); | |
2577 | Option* par = r.FindOption("par"); | |
2578 | Option* type = r.FindOption("type"); | |
2579 | Option* mode = r.FindOption("mode"); | |
2580 | Option* oper = r.FindOption("oper"); | |
2581 | Option* mc = r.FindOption("mc"); | |
2582 | Option* verb = r.FindOption("verb"); | |
2583 | Option* root = r.FindOption("root"); | |
2584 | Option* aliroot = r.FindOption("aliroot"); | |
2585 | Option* alien = r.FindOption("alien"); | |
2586 | Option* overwrite = r.FindOption("overwrite"); | |
2587 | Option* run_merge = r.FindOption("per-run"); | |
2588 | ||
2589 | if (date && !date->IsSet()) date->fValue = fDatime.AsString(); | |
2590 | if (cluster && !cluster->IsSet()) cluster->fValue = fProofServer; | |
2591 | if (dataSet && !dataSet->IsSet()) dataSet->fValue = fDataSet; | |
2592 | if (dataDir && !dataDir->IsSet()) dataDir->fValue = fDataSet; | |
2593 | if (pattern && !pattern->IsSet()) pattern->fValue = fDataPattern; | |
2594 | if (debug && !debug->IsSet()) debug->fValue = fUseGDB ? "1" : ""; | |
2595 | if (type && !type->IsSet()) type->fValue = TypeString(fExecType); | |
2596 | if (mode && !mode->IsSet()) mode->fValue = ModeString(fExecMode); | |
2597 | if (oper && !oper->IsSet()) oper->fValue = OperString(fExecOper); | |
2598 | if (par && !par->IsSet()) par->fValue = fUsePar ? "1" : ""; | |
2599 | if (mc && !mc->IsSet()) mc->fValue = fMC ? "1" : ""; | |
2600 | if (verb && !verb->IsSet()) verb->fValue = Form("%d", fVerbose); | |
2601 | if (root && !root->IsSet()) root->fValue = fRootVersion; | |
2602 | if (aliroot && !aliroot->IsSet()) aliroot->fValue = fAliRootVersion; | |
2603 | if (alien && !alien->IsSet()) alien->fValue = fAliEnAPIVersion; | |
2604 | if (overwrite && !overwrite->IsSet()) | |
2605 | overwrite->fValue = fAllowOverwrite ? "1" : ""; | |
2606 | if (run_merge && !run_merge->IsSet()) | |
2607 | run_merge->fValue = fPerRunMerge ? "1" : ""; | |
2608 | } | |
2609 | /** | |
2610 | * Set the option values on the train. Sub-classes can overload | |
e01b1d30 | 2611 | * this to set custom options on the train. |
2612 | */ | |
2613 | virtual void SetOptions(Runner& r) | |
2a276c75 | 2614 | { |
e01b1d30 | 2615 | Option* debug = r.FindOption("debug"); |
2616 | Option* date = r.FindOption("date"); | |
2617 | Option* cluster = r.FindOption("cluster"); | |
2618 | Option* dataSet = r.FindOption("dataSet"); | |
2619 | Option* dataDir = r.FindOption("dataDir"); | |
2620 | Option* pattern = r.FindOption("pattern"); | |
2621 | Option* par = r.FindOption("par"); | |
2622 | Option* type = r.FindOption("type"); | |
2623 | Option* mode = r.FindOption("mode"); | |
2624 | Option* oper = r.FindOption("oper"); | |
2625 | Option* mc = r.FindOption("mc"); | |
2626 | Option* verb = r.FindOption("verb"); | |
2627 | Option* root = r.FindOption("root"); | |
2628 | Option* aliroot = r.FindOption("aliroot"); | |
2629 | Option* alien = r.FindOption("alien"); | |
2630 | Option* overwrite = r.FindOption("overwrite"); | |
2631 | Option* run_merge = r.FindOption("per-run"); | |
2632 | ||
2633 | if (date && date->IsSet()) SetDateTime(date->AsString()); | |
2634 | if (cluster) SetProofServer(cluster->AsString()); | |
2635 | if (dataSet) SetDataSet(dataSet->AsString()); | |
2636 | if (dataDir) SetDataDir(dataDir->AsString()); | |
2637 | if (pattern) SetDataPattern(pattern->AsString()); | |
2638 | if (debug) SetUseGDB(debug->AsBool()); | |
2639 | if (type && type->IsSet()) SetType(type->AsString()); | |
2640 | if (mode && mode->IsSet()) SetMode(mode->AsString()); | |
2641 | if (oper && oper->IsSet()) SetOperation(oper->AsString()); | |
2642 | if (par) SetUsePar(par->AsBool()); | |
2643 | if (mc) SetMC(mc->AsBool()); | |
2644 | if (verb) SetVerbose(verb->AsInt()); | |
2645 | if (root) SetROOTVersion(root->AsString()); | |
2646 | if (aliroot) SetAliROOTVersion(aliroot->AsString()); | |
2647 | if (alien) SetAliEnAPIVersion(alien->AsString()); | |
2648 | if (overwrite) SetAllowOverwrite(overwrite->AsBool()); | |
2649 | if (run_merge) SetPerRunMerge(run_merge->AsBool()); | |
2a276c75 | 2650 | } |
e01b1d30 | 2651 | //------------------------------------------------------------------ |
2652 | /** | |
2653 | * Set the option values on the train. Sub-classes can overload | |
2654 | * this to set custom options on the train. | |
2655 | */ | |
2656 | virtual void SaveOptions(std::ostream& o, const char* str, Runner& r) | |
2a276c75 | 2657 | { |
e01b1d30 | 2658 | Option* debug = r.FindOption("debug"); |
2659 | Option* date = r.FindOption("date"); | |
2660 | Option* cluster = r.FindOption("cluster"); | |
2661 | Option* dataSet = r.FindOption("dataSet"); | |
2662 | Option* dataDir = r.FindOption("dataDir"); | |
2663 | Option* pattern = r.FindOption("pattern"); | |
2664 | Option* par = r.FindOption("par"); | |
2665 | Option* type = r.FindOption("type"); | |
2666 | Option* mode = r.FindOption("mode"); | |
2667 | Option* oper = r.FindOption("oper"); | |
2668 | Option* mc = r.FindOption("mc"); | |
2669 | Option* verb = r.FindOption("verb"); | |
2670 | Option* root = r.FindOption("root"); | |
2671 | Option* aliroot = r.FindOption("aliroot"); | |
2672 | Option* alien = r.FindOption("alien"); | |
2673 | Option* overwrite = r.FindOption("overwrite"); | |
2674 | Option* run_merge = r.FindOption("per-run"); | |
2675 | ||
2676 | if (date) date->Save(o, str, | |
2677 | Form("%04d-%02d-%02d %02d:%02d:00", | |
2678 | fDatime.GetYear(), | |
2679 | fDatime.GetMonth(), | |
2680 | fDatime.GetDay(), | |
2681 | fDatime.GetHour(), | |
2682 | fDatime.GetMinute())); | |
2683 | if (cluster) cluster->Save(o, str, fProofServer); | |
2684 | if (dataSet) dataSet->Save(o, str, fDataSet); | |
2685 | if (dataDir) dataDir->Save(o, str, fDataDir); | |
2686 | if (pattern) pattern->Save(o, str, fDataPattern); | |
2687 | if (debug) debug->Save(o, str, fUseGDB); | |
2688 | if (type) type->Save(o, str, TypeString(fExecType)); | |
2689 | if (mode) mode->Save(o, str, ModeString(fExecMode)); | |
2690 | if (oper) oper->Save(o, str, OperString(fExecOper)); | |
2691 | if (par) par->Save(o, str, fUsePar); | |
2692 | if (mc) mc->Save(o, str, fMC); | |
2693 | if (verb) verb->Save(o, str, fVerbose); | |
2694 | if (root) root->Save(o, str, fRootVersion); | |
2695 | if (aliroot) aliroot->Save(o, str, fAliRootVersion); | |
2696 | if (alien) alien->Save(o, str, fAliEnAPIVersion); | |
2697 | if (overwrite)overwrite->Save(o, str, fAllowOverwrite); | |
2698 | if (run_merge)run_merge->Save(o, str, fPerRunMerge); | |
2a276c75 | 2699 | } |
e01b1d30 | 2700 | /** |
2701 | * Save the setup to file for later re-execution | |
2702 | * | |
2703 | * @param r Runner object | |
2704 | * @param nEvents Number of events | |
2705 | * @param asShell If true, save as shell script - otherwise ROOT script | |
2706 | */ | |
2707 | virtual void SaveSetup(Runner& r, Int_t nEvents, Bool_t asShell=false) | |
2a276c75 | 2708 | { |
e01b1d30 | 2709 | if (asShell) SaveSetupShell(r, nEvents); |
2710 | /* else */ SaveSetupROOT(r, nEvents); | |
2a276c75 | 2711 | } |
e01b1d30 | 2712 | /** |
2713 | * Save the setup to shell script for later re-execution | |
2714 | * | |
2715 | * @param r Runner object | |
2716 | * @param nEvents Number of events | |
2717 | */ | |
2718 | virtual void SaveSetupShell(Runner& r, Int_t nEvents) | |
2a276c75 | 2719 | { |
e01b1d30 | 2720 | std::ofstream o("rerun.sh"); |
2721 | o << "#!/bin/bash\n\n" | |
2722 | << "oper=$1\n" | |
2723 | << "if test x$oper = x ; then oper=full ; fi \n\n" | |
2724 | << "class=\"" << ClassName() << "\"\n" | |
2725 | << "name=\"" << fName << "\"\n" | |
2726 | << "nev=" << nEvents << "\n\n" | |
2727 | << "opts=(--class=$class \\\n" | |
2728 | << " --name=$name \\\n" | |
2729 | << " --events=$nev \\" << std::endl; | |
2a276c75 | 2730 | for (Int_t i = 0; i < fRunNumbers.GetSize(); i++) |
e01b1d30 | 2731 | o << " --run=" << fRunNumbers.At(i) << " \\\n"; |
2732 | SaveOptions(o, "--", r); | |
2733 | o << " --oper=$oper)\n\n" | |
2734 | << "echo \"Running runTrain ${opts[@]}\"\n" | |
2735 | << "runTrain \"${opts[@]}\"\n\n" | |
6ff251d8 | 2736 | << "# EOF" << std::endl; |
e01b1d30 | 2737 | o.close(); |
2738 | gSystem->Exec("chmod a+x rerun.sh"); | |
2a276c75 | 2739 | } |
e01b1d30 | 2740 | /** |
2741 | * Save the setup to shell script for later re-execution | |
2742 | * | |
2743 | * @param r Runner object | |
2744 | * @param nEvents Number of events | |
2745 | */ | |
2746 | virtual void SaveSetupROOT(Runner& r, Int_t nEvents) | |
2a276c75 | 2747 | { |
e01b1d30 | 2748 | std::ofstream o("rerun.C"); |
2749 | o << "void rerun(bool terminate=false)\n" | |
2750 | << "{\n" | |
2751 | << " TString opts;" << std::endl; | |
2752 | SaveOptions(o, "opts", r); | |
2753 | ||
2754 | o << " if (terminate) opts.Append(\"mode=terminate;\");\n\n" | |
2755 | << " TString runs(\""; | |
2756 | for (Int_t i = 0; i < fRunNumbers.GetSize(); i++) | |
2757 | o << (i == 0 ? "" : ", ") << fRunNumbers.At(i); | |
2758 | o << "\");\n\n" | |
2759 | << " Int_t nEvents = " << nEvents << ";\n\n" | |
2760 | << " gROOT->LoadMacro(\"$ALICE_ROOT/PWGLF/FORWARD/analysis2/trains/RunTrain.C\");\n" | |
2761 | << " RunTrain(\"" << ClassName() << "\",\"" | |
2762 | << fName << "\",opts,runs,nEvents);\n" | |
2763 | << "}\n" | |
2764 | << "// EOF" << std::endl; | |
2a276c75 | 2765 | o.close(); |
2766 | } | |
e01b1d30 | 2767 | /* @} */ |
2768 | ||
2a276c75 | 2769 | //__________________________________________________________________ |
1d86b7ca | 2770 | TString fName; // Name of analysis |
2a276c75 | 2771 | TString fEscapedName; // Name escaped for special chars |
1d86b7ca | 2772 | TString fRootVersion; // ROOT version to use |
2773 | TString fAliRootVersion; // AliROOT version to use | |
2774 | TString fAliEnAPIVersion; // AliEn API version to use | |
2775 | TString fProofServer; // Name of proof server | |
2776 | TString fDataDir; // Grid Input directory | |
e01b1d30 | 2777 | TString fDataPattern; // Data directory pattern |
1d86b7ca | 2778 | TString fDataSet; // Proof data set name |
2779 | TString fXML; // XML collection for local/proof mode | |
1d86b7ca | 2780 | Int_t fNReplica; // Storage replication |
871a9ac1 | 2781 | Bool_t fAllowOverwrite; // Allow overwriting output dir |
2782 | Bool_t fUseGDB; // Wrap PROOF slaves in GDB | |
2a276c75 | 2783 | Int_t fMaxSplit; // Maximum number of files per split |
2784 | TArrayI fRunNumbers; // List of run number | |
2785 | TList fListOfPARs; // List of PAR files to use | |
2786 | TList fListOfSources; // List of sources to upload and AcLIC | |
2787 | TList fListOfLibraries; // List of libraries to load | |
2788 | TList fListOfExtras; // List of extra files to upload | |
e01b1d30 | 2789 | TDatime fDatime; // Date and time |
2790 | EType fExecType; // Execution type (ESD, AOD) | |
2791 | EMode fExecMode; // Execution mode (PROOF, local, Grid) | |
2792 | EOper fExecOper; // Execution operation (full, terminate, ...) | |
2793 | Bool_t fUsePar; // Wether to use PAR files | |
2794 | Bool_t fMC; // Whether to assume MC input | |
2795 | Bool_t fPerRunMerge; // Whether to merge per run or over-all | |
2796 | Int_t fVerbose; // Verbosity level | |
1d86b7ca | 2797 | }; |
1d86b7ca | 2798 | |
2799 | //____________________________________________________________________ | |
2800 | // | |
2801 | // EOF | |
2802 | // |