Diana Software
diana-rootfilehandler.cxx
Go to the documentation of this file.
1 #include <TFile.h>
2 #include "QFileList.hh"
3 #include <string.h>
4 #include <stdlib.h>
5 #include <unistd.h>
6 #include <stdio.h>
7 #include <getopt.h>
8 #include <sys/types.h>
9 #include <TFile.h>
10 #include "QAliases.hh"
11 #include "QEventLabel.hh"
12 #include <TKey.h>
13 #include <string>
14 #include <iostream>
15 #include <TError.h>
16 #include <set>
17 #include <list>
18 #include <map>
19 #include <unistd.h>
20 #include "QTree.hh"
21 #ifndef __USING_ROOT6__
22  #include <TCint.h>
23 #endif
24 #include <TFileMerger.h>
25 #include <TInterpreter.h>
26 #include "QFrameWorkConfig.hh"
27 #include "QGlobalDataManager.hh"
28 #include "QStringHandler.hh"
29 
30 #include <TROOT.h>
31 
32 /* customized structure for command line parameters */
33 struct arg_t
34 {
35  bool l;
36  bool b;
37  bool c;
38  bool t;
39  char * r;
40  bool h;
41  bool v;
42  char *C;
43  char *S;
44  char *a;
45  int optind;
46 };
47 
48 /* function prototypes */
49 struct arg_t * Cmdline(int, char **);
50 void usage(char *);
51 void free_args(struct arg_t *);
52 struct arg_t *Cmdline(int argc, char *argv[]);
53 std::string RemoveDuplicates(const std::string& input,char d);
54 std::vector<std::string> GetTrees(TFile* file);
55 
56 //int gErrorIgnoreLevel = kError;
57 
58 void ParseDirAndFileName(const std::string& iinput, std::string& dir, std::string& file)
59 {
60  std::string input = RemoveDuplicates(iinput,'/');
61  size_t slash = input.find_last_of("/");
62  if(slash != std::string::npos) {
63  dir = input.substr(0,slash+1);
64  file = input.substr(slash+1,std::string::npos);
65  } else {
66  char cwd[1024];
67  getcwd(cwd, sizeof(cwd));
68  dir = cwd;
69  dir += "/";
70  file = input;
71  }
72 }
73 
74 std::string RemoveDuplicates(const std::string& input,char d)
75 {
76  std::string output;
77  if(input.empty()) return output;
78  char prev = input[0];
79  output.push_back(prev);
80  for(size_t i = 1; i < input.size(); i++) {
81  char curr = input[i];
82  if(!(curr == prev && curr == d)) {
83  output.push_back(curr);
84  }
85  prev = curr;
86  }
87  return output;
88 }
89 
90 int main(int argc, char* argv[])
91 {
92  arg_t* args = Cmdline(argc,argv);
93 
94  int optind = args->optind;
95  if(optind == 0) {
96  usage(argv[0]);
97  }
98 
99  #ifdef __USING_ROOT6__
100  // MV FIXME
101 // ::ROOT::GetROOT()->GetInterpreter()->EnableAutoLoading();
102  #else
103  TCint* cint = new TCint("pino","pino");
104  cint->EnableAutoLoading();
105  #endif
106 
107  // gather filenames
108  std::set<std::string> filenames;
109  for(int f = args->optind; f < argc; f++) {
110  std::string fileExtension = "";
111  std::string inFile = argv[f];
112  size_t dotpos = inFile.find_last_of(".");
113  if(dotpos != std::string::npos)
114  fileExtension = inFile.substr( dotpos+1 );
115  if(fileExtension == "list") {
116  std::list<std::string> list = QFileList::Read(inFile,"");
117  if(list.empty()) {
118  std::cerr<<"Error: problems reading file list "<<inFile<<std::endl;
119  exit(2);
120  }
121  std::list<std::string>::const_iterator iter = list.begin();
122  while(iter != list.end()) {
123  filenames.insert(*iter);
124  iter++;
125  }
126  } else {
127  filenames.insert(inFile);
128  }
129  }
130  // check they are all good files and group by dir
131  std::set<std::string>::const_iterator fiter = filenames.begin();
132  std::map<std::string, std::set<std::string> > dirfiles;
133  while(fiter != filenames.end()) {
134  TFile tfile(fiter->c_str());
135  if(tfile.IsZombie()) {
136  std::cerr<<"Error: file "<<fiter->c_str()<<" cannot be opened"<<std::endl;
137  exit(2);
138  }
139  std::string dir,file;
140  ParseDirAndFileName(*fiter,dir,file);
141  dirfiles[dir].insert(file);
142  fiter++;
143  }
144 
145 
146 
147  std::map<std::string, std::set<std::string> >::const_iterator dfiter = dirfiles.begin();
148  while(dfiter != dirfiles.end()) {
149  filenames = dfiter->second;
150  fiter = filenames.begin();
151  std::cout<<"== Processing directory: "<<dfiter->first<<std::endl;
152  while(fiter != filenames.end()) {
153  // list content of each file
154  std::string filename = dfiter->first + *fiter;
155  std::cout<<*fiter<<": ";
156  std::cout.flush();
157  bool found = false;
158  if(args->v || args->t) {
159  TFile file(filename.c_str());
160  std::vector<std::string> trees = GetTrees(&file);
161  std::cout<<" QTrees { ";
162  for(size_t t = 0; t < trees.size(); t++) {
163  QTree* qtree = (QTree*)file.Get(trees[t].c_str());
164  std::cout<<trees[t]<<"[";
165  if(args->v) std::cout<<qtree->GetSoftwareRevision()<<"] ";
166  else if(args->t) std::cout<<qtree->GetVersionTag()<<"] ";
167  }
168  std::cout<<"}";
169  }
170  else if(args->l) {
171  TFile file(filename.c_str());
172  std::vector<std::string> trees = GetTrees(&file);
173  if(args->b) {
174  std::cout<<" TBranches { ";
175  for(size_t t = 0; t < trees.size(); t++) {
176  QTree* qtree = (QTree*)file.Get(trees[t].c_str());
177  TObjArray* leaflist = qtree->GetListOfBranches();
178  TIter next(leaflist);
179  while(TObject* leaf = next()) {
180  std::cout<<leaf->GetName()<<" ";
181  }
182  }
183  std::cout<<"}";
184  } else {
185  std::cout<<" QTrees { ";
186  for(size_t t = 0; t < trees.size(); t++) {
187  std::cout<<trees[t]<<" ";
188  }
189  std::cout<<"}";
190  }
191  } else if(args->a) {
192  Diana::QAliases aliases;
193  QError err = aliases.FillFromFile(args->a);
194  if(err != QERR_SUCCESS) {
195  std::stringstream str;
196  str<<err;
197  std::cout<<str.str().c_str()<<std::endl;;
198  return 1;
199  }
200  TFile file(filename.c_str(),"UPDATE");
201  std::vector<std::string> trees = GetTrees(&file);
202  for(size_t t = 0; t < trees.size(); t++) {
203  QTree* qtree = (QTree*)file.Get(trees[t].c_str());
204  TObjArray* leaflist = qtree->GetListOfBranches();
205  TIter next(leaflist);
206  while(TObject* leaf = next()) {
207  std::string labelstr = leaf->GetName();
208  labelstr = labelstr.substr(0,labelstr.size()-1);
209  Diana::QEventLabel label(labelstr);
210  std::map<std::string, std::string> aliasMap = aliases.Find(label);
211  std::map<std::string, std::string>::const_iterator aiter = aliasMap.begin();
212 
213 
214  while(aiter != aliasMap.end()) {
215  std::string path;
216  if(aiter->second =="") {
217  path = labelstr;
218  } else {
219  path = labelstr+std::string(".")+aiter->second;
220 
221  }
222  const char* al = aiter->first.c_str();
223  const char* ap = path.c_str();
224  // printf("Adding alias %s for %s\n",al,ap);
225  qtree->SetAlias(al,ap);
226  aiter++;
227  }
228  }
229  }
230  file.Write("",TObject::kOverwrite);
231 
232  }else if(args->C || args->S) {
233  Diana::QGlobalDataManager dm;
234  Diana::GlobalHandle<QFrameWorkConfig> fwcHandle("Config");
235  dm.Get("Diana",&fwcHandle,filename);
236  if(fwcHandle.IsValid()) {
237  const QFrameWorkConfig& fwc = fwcHandle.Get();
238  if(args->S) {
239  std::string configfilename = args->S;
240  configfilename += "/";
241  configfilename += *fiter;
242  configfilename += ".cfg";
243  bool ok = fwc.SaveAllSequences(configfilename);
244  if(!ok) exit(3);
245  std::cout<<"Created \""<<configfilename<<"\"";
246  } else if(args->C) {
247  std::string directory = args->C;
248  std::string prefix = *fiter;
249  prefix += "_";
250  bool ok = fwc.SaveAllFiles(directory,prefix);
251  if(!ok) exit(3);
252  std::cout<<"Created config files in dir \""<<directory<<"\"";
253  }
254  }
255 
256  } else if(args->r) {
257  std::list<std::string> delObjects;
258  QStringHandler::Split(args->r,delObjects,',');
259  TFile file(filename.c_str(),"UPDATE");
260  if(args->b) {
261  // remove TBranch
262  std::vector<std::string> trees = GetTrees(&file);
263  std::vector<QTree*> qtreesToUpdate;
264  for(std::list<std::string>::const_iterator d = delObjects.begin(); d != delObjects.end(); d++) {
265  TString delObject = d->c_str();
266  bool foundThis = false;
267  for(size_t t = 0; t < trees.size(); t++) {
268  QTree* qtree = (QTree*)file.Get(trees[t].c_str());
269  if(qtree->FindBranch(delObject)) {
270  found = true;
271  foundThis = true;
272  std::string bname = delObject.Data();
273  qtree->SetBranchStatus(bname.c_str(),0);
274  bname += "*";
275  qtree->SetBranchStatus(bname.c_str(),0);
276  if(std::find(qtreesToUpdate.begin(),qtreesToUpdate.end(),qtree) == qtreesToUpdate.end()) {
277  qtreesToUpdate.push_back(qtree);
278  }
279  }
280  }
281  if(!foundThis) {
282  std::cout<<"TBranch "<<delObject<<" to be removed not found ";
283  std::cout.flush();
284  }
285 
286  }
287  if(found) {
288  std::string tmpOutput= filename+".d-rfh";
289  TFile outputFile(tmpOutput.c_str(),"RECREATE");
290  for(size_t t = 0; t < qtreesToUpdate.size(); t++) {
291  QTree* qtree = qtreesToUpdate[t];
292  outputFile.cd();
293  qtree->CloneTree();
294  TString delObject = qtree->GetName();
295  file.Delete(delObject+";*");
296  }
297  outputFile.Write();
298  file.Write("",TObject::kOverwrite);
299 
300  TFileMerger merg(0);
301 
302  merg.AddFile(&file);
303  merg.AddFile(&outputFile);
304  std::string tmpOutput2= filename+".d-rfh2";
305  merg.OutputFile(tmpOutput2.c_str(),1);
306  if(merg.Merge()) {
307  rename(tmpOutput2.c_str(),filename.c_str());
308  remove(tmpOutput.c_str());
309  } else {
310  std::cout<<"Error merging "<<filename<<": its content is unfortunately now split in: "<<filename<<" and "<<tmpOutput<<std::endl;
311  remove(tmpOutput2.c_str());
312  }
313 
314  }
315  } else {
316  // remove QTree
317  for(std::list<std::string>::const_iterator d = delObjects.begin(); d != delObjects.end(); d++) {
318  TString delObject = d->c_str();
319  if(file.Get(delObject)) {
320  found = true;
321  file.Delete(delObject+";*");
322  TObject* fele = 0;
323  if(QTree* itree = (QTree*) file.Get(QTREE_NAME)) {
324  TList* flist = itree->GetListOfFriends();
325  if(flist) fele = flist->FindObject(delObject.Data());
326  if(fele) itree->GetListOfFriends()->Remove(fele);
327  }
328  } else {
329  std::cout<<"QTree "<<delObject<<" to be removed not found ";
330  std::cout.flush();
331  }
332  }
333  if(found) {
334  file.Write("",TObject::kOverwrite);
335  }
336  }
337  std::cout<<std::endl;
338  }
339 
340  if(args->c && !args->b) {
341  TFileMerger merg(0);
342  TFile file(filename.c_str());
343 
344  merg.AddFile(&file);
345  std::string tmpOutput= filename+".d-rfh";
346  merg.OutputFile(tmpOutput.c_str(),1);
347  if(merg.Merge()) {
348  rename(tmpOutput.c_str(),filename.c_str());
349  } else {
350  std::cout<<"Error merging "<<filename<<std::endl;
351  remove(tmpOutput.c_str());
352  }
353  }
354  fiter++;
355  std::cout<<std::endl;
356  } // end loop on files
357  dfiter++;
358  } // end loop on dirs
359 
360  return 0;
361 }
362 
363 
364 
365 
366 
367 void usage(char *executable)
368 {
369  printf("usage: %s [ -alcrSCh ] .root and/or .list filenames \n", executable);
370  printf(" [ -l ] ");
371  printf("[ --list ] ");
372  printf("\n");
373  printf(" list QTrees (or their TBranches) in input files\n");
374 
375 
376  printf(" [ -t ] ");
377  printf("[ --tag ] ");
378  printf("\n");
379  printf(" list version tag of QTrees in input files\n");
380 
381  printf(" [ -v ] ");
382  printf("[ --version ] ");
383  printf("\n");
384  printf(" list software revision of QTrees in input files\n");
385 
386  printf(" [ -b ] ");
387  printf("[ --branch ] ");
388  printf("\n");
389  printf(" let -l and -r options act on TBranches instead of QTrees\n");
390 
391  printf(" [ -c ] ");
392  printf("[ --compact ] ");
393  printf("\n");
394  printf(" optimize file size (takes time)\n");
395 
396  printf(" [ -r ] ");
397  printf("[ --remove ] object_name1,object_name2,... ");
398  printf("\n");
399  printf(" remove QTree (or TBranch) with specified name\n");
400 
401  printf(" [ -C ] ");
402  printf("[ --configfile ] outputdir ");
403  printf("\n");
404  printf(" extract config files containing all sequences used to produce each file\n");
405 
406  printf(" [ -S ] ");
407  printf("[ --single-configfile ] outputdir ");
408  printf("\n");
409  printf(" extract a single config file containing all sequences used to produce each file\n");
410 
411  printf(" [ -a ] ");
412  printf("[ --aliasfile ] aliasfile ");
413  printf("\n");
414  printf(" apply aliases from aliasfile\n");
415 
416  printf(" [ -h ] ");
417  printf("[ --help ] ");
418  printf("\n");
419  printf(" Display help information.\n");
420 
421  printf("\nexample 1: (lists QTrees in root files and lists files in current dir)\n");
422  printf("\n-> diana-rootfilehandler -l *.root *.list\n\n");
423 
424  printf("example 2: (get all executed sequences in a single config file per root file)\n");
425  printf("\n-> diana-rootfilehandler -S cfg *.root *.list\n\n");
426 
427  exit(1);
428 }
429 
430 /*----------------------------------------------------------------------------
431  **
432  ** free_args()
433  **
434  ** Call this to free the memory that was dynamically allocated by the parser.
435  **
436  **--------------------------------------------------------------------------*/
437 
438 void free_args(struct arg_t *my_args)
439 {
440  if (my_args->r != NULL) free(my_args->r);
441  if (my_args->C != NULL) free(my_args->C);
442  if (my_args->S != NULL) free(my_args->S);
443  if (my_args->a != NULL) free(my_args->a);
444  free(my_args);
445 }
446 
447 /*----------------------------------------------------------------------------
448  **
449  ** Cmdline()
450  **
451  ** Parse the argv array into the command line structure
452  **
453  **--------------------------------------------------------------------------*/
454 
455 struct arg_t *Cmdline(int argc, char *argv[])
456 {
457  extern char *optarg;
458  extern int optind;
459  int option_index = 0;
460  int c;
461  struct arg_t *my_args;
462  int errflg = 0;
463 
464  static struct option long_options[] =
465  {
466  {"list", 0, 0, 'l'},
467  {"version", 0, 0, 'v'},
468  {"tag", 0, 0, 't'},
469  {"branch", 0, 0, 'b'},
470  {"compact", 0, 0, 'c'},
471  {"remove", 1, 0, 'r'},
472  {"help", 0, 0, 'h'},
473  {"configfile", 1, 0, 'C'},
474  {"single-configfile", 1, 0, 'S'},
475  {0, 0, 0, 0}
476  };
477 
478  my_args = (struct arg_t *) malloc (sizeof(struct arg_t));
479 
480  my_args->l = false;
481  my_args->b = false;
482  my_args->r = NULL;
483  my_args->c = false;
484  my_args->h = false;
485  my_args->v = false;
486  my_args->t = false;
487  my_args->C = NULL;
488  my_args->S = NULL;
489  my_args->a = NULL;
490 
491  while ((c = getopt_long(argc, argv, "a:lvtbcr:hC:S:", long_options, &option_index)) != EOF)
492  {
493  switch(c)
494  {
495  case 'l':
496  my_args->l = true;
497  break;
498  case 'v':
499  my_args->v = true;
500  break;
501  case 't':
502  my_args->t = true;
503  break;
504  case 'b':
505  my_args->b = true;
506  break;
507  case 'c':
508  my_args->c = true;
509  break;
510  case 'r':
511  my_args->r = strdup(optarg);
512  break;
513  case 'h':
514  my_args->h = true;
515  usage(argv[0]);
516  break;
517  case 'C':
518  my_args->C = strdup(optarg);
519  break;
520  case 'S':
521  my_args->S = strdup(optarg);
522  break;
523  case 'a':
524  my_args->a = strdup(optarg);
525  break;
526  default:
527  usage(argv[0]);
528 
529  }
530  } /* while */
531 
532  if (errflg)
533  usage(argv[0]);
534 
535  if (optind >= argc)
536  my_args->optind = 0;
537  else
538  my_args->optind = optind;
539  return my_args;
540 }
541 
542 std::vector<std::string> GetTrees(TFile* file)
543 {
544  TList* keys = file->GetListOfKeys();
545  std::vector<std::string> trees;
546  if(keys) {
547  TIter next(keys);
548  while(TKey* key = (TKey*) next()) {
549  std::string className = key->GetClassName();
550  if(className != "QTree") continue;
551  std::string objectName = key->GetName();
552  if(objectName.find("qtree") == 0) {
553  trees.push_back(key->GetName());
554  }
555  }
556  }
557  return trees;
558 }
ap
Definition: CheckOFShape.C:47
err
Definition: CheckOF.C:114
QGlobalDataManager dm
#define QTREE_NAME
Definition: QBaseTree.hh:18
@ QERR_SUCCESS
Definition: QError.hh:27
int optind
char * optarg
const std::string & GetVersionTag()
Definition: QBaseTree.hh:45
const std::string & GetSoftwareRevision()
Definition: QBaseTree.hh:43
error class with error type and description
Definition: QError.hh:115
void Read(const std::string &fileListPath)
Definition: QFileList.cc:67
QObject storing a set of QSecuenceConfigs.
bool SaveAllSequences(const std::string &outputfilename) const
save all sequences to a single file. Returns true/false in case of success/failure.
bool SaveAllFiles(const std::string &outputdir=".", const std::string &prefix="") const
calls SaveFile on all files present in the QSequenceConfigs and saves each file (preprnding an option...
QError Get(const std::string &owner, GlobalHandle< Q > *gh, const std::string &inSource, bool printError=true) const
Get an object using a global handle.
TTree used in diana.
Definition: QTree.hh:19
int main(int argc, char *argv[])
struct arg_t * Cmdline(int, char **)
void ParseDirAndFileName(const std::string &iinput, std::string &dir, std::string &file)
void free_args(struct arg_t *)
std::string RemoveDuplicates(const std::string &input, char d)
std::vector< std::string > GetTrees(TFile *file)
void usage(char *)
size_t Split(std::string source, std::list< std::string > &splitted, char separtator)
split source into a list of substrings separated by separator