]> git.uio.no Git - u/mrichter/AliRoot.git/blob - PWGLF/FORWARD/trains/ChainBuilder.C
Added ignores
[u/mrichter/AliRoot.git] / PWGLF / FORWARD / trains / ChainBuilder.C
1 /**
2  * @file   ChainBuilder.C
3  * @author Christian Holm Christensen <cholm@master.hehi.nbi.dk>
4  * @date   Tue Oct 16 17:54:26 2012
5  * 
6  * @brief  Build a chain
7  * 
8  * @ingroup pwglf_forward_trains_util
9  */
10
11 #ifndef CHAINBUILDER_C
12 #define CHAINBUILDER_C
13 #ifndef __CINT__
14 # include <TString.h>
15 # include <TChain.h>
16 # include <TSystemDirectory.h>
17 # include <TSystem.h>
18 # include <TFile.h>
19 # include <TList.h>
20 # include <TError.h>
21 # include <TROOT.h>
22 # include <TGridCollection.h>
23 # include <TFileCollection.h>
24 # include <THashList.h>
25 # include <TKey.h>
26 # include <fstream>
27 #else 
28 class TString;
29 class TChain;
30 class TSystemDirectory;
31 #endif
32
33 // ===================================================================
34 /**
35  * Build a chain 
36  *
37  * @ingroup pwglf_forward_trains_util
38  */
39 struct ChainBuilder 
40 {
41   enum { 
42     kInvalid,
43     kDirectory, 
44     kXML, 
45     kAscii, 
46     kROOT
47   };
48   //------------------------------------------------------------------
49   static UShort_t CheckSource(TString& src)
50   {
51     // Local copy 
52     TString tmp(src);
53
54     // --- Normalize the path ----------------------------------------
55     if (tmp == ".") tmp = "";
56     if (!tmp.BeginsWith("/")) tmp.Prepend("../");
57     if (gSystem->ExpandPathName(tmp)) { 
58       Error("ChainBuilder::CheckSource", 
59             "Failed to expand source %s", src.Data());
60       return kInvalid;
61     }
62
63     // --- Stat the file ---------------------------------------------
64     FileStat_t stat; 
65     if (gSystem->GetPathInfo(tmp, stat)) return kInvalid;
66     src = tmp;
67
68     // --- Check if directory or file --------------------------------
69     if (R_ISDIR(stat.fMode)) return kDirectory;
70
71     // --- check file type -------------------------------------------
72     TString type(gSystem->GetFromPipe(Form("file -b %s", src.Data())));
73     if      (type.Contains("ROOT"))  return kROOT;
74     else if (type.Contains("XML"))   return kXML;
75     else if (type.Contains("ASCII")) return kAscii;
76
77     Error("ChainBuilder::CheckSource", 
78           "Do not now how to process %s of type %s", 
79           src.Data(), type.Data());
80     return kInvalid;
81   }
82   //------------------------------------------------------------------
83   /** 
84    * Create the chain.  User is owner. 
85    * 
86    * @return Null in case of problems, chain otherwise 
87    */
88   static TChain* Create(const TString& src, 
89                         const TString& treeName, 
90                         const TString& pattern, 
91                         Bool_t         mc, 
92                         Bool_t         recursive)
93   {
94     TString tmp(src);
95     UShort_t type = CheckSource(tmp);
96
97     return Create(type, tmp, treeName, pattern, mc, recursive);
98   }
99   //------------------------------------------------------------------
100   /** 
101    * Create the chain.  User is owner. 
102    * 
103    * @return Null in case of problems, chain otherwise 
104    */
105   static TChain* Create(UShort_t       type, 
106                         const TString& src, 
107                         const TString& treeName, 
108                         const TString& pattern, 
109                         Bool_t         mc, 
110                         Bool_t         recursive)
111   {
112     // --- check input -----------------------------------------------
113     if (type == kInvalid) {
114       Error("ChainBuilder::Create", "Source %s isn't a file or directory",
115             src.Data());
116       return 0;
117     }
118     TString tN(treeName);
119     if (tN.IsNull()) 
120       Warning("ChainBuilder::Create", "No tree name specified, assuming T");
121
122     TString pat(pattern);
123     if (pat.IsNull()) {
124       if      (tN.EqualTo("esdTree")) pat = "AliESD";
125       else if (tN.EqualTo("aodTree")) pat = "AliAOD";
126     }
127       
128     // --- Create output ---------------------------------------------
129     TChain* chain = new TChain(tN);
130
131     // --- execute based on type 
132     Bool_t ret = true;
133     switch (type) { 
134     case kROOT:      ret = CreateFromFile(chain, src); break;
135     case kXML:       ret = CreateFromXML(chain,  src); break;
136     case kAscii:     ret = CreateFromList(chain, src); break;
137     case kDirectory: ret = CreateFromDirectory(chain, src, 
138                                                pat, mc, 
139                                                recursive); break;
140     default:         ret = false;
141     }
142
143     // --- Clean-up --------------------------------------------------
144     if (chain->GetListOfFiles()->GetEntries() <= 0) ret = false;
145     if (!ret) { 
146       delete chain;
147       chain = 0;
148     }
149     return chain;
150   }
151   //------------------------------------------------------------------
152   /** 
153    * Create a chain consiting of a single file 
154    * 
155    * @param fn File name. 
156    * 
157    * @return Chain or null
158    */
159   static Bool_t CreateFromFile(TChain* chain, const TString& src)
160   {
161     // Info("CreateFromFile", "Making from single file %s", src.Data());
162     if (!CheckFile(src, chain)) return false;
163     return true;
164   }
165   //------------------------------------------------------------------
166   /** 
167    * Create a chain from an XML containing an collection
168    * 
169    * @return Newly allocated chain or null
170    */
171   static Bool_t CreateFromXML(TChain* chain, const TString& src) 
172   {
173     Long_t ret = gROOT->ProcessLine(Form("TAlienCollection(\"%s\")", 
174                                          src.Data()));
175     if (!ret) { 
176       Error("ChainBuilder::CreateFromXML", 
177             "Cannot create AliEn collection from XML file %s", src.Data());
178       return false;
179     }
180     
181     TGridCollection* collection = reinterpret_cast<TGridCollection*>(ret);
182     if (!collection) { 
183       Error("ChainBuilder::CreateFromXML", 
184             "Cannot create AliEn collection from XML file %s", src.Data());
185       return false;
186     }
187     
188     collection->Reset();
189     while (collection->Next()) chain->Add(collection->GetTURL(""));
190     
191     return true;
192   }
193   //------------------------------------------------------------------
194   /** 
195    * Create a chain from a file containing a list of files
196    * 
197    * @return Newly allocated chain or null
198    */
199   static Bool_t CreateFromList(TChain* chain, const TString& src) 
200   {
201     std::ifstream in(src.Data());
202     if (!in) { 
203       Error("ChainBuilder::CreateFromList", 
204             "Failed to open list %s", src.Data());
205       return false;
206     }
207     
208     while (in.good()) { 
209       TString line;
210       line.ReadToDelim(in);
211       TString l(line.Strip(TString::kBoth));
212       if (l.IsWhitespace() || l.BeginsWith("#")) continue;
213       
214       if (!CheckFile(l, chain))
215         Warning("ChainBuilder::CreateFromList", 
216                 "Failed to add %s to chain", l.Data());
217     }
218     return true;
219   }
220   //------------------------------------------------------------------
221   /** 
222    * Make a chain from a base directory, pattern, and treename -
223    * possibly recursively
224    * 
225    * @return true on success 
226    */
227   static Bool_t CreateFromDirectory(TChain* chain, 
228                                     const TString& src, 
229                                     const TString& pattern, 
230                                     Bool_t         mc, 
231                                     Bool_t         recursive) 
232   {
233     // Info("", "Scanning src=%s, pattern=%s, mc=%d recursive=%d", 
234     //       src.Data(), pattern.Data(), mc, recursive);
235     // Save current directory 
236     TString savdir(gSystem->WorkingDirectory());
237     TSystemDirectory d(gSystem->BaseName(src.Data()), src.Data());
238     // Info("", "Will scan %s", d.GetTitle());
239     if (!ScanDirectory(chain, &d, pattern, mc, recursive)) return false;
240     // Go back to the saved directory 
241     gSystem->ChangeDirectory(savdir);
242     
243     return true;
244   }
245   //------------------------------------------------------------------
246   /** 
247    * Check if we can add a file to the chain 
248    * 
249    * @param path   Full path to file 
250    * @param chain  Chain 
251    * 
252    * @return true on success, false otherwise
253    */
254   static Bool_t CheckFile(const TString& path, TChain* chain)
255   {
256     // Info("", "Checking %s", path.Data());
257     gSystem->RedirectOutput("/dev/null", "w");
258     TFile* test = TFile::Open(path, "READ");
259     gSystem->RedirectOutput(0);
260     if (!test) { 
261       Warning("ChainBuilder::CheckFile", "Failed to open %s", path.Data());
262       return false;
263     }
264
265     TObject* o = test->Get(chain->GetName());
266     if (!o) {
267       // Let's try to find a TFileCollection 
268       TList* l = test->GetListOfKeys();
269       TIter next(l);
270       TKey* k = 0;
271       Bool_t ok = false;
272       while ((k = static_cast<TKey*>(next()))) {
273         TString cl(k->GetClassName());
274         if (!cl.EqualTo("TFileCollection")) continue;
275         TFileCollection* fc = dynamic_cast<TFileCollection*>(k->ReadObj());
276         Info("", "Adding file collection");
277         chain->AddFileInfoList(fc->GetList());
278         ok = true;
279       }
280       if (ok) { 
281         test->Close();
282         return true;
283       }
284     }
285     else if (dynamic_cast<TTree*>(o)) {
286       test->Close();
287       chain->Add(path);
288       return true;
289     }
290     
291     Warning("ChainBuilder::CheckFile", 
292             "The file %s does not contain the tree %s or a file collection", 
293             path.Data(), chain->GetName());
294     
295     return false;
296   }
297   //------------------------------------------------------------------
298   /** 
299    * Scan directory @a dir (possibly recursive) for tree files to add
300    * to the chain.    This does not follow sym-links
301    * 
302    * @param dir        Directory to scan
303    * @param chain      Chain to add to
304    *
305    * @return true if any files where added 
306    */
307   static Bool_t ScanDirectory(TChain*           chain, 
308                               TSystemDirectory* dir,
309                               const TString&    pattern,
310                               Bool_t            mc,
311                               Bool_t            recursive)
312   {
313     // Assume failure 
314     Bool_t ret = false;
315
316     // Get list of files, and go back to old working directory
317     TString oldDir(gSystem->WorkingDirectory());
318     TList*  files = dir->GetListOfFiles();
319     if (!gSystem->ChangeDirectory(oldDir)) { 
320       Error("ChainBuilder::ScanDirectory", "Failed to go back to %s", 
321             oldDir.Data());
322       return false;
323     }
324     if (!files) {
325       Warning("ChainBuilder::ScanDirectory", "No files");
326       return false;
327     }
328
329     TList toAdd;
330     toAdd.SetOwner();
331     Bool_t hasGAlice = (!(mc) ? true : false);
332     Bool_t hasKine   = (!(mc) ? true : false);
333     Bool_t hasTrRef  = (!(mc) ? true : false);
334     
335     // Sort list of files and check if we should add it 
336     files->Sort();
337     TIter next(files);
338     TSystemFile* file = 0;
339     while ((file = static_cast<TSystemFile*>(next()))) {
340       TString name(file->GetName());
341       TString title(file->GetTitle());
342       TString full(gSystem->ConcatFileName(file->GetTitle(), name.Data()));
343       // Info("", "Got file %s", full.Data());
344       if (file->IsA()->InheritsFrom(TSystemDirectory::Class())) full = title;
345       // Ignore special links 
346       if (name == "." || name == "..") { 
347         // Info("ChainBuilder::ScanDirectory", "Ignoring %s", name.Data());
348         continue;
349       }
350       // Info("", "Got file %s", full.Data());
351
352       FileStat_t fs;
353       if (gSystem->GetPathInfo(full.Data(), fs)) {
354         Warning("ChainBuilder::ScanDirectory", "Cannot stat %s (%s)", 
355                 full.Data(), gSystem->WorkingDirectory());
356         continue;
357       }
358       // Check if this is a directory 
359       if (file->IsDirectory(full)) { 
360         // Info("", "Recursive scan of %s", full.Data());
361         if (recursive) {
362           // if (title[0] == '/') 
363           TSystemDirectory* d = new TSystemDirectory(file->GetName(),
364                                                      full.Data());
365           if (ScanDirectory(chain, d, pattern, mc, recursive)) 
366             ret = true;
367           delete d;
368         }
369         continue;
370       }
371     
372       // If this is not a root file, ignore 
373       if (!name.EndsWith(".root")) {
374         // Info("ScanDirectory", "File %s does not end in .root", name.Data());
375         continue;
376       }
377
378       // If this file does not contain AliESDs, ignore 
379       if (!name.Contains(pattern)) { 
380         // Info("ChainBuilder::ScanDirectory", "%s does not match pattern %s", 
381         //      name.Data(), pattern.Data());
382         if (mc) {
383           if (name.CompareTo("galice.root") == 0)     hasGAlice = true;
384           if (name.CompareTo("Kinematics.root") == 0) hasKine   = true;
385           if (name.CompareTo("TrackRefs.root")  == 0) hasTrRef = true;
386         }
387         continue;
388       }
389     
390       // Add 
391       // Info("ChainBuilder::ScanDirectory", "Adding %s", full.Data());
392       toAdd.Add(new TObjString(full));
393     }
394
395     if (mc && toAdd.GetEntries() > 0 && 
396         (!hasGAlice || !hasKine || !hasTrRef)) { 
397       Warning("ChainBuilder::ScanDirectory", 
398               "one or more of {galice,Kinematics,TrackRefs}.root missing from "
399               "%s, not adding anything from this directory", 
400               dir->GetTitle());
401       toAdd.Delete();
402     }
403
404     TIter nextAdd(&toAdd);
405     TObjString* s = 0;
406     Int_t added = 0;
407     while ((s = static_cast<TObjString*>(nextAdd()))) {
408       // Info("ChainBuilder::ScanDirectory", 
409       //      "Adding %s", s->GetString().Data());
410       TString fn = s->GetString();
411       if (!CheckFile(fn, chain)) continue;
412
413       added++;
414     }
415     if (added > 0) ret = true;
416
417     gSystem->ChangeDirectory(oldDir);
418     return ret;
419   }
420 };
421 #endif