ROOT logo
/**
 * @file   MakeChain.C
 * @author Christian Holm Christensen <cholm@dalsgaard.hehi.nbi.dk>
 * @date   Tue Jul 12 10:20:07 2011
 * 
 * @brief  Script to generate a chain of files 
 * 
 * @ingroup pwglf_forward_scripts
 */
/** 
 * Check if a path points to a file 
 * 
 * @param path Path
 * 
 * @return True if the path points to a regular file 
 *
 * @ingroup pwglf_forward_scripts
 */
Bool_t
IsFile(const char* path)
{
  Long_t id;
  Long_t size;
  Long_t flags;
  Long_t modtime;
  gSystem->GetPathInfo(path, &id, &size, &flags, &modtime);
  return !((flags & 0x2) == 0x2);
}

/** 
 * Test if we can open a file 
 * 
 * @param name    Name of file 
 * @param pattern Pattern to check against 
 * 
 * @return True on success
 */
Bool_t
TestFile(const TString& name, const char* pattern=0)
{
  // If this is not a root file, ignore 
  if (!name.EndsWith(".root")) return false;

  // If this file does not contain the pattern, ignore 
  if (pattern && pattern[0] != '\0' && !name.Contains(pattern)) return false;
  if (name.Contains("friends")) return false;
    
  Bool_t ret  = true;
  TFile* test = TFile::Open(name.Data(), "READ");
  if (!test || test->IsZombie()) { 
    Warning("TestFile", "Failed to open file %s", name.Data());
    ret = false;
  }
  else 
    test->Close();
  return ret;
}

/** 
 * Scan a directory (optionally recursive) for data files to add to
 * the chain.  Only ROOT files, and files which name contain the
 * passed pattern are considered.
 * 
 * @param dir        Directory to scan
 * @param chain      Chain to add data to 
 * @param pattern    Pattern that the file name must contain
 * @param recursive  Whether to scan recursively 
 *
 * @ingroup pwglf_forward_scripts
 */
void
ScanDirectory(TSystemDirectory* dir, TChain* chain, 
	      const char* pattern, bool recursive)
{
  // Get list of files, and go back to old working directory
  TString oldDir(gSystem->WorkingDirectory());
  TList* files = dir->GetListOfFiles();
  gSystem->ChangeDirectory(oldDir);

  // Sort list of files and check if we should add it 
  files->Sort();
  TIter next(files);
  TSystemFile* file = 0;
  while ((file = static_cast<TSystemFile*>(next()))) {
    TString name(file->GetName());
    
    // Ignore special links 
    if (name == "." || name == "..") continue;

    // Check if this is a directory 
    if (file->IsDirectory()) { 
      if (recursive) 
	ScanDirectory(static_cast<TSystemDirectory*>(file),chain,
		      pattern,recursive);
      continue;
    }
    
    // Get the path 
    TString data(Form("%s/%s", file->GetTitle(), name.Data()));

    // Check the fuile 
    if (!TestFile(data, pattern)) continue;
    chain->Add(data);
  }
}
/** 
 * Scan an input list of files 
 * 
 * @param chain    Chain to add to 
 * @param path     File with list of files to add 
 * @param treeName Name of tree in files 
 * 
 * @return true on success 
 */
Bool_t 
ScanInputList(TChain* chain, const TString& path, const char* treeName=0)
{
  std::ifstream in(path.Data()); 
  if (!in) { 
    Error("ScanInputList", "Failed to open input list %s", path.Data());
    return false;
  }
  TString line;
  while (in.good()) { 
    line.ReadLine(in); // Skip white-space
    if (line.IsNull()) break; // Nothing -> EOF
    if (line[0] == '#') continue; // Ignore comment lines 
    if (!TestFile(line, 0)) continue; 
    chain->Add(line);
  }
  in.close();
  return true;
}
    
  
/** 
 * Make a chain of specified data 
 * 
 * @param what       What data to chain.  Possible values are 
 *                   - ESD Event summary data (AliESD)
 *                   - AOD Analysis object data (AliAOD)
 *                   - MC  Simulation data (galice)
 * @param datadir    Data directory to scan 
 * @param recursive  Whether to recurse into sub-directories 
 * 
 * @return Pointer to newly create chain, or null
 *
 * @ingroup pwglf_forward_scripts
 */
