]> git.uio.no Git - u/mrichter/AliRoot.git/blame - PWGLF/FORWARD/trains/GridHelper.C
Added ignores
[u/mrichter/AliRoot.git] / PWGLF / FORWARD / trains / GridHelper.C
CommitLineData
fdfd93b4 1/**
2 * @file GridHelper.C
3 * @author Christian Holm Christensen <cholm@master.hehi.nbi.dk>
4 * @date Tue Oct 16 19:01:27 2012
5 *
6 * @brief Grid Analysis Helper
7 *
8 * @ingroup pwglf_forward_trains_helper
9 *
10 */
11#ifndef GRIDHELPER_C
12#define GRIDHELPER_C
13#include "PluginHelper.C"
14#ifndef __CINT__
15# include <TUrl.h>
16# include <TString.h>
17# include <TGrid.h>
18# include <AliAnalysisManager.h>
19# include <AliAnalysisAlien.h>
20#else
21class TUrl;
22class AliAnalysisAlien;
23#endif
24
25// ===================================================================
26/**
27 * Handle analysis on an the Grid
28 *
29 * This helper is triggered by a URL of the form
30 *
31 * @code
32 * alien:///<directory>[?<options>][#<pattern>]
33 * @endcode
34 * where
35 * <dl>
36 * <dt>&lt;directory@gt;</dt>
37 * <dd>Grid directory that holds the data</dd>
38 * <dt>&lt;treeName@gt;</dt>
39 * <dd>Tree to loop over</dd>
40 * <dt>&lt;options@gt;</dt>
41 * <dd>List of options separated by an &amp;
42 * <dl>
43 * <dt><tt>storage=&lt;url&gt;</tt></dt>
44 * <dd>Specify a non-default storage location for special output
45 * (e.g., AOD trees). &lt;url&gt; should be a valid XRootd
46 * server URI accessible to the slaves - e.g.,
47 * <tt>root://lxplus.cern.ch:10930//tmp</tt>.</dd>
48 * <dt><tt>mode=[default,rec,sim,train,custom]</tt></dt>
49 * <dd>Set the AliROOT mode. If not specified <tt>default</tt>
50 * is assumed</tt>. See also CreateAliROOTPar</dd>
51 * <dt><tt>par</tt></dt>
52 * <dd> Use PAR files</dd>
53 * <dt><tt>runs=[list or file]</tt></dt>
54 * <dd>Comma separated list of run numbers, or file(s) containing
55 * run numbers</dd>
56 * <dt><tt>oper=[FULL,TERMINATE,SUBMIT,OFFLINE,TEST]</tt></dt>
57 * <dd>How to run the analysis</dd>
58 * <dt><tt>split=&lt;N&gt;</tt></dt>
59 * <dd>Maximum number of files per split</dd>
60 * <dt><tt>merge=&lt;N&gt;</tt></dt>
61 * <dd>Maximum number of files per merger</dd>
62 * <dt><tt>mc</tt></dt>
63 * <dd>Scan also for MC files (<tt>galice.root</tt>,
64 * <tt>Kinematics.root</tt>, and <tt>TrackRefs.root</tt>) when
65 * scanning &lt;datadir&gt;</dd>
66 * <dt><tt>pattern=&lt;GLOB&gt;</tt></dt>
67 * <dd>Shell glob pattern that files must check when scanning
68 * &lt;datadir&gt;</dd>
69 * </dl>
70 * </dd>
71 * </dl>
72 *
73 * @ingroup pwglf_forward_trains_helper
74 */
75struct GridHelper : public PluginHelper
76{
77 /**
78 * Constructor
79 *
80 * @param url Url
81 * @param opts Options
82 */
83 GridHelper(const TUrl& url, Int_t verbose)
84 : PluginHelper(url, verbose)
85 {
86 fOptions.Add("oper", "FULL|TERMINATE|SUBMIT", "Analysis operation", "FULL");
87 fOptions.Add("split", "N", "Maximum number of files before split", "max");
88 fOptions.Add("merge", "N", "Maximum number of files for merge", "max");
89 fOptions.Add("run", "RUNS", "Range, list, and/or file of runs", "");
90 fOptions.Add("pattern","GLOB", "File/directory name pattern", "");
91 fOptions.Add("mc", "Assume MC input");
92 }
93 virtual ~GridHelper() {}
94 /**
95 * Get the mode identifier
96 *
97 * @return Always kProof
98 */
99 virtual UShort_t Mode() const { return kGrid; }
100 /**
101 * Get the mode string used for AliAnalysisManager::StartAnalysis
102 */
103 virtual const char* ModeString() const { return "grid"; }
104 /**
105 * Set-up done before task set-ups
106 *
107 * @return true on success
108 */
109 virtual UShort_t Operation() const
110 {
111 if (!fOptions.Has("oper")) return kFull;
112 const TString& oper = fOptions.Get("oper");
113 if (oper.EqualTo("FULL", TString::kIgnoreCase)) return kFull;
114 else if (oper.EqualTo("OFFLINE", TString::kIgnoreCase)) return kOffline;
115 else if (oper.EqualTo("SUBMIT", TString::kIgnoreCase)) return kSubmit;
116 else if (oper.EqualTo("TERMINATE", TString::kIgnoreCase)) return kTerminate;
117 else if (oper.EqualTo("TEST", TString::kIgnoreCase)) return kTest;
118 return kFull;
119 }
120 /**
121 * Read run numbers
122 *
123 * @return Number of registered runs
124 */
125 virtual Int_t RegisterRuns()
126 {
127 if (!fOptions.Find("run")) {
128 Error("GridHelper::RegisterRuns", "No runs specified");
129 return -1;
130 }
131 Int_t nRuns = 0;
132 TString runs = fOptions.Get("runs");
133 TObjArray* tokens = runs.Tokenize(",");
134 TObjString* part = 0;
135 TIter next(tokens);
136 Bool_t range = false;
137 Bool_t individual = false;
138 while ((part = static_cast<TObjString*>(next()))) {
139 TString& s = part->String();
140 if (s.Contains("-")) { // Run range
141 if (range) {
142 Warning("GridHelper::RegisterRuns", "Run range already specified, "
143 "ignoring %s", s.Data());
144 continue;
145 }
146 if (individual) {
147 Warning("GridHelper::RegisterRuns",
148 "Run ranges and individual run specs do not mix, "
149 "ignoring %s", s.Data());
150 continue;
151 }
152 TObjArray* ranges = s.Tokenize("-");
153 if (ranges->GetEntriesFast() > 2) {
154 Warning("GridHelper::RegisterRuns", "Invalid run range: %s",
155 s.Data());
156 ranges->Delete();
157 continue;
158 }
159 Int_t first = static_cast<TObjString*>(ranges->At(0))->String().Atoi();
160 Int_t last = static_cast<TObjString*>(ranges->At(1))->String().Atoi();
161 nRuns = last-first+1;
162 fHandler->SetRunRange(first, last);
163 ranges->Delete();
164 range = true;
165 continue;
166 }
167 if (s.IsDigit()) { // single run
168 if (range) {
169 Warning("GridHelper::RegisterRuns",
170 "Run ranges and individual run specs do not mix, "
171 "ignoring %s", s.Data());
172 continue;
173 }
174 fHandler->AddRunNumber(s.Data());
175 nRuns++;
176 individual = true;
177 continue;
178 }
179 if (range) {
180 Warning("GridHelper::RegisterRuns", "Run ranges and list file "
181 "do not mix, ignoring %s", s.Data());
182 continue;
183 }
184
185 // We assume this part is a file
186 std::ifstream in(s.Data());
187 if (!in) {
188 Warning("GridHelper::RegisterRuns", "Failed to open %s", s.Data());
189 continue;
190 }
191 while (!in.eof()) {
192 Int_t r;
193 in >> r;
194 fHandler->AddRunNumber(r);
195 nRuns++;
196 Char_t c;
197 in >> c;
198 if (in.bad()) break;
199 }
200 individual = true;
201 in.close();
202 }
203 return nRuns;
204 }
205 /**
206 * Executed before setting up tasks
207 *
208 * @return true on success
209 */
210 virtual Bool_t PreSetup()
211 {
212 if (!PluginHelper::PreSetup()) return false;
213
214 // --- Open a connection to the grid -----------------------------
215 TGrid::Connect(Form("%s://", fUrl.GetProtocol()));
216 if (!gGrid || !gGrid->IsConnected()) {
217 Error("GridHelper::PreSetup", "Failed to connect to AliEN");
218 return false;
219 }
220
221 return true;
222 }
223 /**
224 * Set-up done after the task set-ups
225 *
226 * @return true on success
227 */
228 virtual Bool_t PostSetup()
229 {
230 if (!PluginHelper::PostSetup()) return false;
231
232 AliAnalysisManager* mgr = AliAnalysisManager::GetAnalysisManager();
233 TString name(mgr->GetName());
234
235 // --- Set the operation to do (TEST, SUBMIT, TERMINATE, FULL) ---
236 TString operation("FULL");
237 if (fOptions.Has("oper")) operation = fOptions.Get("oper");
238 fHandler->SetRunMode(operation);
239
240 // --- Do not test copying ---------------------------------------
241 fHandler->SetCheckCopy(false);
242
243 // --- Set output to be per run ----------------------------------
244 fHandler->SetOutputToRunNo(true);
245
246 // --- Set the job tag -------------------------------------------
247 fHandler->SetJobTag(name);
248
249 // --- Set number of test files - used in test mode only ---------
250 fHandler->SetNtestFiles(1);
251
252 // --- Set the Time-To-Live --------------------------------------
253 fHandler->SetTTL(70000);
254
255 // --- Re-submit failed jobs as long as the ratio of failed jobs -
256 // --- is this percentage.
257 fHandler->SetMasterResubmitThreshold(95);
258
259 // --- Set the input format --------------------------------------
260 fHandler->SetInputFormat("xml-single");
261
262 // --- Set names of generated files ------------------------------
263 fHandler->SetAnalysisMacro(Form("%s.C", name.Data()));
264 fHandler->SetJDLName(Form("%s.jdl", name.Data()));
265 fHandler->SetExecutable(Form("%s.sh", name.Data()));
266
267 // ---- Set the job price !? -------------------------------------
268 fHandler->SetPrice(1);
269
270 // --- Set whether to merge via JDL ------------------------------
271 fHandler->SetMergeViaJDL(true);
272
273 // --- Fast read otion -------------------------------------------
274 fHandler->SetFastReadOption(false);
275
276 // --- Whether to overwrite existing output ----------------------
277 fHandler->SetOverwriteMode(true);
278
279 // --- Set the executable binary name and options ----------------
280 fHandler->SetExecutableCommand("aliroot -b -q -x");
281
282 // --- Split by storage element - must be lower case! ------------
283 fHandler->SetSplitMode("se");
284
285 // --- How much to split -----------------------------------------
286 if (fOptions.Has("split")) {
287 if (!fOptions.Get("split").EqualTo("max")) {
288 fHandler->SetSplitMaxInputFileNumber(fOptions.Get("split").Atoi());
289 }
290 }
291
292 // --- Enable default outputs ------------------------------------
293 fHandler->SetDefaultOutputs(true);
294
295 // --- Merge parameters ------------------------------------------
296 if (fOptions.Has("merge")) {
297 if (!fOptions.Get("merge").EqualTo("max")) {
298 fHandler->SetMaxMergeFiles(fOptions.Get("merge").Atoi());
299 }
300 }
301 fHandler->SetMergeExcludes("AliAOD.root *EventStat*.root "
302 "*event_stat*.root");
303
304 // --- Keep log files ------------------------------------------
305 fHandler->SetKeepLogs();
306
307 // --- Set the working directory to be the trains name (with -----
308 // --- special characters replaced by '_' and the date appended),
309 // --- and also set the output directory (relative to working
310 // --- directory)
311 fHandler->SetGridWorkingDir(name.Data());
312 fHandler->SetGridOutputDir("output");
313 fHandler->SetGridDataDir(fUrl.GetFile());
314
315 // --- Get the tree name and set the file pattern ----------------
316 TString pattern;
317 if (fOptions.Has("pattern")) pattern = fOptions.Get("pattern");
318 else {
319 TString treeName(fUrl.GetAnchor());
320 if (treeName.IsNull()) {
321 Warning("GridHelper::PreSetup", "No tree name specified, assuming T");
322 treeName = "T";
323 }
324 if (treeName.EqualTo("esdTree")) pattern = "AliESD";
325 else if (treeName.EqualTo("aodTree")) pattern = "AliAOD";
326 }
327 fHandler->SetDataPattern(pattern);
328 fHandler->SetRunPrefix(mgr->GetMCtruthEventHandler() ? "" : "000");
329
330 // --- Add the run numbers ---------------------------------------
331 Int_t nRun = RegisterRuns();
332
333 // --- Set number of runs per master - set to one to per run -----
334 fHandler->SetNrunsPerMaster(fOptions.Has("run-merge") ? 1 : nRun+1);
335
336 // --- Loop over defined containers in the analysis manager, and -
337 // --- declare these as outputs
338 TString listOfAODs = "";
339 TString listOfHists = "";
340
341 AliAnalysisDataContainer* cont = 0;
342 TIter nextCont(mgr->GetOutputs());
343 while ((cont = static_cast<AliAnalysisDataContainer*>(nextCont()))) {
344 TString outName(cont->GetFileName());
345 TString& list = (outName == "default" ? listOfAODs : listOfHists);
346 if (outName == "default") {
347 if (!mgr->GetOutputEventHandler()) continue;
348
349 outName = mgr->GetOutputEventHandler()->GetOutputFileName();
350 }
351 if (list.Contains(outName)) continue;
352 if (!list.IsNull()) list.Append(",");
353 list.Append(outName);
354 }
355 if (!mgr->GetExtraFiles().IsNull()) {
356 if (!listOfAODs.IsNull()) listOfAODs.Append("+");
357 TString extra = mgr->GetExtraFiles();
358 extra.ReplaceAll(" ", ",");
359 listOfAODs.Append(extra);
360 }
361
362 Int_t nReplica = 2;
363 TString outArchive = Form("stderr, stdout@disk=%d", nReplica);
364 if (!listOfHists.IsNull())
365 outArchive.Append(Form(" hist_archive.zip:%s@disk=%d",
366 listOfHists.Data(), nReplica));
367 if (!listOfAODs.IsNull())
368 outArchive.Append(Form(" aod_archive.zip:%s@disk=%d",
369 listOfAODs.Data(), nReplica));
370 if (listOfAODs.IsNull() && listOfHists.IsNull())
371 Fatal("PostSetup", "No outputs defined");
372
373 return true;
374 };
375 /**
376 * Start the analysis
377 *
378 * @param nEvents Number of events to analyse
379 *
380 * @return The return value of AliAnalysisManager::StartAnalysis
381 */
382 virtual Long64_t Run(Long64_t nEvents=-1)
383 {
384 AliAnalysisManager* mgr = AliAnalysisManager::GetAnalysisManager();
385
386 return mgr->StartAnalysis("grid", nEvents);
387 }
388 /**
389 * Link an auxilary file to working directory
390 *
391 * @param name Name of the file
392 *
393 * @return true on success
394 */
395 virtual Bool_t AuxFile(const TString& name)
396 {
397 if (!Helper::AuxFile(name)) return false;
398 // We need to add this file as an additional 'library', so that the
399 // file is uploaded to the users Grid working directory.
400 fHandler->AddAdditionalLibrary(gSystem->BaseName(name.Data()));
401 return true;
402 }
403 /**
404 * Get the output (directory)
405 *
406 */
407 virtual TString OutputPath() const
408 {
409 TString ret;
410 if (!fHandler) {
411 Warning("GridHelper::OutputLocation", "No AliEn handler");
412 return ret;
413 }
414 ret = fHandler->GetGridOutputDir();
415 if (ret.BeginsWith("/")) return ret;
416
417 AliAnalysisManager* mgr = AliAnalysisManager::GetAnalysisManager();
418 if (!mgr) {
419 Warning("GridHelper::OutputLocation", "No analysis manager");
420 return ret;
421 }
422 ret.Prepend(Form("%s/", mgr->GetName()));
423 if (gGrid)
424 ret.Prepend(Form("%s/", gGrid->GetHomeDirectory()));
425
426 return ret;
427 }
428 /**
429 * @return URL help string
430 */
431 virtual const Char_t* UrlHelp() const
432 {
433 return "alien:///<datadir>[?<options>][#<treeName>]";
434 }
435 /**
436 * @return Short description
437 */
438 virtual const char* Desc() const { return "AliEn"; }
439};
440#endif
441//
442// EOF
443//