TChain*
MakeChain(const char* what, const char* datadir, bool recursive=false)
{
  TString w(what);
  w.ToUpper();
  const char* treeName = 0;
  const char* pattern  = 0;
  if      (w.Contains("ESD")) { treeName = "esdTree"; pattern = "AliESD"; }
  else if (w.Contains("AOD")) { treeName = "aodTree"; pattern = "AliAOD"; }
  else if (w.Contains("MC"))  { treeName = "TE";      pattern = "galice"; }
  else {
    Error("MakeChain", "Unknown mode '%s' (not one of ESD,AOD, or MC)", what);
    return 0;
  }
    
  // --- Our data chain ----------------------------------------------
  TChain* chain = new TChain(treeName);

  // --- Get list of files --------------------------------------------
  // Open source directory, and make sure we go back to were we were 
  TString oldDir(gSystem->WorkingDirectory());
  TString path(gSystem->ExpandPathName(datadir));
  if (!IsFile(path)) {
    TSystemDirectory d(datadir, datadir);
    ScanDirectory(&d, chain, pattern, recursive);
  }
  else if (path.EndsWith(".root")) { 
    if (TestFile(path, pattern)) chain->Add(path);
  }
  else { 
    // Input seems to be a list - parse it 
    ScanInputList(chain, path);
  }
  
  // Make sure we do not make an empty chain 
  if (chain->GetListOfFiles()->GetEntries() <= 0) { 
    Warning("MakeChain", "Chain %s is empty for input %s", 
	    treeName, datadir);
    delete chain;
    chain = 0;
  }
  return chain;
}
//
// EOF
//
 MakeChain.C:1
 MakeChain.C:2
 MakeChain.C:3
 MakeChain.C:4
 MakeChain.C:5
 MakeChain.C:6
 MakeChain.C:7
 MakeChain.C:8
 MakeChain.C:9
 MakeChain.C:10
 MakeChain.C:11
 MakeChain.C:12
 MakeChain.C:13
 MakeChain.C:14
 MakeChain.C:15
 MakeChain.C:16
 MakeChain.C:17
 MakeChain.C:18
 MakeChain.C:19
 MakeChain.C:20
 MakeChain.C:21
 MakeChain.C:22
 MakeChain.C:23
 MakeChain.C:24
 MakeChain.C:25
 MakeChain.C:26
 MakeChain.C:27
 MakeChain.C:28
 MakeChain.C:29
 MakeChain.C:30
 MakeChain.C:31
 MakeChain.C:32
 MakeChain.C:33
 MakeChain.C:34
 MakeChain.C:35
 MakeChain.C:36
 MakeChain.C:37
 MakeChain.C:38
 MakeChain.C:39
 MakeChain.C:40
 MakeChain.C:41
 MakeChain.C:42
 MakeChain.C:43
 MakeChain.C:44
 MakeChain.C:45
 MakeChain.C:46
 MakeChain.C:47
 MakeChain.C:48
 MakeChain.C:49
 MakeChain.C:50
 MakeChain.C:51
 MakeChain.C:52
 MakeChain.C:53
 MakeChain.C:54
 MakeChain.C:55
 MakeChain.C:56
 MakeChain.C:57
 MakeChain.C:58
 MakeChain.C:59
 MakeChain.C:60
 MakeChain.C:61
 MakeChain.C:62
 MakeChain.C:63
 MakeChain.C:64
 MakeChain.C:65
 MakeChain.C:66
 MakeChain.C:67
 MakeChain.C:68
 MakeChain.C:69
 MakeChain.C:70
 MakeChain.C:71
 MakeChain.C:72
 MakeChain.C:73
 MakeChain.C:74
 MakeChain.C:75
 MakeChain.C:76
 MakeChain.C:77
 MakeChain.C:78
 MakeChain.C:79
 MakeChain.C:80
 MakeChain.C:81
 MakeChain.C:82
 MakeChain.C:83
 MakeChain.C:84
 MakeChain.C:85
 MakeChain.C:86
 MakeChain.C:87
 MakeChain.C:88
 MakeChain.C:89
 MakeChain.C:90
 MakeChain.C:91
 MakeChain.C:92
 MakeChain.C:93
 MakeChain.C:94
 MakeChain.C:95
 MakeChain.C:96
 MakeChain.C:97
 MakeChain.C:98
 MakeChain.C:99
 MakeChain.C:100
 MakeChain.C:101
 MakeChain.C:102
 MakeChain.C:103
 MakeChain.C:104
 MakeChain.C:105
 MakeChain.C:106
 MakeChain.C:107
 MakeChain.C:108
 MakeChain.C:109
 MakeChain.C:110
 MakeChain.C:111
 MakeChain.C:112
 MakeChain.C:113
 MakeChain.C:114
 MakeChain.C:115
 MakeChain.C:116
 MakeChain.C:117
 MakeChain.C:118
 MakeChain.C:119
 MakeChain.C:120
 MakeChain.C:121
 MakeChain.C:122
 MakeChain.C:123
 MakeChain.C:124
 MakeChain.C:125
 MakeChain.C:126
 MakeChain.C:127
 MakeChain.C:128
 MakeChain.C:129
 MakeChain.C:130
 MakeChain.C:131
 MakeChain.C:132
 MakeChain.C:133
 MakeChain.C:134
 MakeChain.C:135
 MakeChain.C:136
 MakeChain.C:137
 MakeChain.C:138
 MakeChain.C:139
 MakeChain.C:140
 MakeChain.C:141
 MakeChain.C:142
 MakeChain.C:143
 MakeChain.C:144
 MakeChain.C:145
 MakeChain.C:146
 MakeChain.C:147
 MakeChain.C:148
 MakeChain.C:149
 MakeChain.C:150
 MakeChain.C:151
 MakeChain.C:152
 MakeChain.C:153
 MakeChain.C:154
 MakeChain.C:155
 MakeChain.C:156
 MakeChain.C:157
 MakeChain.C:158
 MakeChain.C:159
 MakeChain.C:160
 MakeChain.C:161
 MakeChain.C:162
 MakeChain.C:163
 MakeChain.C:164
 MakeChain.C:165
 MakeChain.C:166
 MakeChain.C:167
 MakeChain.C:168
 MakeChain.C:169
 MakeChain.C:170
 MakeChain.C:171
 MakeChain.C:172
 MakeChain.C:173
 MakeChain.C:174
 MakeChain.C:175
 MakeChain.C:176
 MakeChain.C:177
 MakeChain.C:178
 MakeChain.C:179
 MakeChain.C:180
 MakeChain.C:181
 MakeChain.C:182
 MakeChain.C:183
 MakeChain.C:184
 MakeChain.C:185
 MakeChain.C:186
 MakeChain.C:187
 MakeChain.C:188
 MakeChain.C:189
 MakeChain.C:190
 MakeChain.C:191
 MakeChain.C:192
 MakeChain.C:193
 MakeChain.C:194
 MakeChain.C:195
 MakeChain.C:196