Hall-D Software  alpha
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
hddm2root.cc
Go to the documentation of this file.
1 
2 
3 #include <iostream>
4 #include <iomanip>
5 #include <string>
6 #include <fstream>
7 #include <stack>
8 using namespace std;
9 
10 #include <sys/stat.h>
11 #include <time.h>
12 #include <expat.h>
13 #include <string.h>
14 
15 #include "DClassDef.h"
16 
17 string XML_FILENAME = "/home/davidl/work/latest/sim-recon/src/libraries/HDDM/event.xml";
18 string HDDM_CLASS = "x";
19 string CXXFLAGS = ""; // first and last character should be space (or empty string)
20 //string CXXFLAGS = " -pg -g ";
21 
22 map<string, DClassDef> CLASSES;
23 unsigned int MAX_DEPTH=0;
24 unsigned int TARGET_DEPTH=1;
25 
26 void startElement(void *data, const char *el, const char **attr);
27 void endElement(void *data, const char *el);
28 void CreateCopyRoutines(void);
29 void CreateHDDM2ROOT_tool(void);
30 string NameToHDDMname(string name);
31 string HDDMPlural(string name_hddm);
32 void Usage(void);
33 void ParseCommandLineArguments(int narg, char *argv[]);
34 
35 
36 //--------------
37 // main
38 //--------------
39 int main(int narg, char *argv[])
40 {
41  // Parse Command line args
42  ParseCommandLineArguments(narg, argv);
43 
44  // Parse XML file to get class definitions
45  stack<string> ancestory;
46 
47  XML_Parser parser = XML_ParserCreate(NULL);
48  XML_SetUserData(parser, &ancestory);
49  XML_SetElementHandler(parser, startElement, endElement);
50 
51  ifstream ifs(XML_FILENAME.c_str());
52 
53  // get length of file:
54  ifs.seekg (0, ios::end);
55  int length = ifs.tellg();
56  ifs.seekg (0, ios::beg);
57 
58  if(length > 102400)length = 102400; // limit size to 100kB in case this is hddm file
59 
60  char *buff = new char[length];
61  ifs.read (buff,length);
62  ifs.close();
63 
64  // Find terminating "</HDDM>" string and shorten buffer to this
65  char *end = strstr(buff, "</HDDM>");
66  if(end){
67  end[strlen("</HDDM>")] = 0;
68  length = strlen(buff);
69  }
70 
71  // Create sub-directory for all source just to keep things a little cleaner
72  mkdir("hddm_root_generated", S_IRWXU | S_IRWXG | S_IRWXO);
73 
74  // Write hddm XML definition to file
75  ofstream hddmxmlofs("hddm_root_generated/hddm_def.xml");
76  if(hddmxmlofs.is_open()){
77  hddmxmlofs << buff;
78  hddmxmlofs.close();
79 
80  // If we were able to write the XML file, then use it to
81  // generate the I/O routines in our source directory. This
82  // is preferred since it will guarantee compatibility with
83  // this file. In case we don't get here, the tool will need
84  // to compile using I/O routines from sim-recon.
85  mkdir("hddm_root_generated/HDDM", S_IRWXU | S_IRWXG | S_IRWXO);
86  system("cd hddm_root_generated/HDDM ; hddm-c ../hddm_def.xml");
87  system("cd hddm_root_generated/HDDM ; hddm-cpp ../hddm_def.xml");
88  // sed -e '/\/HDDM/,$d'
89  }
90 
91  int done = 0;
92  XML_Parse(parser, buff, length, done);
93 
94  delete[] buff;
95 
96 
97  // Create a header file for each class. This is needed to make
98  // the ROOT dictionaries (cint doesn't seem to like it when they
99  // are all in the same file).
100 
101  // Print class definitions
102  // Here we must print them in reverse-depth order so the classes
103  // that show up as members of others are defined first.
104  map<string, DClassDef>::iterator iter;
105  for(iter=CLASSES.begin(); iter!=CLASSES.end(); iter++){
106  string name = iter->first;
107  string type = iter->second.name;
108  map<string,string> &members = iter->second.members;
109 
110  //if(iter->second.depth != depth)continue; // printing in reverse-depth order
111  if(name == "HDDM_t")continue; // Skip outer HDDM tags
112 
113  // Open output file
114  string fname = string("hddm_root_generated/") + name + ".h";
115  cout<<"writing "<<fname<<endl;
116  ofstream ofs(fname.c_str());
117 
118  // Write header to file
119  ofs << "#include<vector>" << endl;
120  ofs << "using namespace std;" << endl;
121  ofs << endl;
122  ofs << "#include<Rtypes.h>" << endl;
123  ofs << "#include<TObject.h>" << endl;
124  ofs << endl;
125 
126  ofs << "#ifndef _" << name << "_"<<endl;
127  ofs << "#define _" << name << "_"<<endl;
128 
129  ofs << "typedef int Particle_t;" << endl;
130  ofs << endl;
131 
132  // Add relevant includes for other classes this depends on
133  set<string> &include_types = iter->second.include_types;
134  set<string>::iterator iter_inc;
135  for(iter_inc=include_types.begin(); iter_inc!=include_types.end(); iter_inc++){
136  ofs << "#include \"" << *iter_inc << "_t.h\""<<endl;
137  }
138  ofs << endl;
139 
140  // Write class definition to file
141  ofs<<"class " << name << ":public TObject{" << endl;
142  ofs<<" public:"<<endl;
143  ofs<<endl;
144 
145  map<string,string>::iterator iter2;
146  for(iter2=members.begin(); iter2!=members.end(); iter2++){
147  ofs << " " << iter2->second << " " << iter2->first << ";" << endl;
148  }
149  ofs<<endl;
150  ofs<<" ClassDef("<<name<<",1)"<<endl;
151  ofs<<"};"<<endl;
152  ofs<<endl;
153 
154  ofs << "#endif" << endl;
155 
156  // Close file
157  ofs.close();
158  }
159 
160  // Create script that will generate ROOT dictionaries for each header file
161  ofstream ofs("hddm_root_generated/makefile");
162  ofs << endl << endl;
163  ofs << "all: dictionaries copy_routines tool" << endl;
164  ofs << endl;
165  ofs << "dictionaries: *.h"<<endl;
166  for(iter=CLASSES.begin(); iter!=CLASSES.end(); iter++){
167  string name = iter->first;
168  if(name == "HDDM_t")continue; // Skip outer HDDM tags
169 
170  string cmd = " rootcint -f " + name + "_Dict.cc -c " + name + ".h";
171  ofs << cmd << endl;
172  }
173 
174  for(iter=CLASSES.begin(); iter!=CLASSES.end(); iter++){
175  string name = iter->first;
176  if(name == "HDDM_t")continue; // Skip outer HDDM tags
177 
178  string cmd = " c++ `root-config --cflags` -c " + name + "_Dict.cc" + CXXFLAGS;
179  ofs << cmd << endl;
180  }
181  ofs << " ar -r libhddm_root.a *_t_Dict.o" << endl;
182  ofs << endl;
183  ofs << endl;
184 
185  ofs << "copy_routines: hddm_root_CopyRoutines.cc hddm_root_CopyRoutines.h" << endl;
186  string cmd = " c++ `root-config --cflags` -c -I${HALLD_RECON_HOME}/${BMS_OSNAME}/include -I. hddm_root_CopyRoutines.cc" + CXXFLAGS;
187  ofs << cmd << endl;
188  ofs << " ar -r libhddm_root.a hddm_root_CopyRoutines.o" << endl;
189  ofs << endl;
190 
191  ofs << "tool: hddm2root_*.cc" << endl;
192  cmd = " c++ `root-config --cflags --libs` -I${HALLD_RECON_HOME}/${BMS_OSNAME}/include -I. hddm2root_" + HDDM_CLASS + ".cc -o hddm2root_" + HDDM_CLASS + CXXFLAGS + " ./libhddm_root.a -lbz2 -lz -L${HALLD_RECON_HOME}/${BMS_OSNAME}/lib -lHDDM -lxstream";
193  ofs << cmd << endl;
194  ofs << endl;
195  ofs << endl;
196 
197  ofs.close();
198 
199  // Create Copy Routines
201 
202  // Create main tool file
204 
205  // Notify user of final step
206  cout<<endl;
207  cout<<"Code generation complete. Issue the following"<<endl;
208  cout<<"to build the hddm2root_"<<HDDM_CLASS<<" tool:"<<endl;
209  cout<<endl;
210  cout<<" make -C hddm_root_generated"<<endl;
211  cout<<endl;
212  cout<<"The tool will be left as hddm_root_generated/hddm2root_"<<HDDM_CLASS<<endl;
213  cout<<endl;
214 
215  return 0;
216 }
217 
218 //--------------
219 // startElement
220 //--------------
221 void startElement(void *data, const char *el, const char **attr)
222 {
223  // Setup reference to our ancestory stack
224  stack<string> &ancestory = *(stack<string>*)data;
225 
226  // Convert element tag to string
227  string name(el);
228 
229  // Loop over attributes, temporarily storing them into map
230  map<string, string> members;
231  bool is_unbounded = false;
232  for (int i = 0; attr[i]; i += 2) {
233  string name(attr[i]);
234  string type(attr[i+1]);
235 
236  // Some attributes are HDDM-specific
237  if(name == "class") HDDM_CLASS = type;
238  if(name == "minOccurs")continue;
239  if(name == "version")continue;
240  if(name == "maxOccurs"){
241  if(type == "unbounded"){
242  is_unbounded = true;
243  continue;
244  }
245  if(atoi(type.c_str())>1){
246  is_unbounded = true;
247  continue;
248  }
249  continue;
250  }
251 
252  if(type.find("GeV")== 0 )continue; // skip Eunit and punit stuff
253  if(type == "rad")continue;
254  if(type == "ns")continue;
255  if(type == "cm")continue;
256 
257  if(type=="boolean") type = "bool"; // (sigh...)
258 
259  // Add member to list
260  members[name] = type;
261  }
262 
263 
264  // If there is a parent, add this element as a member
265  if(!ancestory.empty()){
266  if(is_unbounded){
267  CLASSES[ancestory.top()].members[name+"s"] = string("vector<") + name + "_t>";
268  }else{
269  CLASSES[ancestory.top()].members[name] = name + "_t";
270  }
271  CLASSES[ancestory.top()].include_types.insert(name);
272  }
273 
274  // Get reference to class definition, creating it if necessary
275  DClassDef &class_def = CLASSES[name + "_t"];
276  class_def.members.insert(members.begin(), members.end());
277  class_def.depth = ancestory.size();
278  if(class_def.depth > MAX_DEPTH) MAX_DEPTH = class_def.depth;
279 
280  ancestory.push(name + "_t");
281 }
282 
283 //--------------
284 // endElement
285 //--------------
286 void endElement(void *data, const char *el)
287 {
288  stack<string> &ancestory = *(stack<string>*)data;
289 
290  ancestory.pop();
291 }
292 
293 //--------------
294 // CreateCopyRoutines
295 //--------------
297 {
298  // Open header file to write into
299  cout << "Writing hddm_root_generated/hddm_root_CopyRoutines.h" << endl;
300  ofstream ofs("hddm_root_generated/hddm_root_CopyRoutines.h");
301 
302  // Add file header
303  time_t t = time(NULL);
304  ofs << "//" << endl;
305  ofs << "// Auto-generated HDDM to ROOT copy routines DO NOT EDIT" << endl;
306  ofs << "//" << endl;
307  ofs << "// "<<ctime(&t);
308  ofs << "// Generated from: "<<XML_FILENAME<<endl;
309  ofs << "//" << endl;
310  ofs << endl;
311 
312  ofs << "#define Particle_t Particle_tt"<<endl;
313  map<string, DClassDef>::iterator iter;
314  for(unsigned int depth=0; depth<MAX_DEPTH; depth++){
315  for(iter=CLASSES.begin(); iter!=CLASSES.end(); iter++){
316  if(iter->second.depth != depth) continue;
317  if(iter->first == "HDDM_t")continue;
318  ofs << "#include \"" << iter->first << ".h\"" << endl;
319  }
320  }
321  ofs << "#undef Particle_t" << endl;
322  ofs << endl;
323  ofs << endl;
324 
325  ofs << "#include <HDDM/hddm_"<<HDDM_CLASS<<".hpp>"<<endl;
326  ofs << "using namespace hddm_"<<HDDM_CLASS<<";"<<endl;
327  ofs << endl;
328 
329  // Copy Routine declarations
330  for(iter=CLASSES.begin(); iter!=CLASSES.end(); iter++){
331  string name = iter->first;
332  string varname = name.substr(0, name.length()-2);
333  string name_hddm = NameToHDDMname(varname);
334 
335  if(varname == "HDDM")continue;
336 
337  ofs << "void Copy"<<name_hddm<<"("<<name<<" &"<<varname<<", class "<<name_hddm<<" &"<<varname<<"_hddm, bool hddm_invalid=false);"<<endl;
338  }
339  ofs << endl;
340 
341  // Clear Routine declarations
342  for(iter=CLASSES.begin(); iter!=CLASSES.end(); iter++){
343  string name = iter->first;
344  string varname = name.substr(0, name.length()-2);
345  string name_hddm = NameToHDDMname(varname);
346 
347  if(varname == "HDDM")continue;
348 
349  ofs << "void Clear"<<name_hddm<<"("<<name<<" &"<<varname<<");"<<endl;
350  }
351  ofs << endl;
352  ofs << endl;
353  ofs.close(); // header file
354 
355  // Open implementation file to write into
356  cout << "Writing hddm_root_generated/hddm_root_CopyRoutines.cc" << endl;
357  ofs.open("hddm_root_generated/hddm_root_CopyRoutines.cc");
358 
359  // Add file header
360  ofs << "//" << endl;
361  ofs << "// Auto-generated HDDM to ROOT copy routines DO NOT EDIT" << endl;
362  ofs << "//" << endl;
363  ofs << "// "<<ctime(&t);
364  ofs << "// Generated from: "<<XML_FILENAME<<endl;
365  ofs << "//" << endl;
366  ofs << endl;
367  ofs << "#include \"hddm_root_CopyRoutines.h\"" << endl;
368  ofs << endl;
369  ofs << endl;
370 
371  // Copy Routines
372  for(iter=CLASSES.begin(); iter!=CLASSES.end(); iter++){
373  string name = iter->first;
374  string varname = name.substr(0, name.length()-2);
375  string name_hddm = NameToHDDMname(varname);
376  string name_hddm_plural = HDDMPlural(name_hddm);
377  map<string, string> &members = iter->second.members;
378 
379  if(varname == "HDDM")continue;
380 
381  ofs << "void Copy"<<name_hddm<<"("<<name<<" &"<<varname<<", class "<<name_hddm<<" &"<<varname<<"_hddm, bool hddm_invalid)"<<endl;
382  ofs << "{"<<endl;
383  ofs << " if(hddm_invalid)return; // FIXME!!!" << endl;
384  ofs << endl;
385 
386  map<string, string>::iterator iter_members;
387  for(iter_members=members.begin(); iter_members!=members.end(); iter_members++){
388  string myname = iter_members->first;
389  string mytype = iter_members->second;
390  string myvarname = myname;
391  string myname_hddm = NameToHDDMname(myvarname);
392 
393  if( mytype == "int"
394  || mytype == "float"
395  || mytype == "bool"
396  || mytype == "Particle_t"
397  || mytype == "string"){
398 
399  // Atomic type uses equals
400  ofs << " " << varname<<"."<<myvarname<<" = "<<varname<<"_hddm.get"<<myname_hddm<<"();" << endl;
401  }else if(mytype.find("vector<") == 0){
402  // STL vector requires iteration
403  mytype = myname.substr(0, myname.length()-1); // chop off "s" that was added
404  myname_hddm = NameToHDDMname(mytype);
405  string myname_hddm_plural = HDDMPlural(mytype);
406  string iter_name = "iter_" + mytype;
407  ofs << endl;
408  //ofs << "--- skipping "<<mytype<<":"<<myname<<":"<<myname_hddm_plural<<endl;
409  ofs << " "<<myname_hddm<<"List &"<<myname_hddm_plural<<" = "<<varname<<"_hddm.get"<<HDDMPlural(myname_hddm)<<"();" <<endl;
410  ofs << " "<<myname_hddm<<"List::iterator "<<iter_name<<";"<<endl;
411  ofs << " for("<<iter_name<<"="<<myname_hddm_plural<<".begin(); "<<iter_name<<"!="<<myname_hddm_plural<<".end(); "<<iter_name<<"++){"<<endl;
412  ofs << " "<<mytype<<"_t a;"<<endl;
413  ofs << " Copy"<<myname_hddm<<"(a, *"<<iter_name<<");"<<endl;
414  ofs << " "<<varname<<"."<<myname<<".push_back(a);"<<endl;
415  ofs << " }"<<endl;
416  }else{
417  // Non-vector calls copy routine
418  string myname_hddm_plural = HDDMPlural(myname_hddm);
419  if(myname_hddm_plural == "Properties") myname_hddm_plural = "PropertiesList";
420  ofs << " Copy"<<myname_hddm<<"("<<varname<<"."<<myvarname<<", "<<varname<<"_hddm.get"<<myname_hddm<<"(), "<<varname<<"_hddm.get"<< myname_hddm_plural<< "().empty());" << endl;
421  }
422  }
423 
424  ofs << "}" << endl;
425  ofs << endl;
426  }
427  ofs << endl;
428  ofs << endl;
429 
430  // Clear Routines
431  for(iter=CLASSES.begin(); iter!=CLASSES.end(); iter++){
432  string name = iter->first;
433  string varname = name.substr(0, name.length()-2);
434  string name_hddm = NameToHDDMname(varname);
435  string name_hddm_plural = HDDMPlural(name_hddm);
436  map<string, string> &members = iter->second.members;
437 
438  if(varname == "HDDM")continue;
439 
440  ofs << "void Clear"<<name_hddm<<"("<<name<<" &"<<varname<<")"<<endl;
441  ofs << "{"<<endl;
442  ofs << endl;
443 
444  map<string, string>::iterator iter_members;
445  for(iter_members=members.begin(); iter_members!=members.end(); iter_members++){
446  string myname = iter_members->first;
447  string mytype = iter_members->second;
448  string myvarname = myname;
449  string myname_hddm = NameToHDDMname(myvarname);
450 
451  if(mytype == "int" || mytype == "Particle_t"){
452  ofs << " " << varname<<"."<<myvarname<<" = 0;" << endl;
453  }else if(mytype == "float"){
454  ofs << " " << varname<<"."<<myvarname<<" = 0.0;" << endl;
455  }else if(mytype == "string"){
456  ofs << " " << varname<<"."<<myvarname<<" = \"\";" << endl;
457  }else if(mytype == "bool"){
458  ofs << " " << varname<<"."<<myvarname<<" = false;" << endl;
459  }else if(mytype.find("vector<") == 0){
460  ofs << " " << varname<<"."<<myname<<".clear();"<< endl;
461  }else{
462  // Non-vector calls copy routine
463  string myname_hddm_plural = HDDMPlural(myname_hddm);
464  if(myname_hddm_plural == "Properties") myname_hddm_plural = "PropertiesList";
465  ofs << " Clear"<<myname_hddm<<"("<<varname<<"."<<myvarname<<");" << endl;
466  }
467  }
468 
469  ofs << "}" << endl;
470  ofs << endl;
471  }
472  ofs << endl;
473  ofs << endl;
474 
475  ofs.close();
476 }
477 
478 //--------------
479 // CreateHDDM2ROOT_tool
480 //--------------
482 {
483 
484  // Open implementation file to write into
485  string fname = string("hddm_root_generated/hddm2root_") + HDDM_CLASS + ".cc";
486  ofstream ofs(fname.c_str());
487  cout << "Writing " << fname << endl;
488 
489  // Add file header
490  time_t t = time(NULL);
491  ofs << "//" << endl;
492  ofs << "// Auto-generated HDDM to ROOT converion tool for class " << HDDM_CLASS << endl;
493  ofs << "//" << endl;
494  ofs << "// "<<ctime(&t);
495  ofs << "// Generated from: "<<XML_FILENAME<<endl;
496  ofs << "//" << endl;
497  ofs << endl;
498  ofs << endl;
499 
500  // Add headers
501  ofs << "#include <stdlib.h>" << endl;
502  ofs << "#include <fstream>" << endl;
503  ofs << "#include <string>" << endl;
504  ofs << "#include <TTree.h>" << endl;
505  ofs << "#include <TFile.h>" << endl;
506  ofs << "using namespace std;" << endl;
507  ofs << endl;
508  ofs << "#include \"hddm_root_CopyRoutines.h\"" << endl;
509  ofs << endl;
510  ofs << endl;
511 
512  // Add main
513  ofs << "int main(int narg, char *argv[])" << endl;
514  ofs << "{" << endl;
515  ofs << endl;
516  ofs << " string usage = \"Usage:\\n\\n hddm2root_"<<HDDM_CLASS<<" [-n nevents] [-o outfile.root] file.{xml|hddm}\";" << endl;
517  ofs << endl;
518  ofs << " if(narg<2){cout << endl << usage << endl << endl; return -1;}"<<endl;
519  ofs << endl;
520  ofs << " // Parse command line arguments" << endl;
521  ofs << " int MAX_EVENTS = 0;"<<endl;
522  ofs << " string ofname=\"hddm2root_" << HDDM_CLASS << ".root\";"<<endl;
523  ofs << " string fname=\"hdgeant_smeared.hddm\";"<<endl;
524  ofs << " for(int i=1; i<narg; i++){" << endl;
525  ofs << " string arg = argv[i];" << endl;
526  ofs << " if(arg==\"-n\"){" << endl;
527  ofs << " if(++i<narg){" << endl;
528  ofs << " MAX_EVENTS = atoi(argv[i]);" << endl;
529  ofs << " }else{" << endl;
530  ofs << " cerr<<\"-n option requires an argument!\"<<endl;" << endl;
531  ofs << " return -1;" << endl;
532  ofs << " }" << endl;
533  ofs << " }else if(arg==\"-o\"){" << endl;
534  ofs << " if(++i<narg){" << endl;
535  ofs << " ofname = argv[i];" << endl;
536  ofs << " }else{" << endl;
537  ofs << " cerr<<\"-o option requires an argument!\"<<endl;" << endl;
538  ofs << " return -2;" << endl;
539  ofs << " }" << endl;
540  ofs << " }else if(arg==\"-h\"){" << endl;
541  ofs << " cout << endl << usage << endl << endl;" << endl;
542  ofs << " return 0;" << endl;
543  ofs << " }else{" << endl;
544  ofs << " fname = argv[i];" << endl;
545  ofs << " }" << endl;
546  ofs << " }" << endl;
547  ofs << endl;
548  ofs << " TFile *f = new TFile(ofname.c_str(), \"RECREATE\");" << endl;
549  ofs << " TTree *t = new TTree(\"T\", \"A Tree\", 99);" << endl;
550  ofs << endl;
551 
552  // Create variable for each depth=TARGET_DEPTH class
553  char branchname[2] = "A";
554  map<string, DClassDef>::iterator iter;
555  for(iter=CLASSES.begin(); iter!=CLASSES.end(); iter++){
556  if(iter->second.depth!=TARGET_DEPTH)continue;
557  string name = iter->first;
558  string varname = name.substr(0, name.length()-2);
559 
560  ofs << " " << name << " *"<<varname << " = new " << name << "();" << endl;
561  ofs << " t->Branch(\""<<branchname<<"\", &"<<varname<<");"<<endl;
562 
563  branchname[0]++; // sketchy trick to name branches A,B,C, ....
564  }
565  ofs << endl;
566  ofs << " // Open hddm file for reading" << endl;
567  ofs << " ifstream ifs(fname.c_str());" << endl;
568  ofs << endl;
569  ofs << " // Associate input file stream with HDDM record" << endl;
570  ofs << " hddm_"<<HDDM_CLASS<<"::istream istr(ifs);" << endl;
571  ofs << endl;
572  ofs << " // Loop over events" << endl;
573  ofs << " unsigned int N = 0;"<<endl;
574  ofs << " while(!ifs.eof()){" << endl;
575  ofs << " try{" << endl;
576  ofs << " HDDM xrec;" << endl;
577  ofs << " istr >> xrec;"<<endl;
578 
579  // Call copy routine for each depth=TARGET_DEPTH class
580  for(iter=CLASSES.begin(); iter!=CLASSES.end(); iter++){
581  if(iter->second.depth!=TARGET_DEPTH)continue;
582  string name = iter->first;
583  string varname = name.substr(0, name.length()-2);
584  string name_hddm = NameToHDDMname(varname);
585 
586  ofs << " Clear" << name_hddm << "(*"<<varname<<");"<<endl;
587  ofs << " Copy" << name_hddm << "(*"<<varname<<", xrec.get"<<name_hddm<<"());"<<endl;
588  }
589  ofs << endl;
590  ofs << " t->Fill();" << endl;
591  ofs << " if(++N%10 == 0){cout<<\" \"<<N<<\" events processed \\r\"; cout.flush();}"<<endl;
592  ofs << " if(MAX_EVENTS>0 && N>=MAX_EVENTS)break;"<<endl;
593  ofs << " }catch(...){" << endl;
594  ofs << " break;" << endl;
595  ofs << " }" << endl;
596  ofs << " }" << endl;
597  ofs << endl;
598  ofs << " f->Write();" << endl;
599  ofs << " f->Close();" << endl;
600  ofs << " delete f;" << endl;
601  ofs << endl;
602  ofs << " cout<<endl<<N<<\" events processed total\"<<endl;" << endl;
603  ofs << " return 0;" << endl;
604  ofs << "}" << endl;
605  ofs << endl;
606 
607  ofs.close();
608 }
609 
610 //--------------
611 // NameToHDDMname
612 //--------------
613 string NameToHDDMname(string name)
614 {
615  // Convert our class name used for ROOT
616  // into the HDDM class name
617  string name_hddm = name;
618  name_hddm[0] = toupper(name[0]);
619 
620  return name_hddm;
621 }
622 
623 //--------------
624 // HDDMPlural
625 //--------------
626 string HDDMPlural(string name_hddm)
627 {
628  // Re-create HDDM-style plurals
629 
630  if(name_hddm.size()<3) return name_hddm + "s";
631 
632  if(name_hddm.substr(name_hddm.length()-2, 2) == "ex"){
633  name_hddm.erase(name_hddm.length()-2);
634  name_hddm += "ices";
635  }else if(name_hddm.substr(name_hddm.length()-4, 4) == "ties"){
636  // do nothing
637  }else if(name_hddm.substr(name_hddm.length()-2, 2) == "ty"){
638  name_hddm.erase(name_hddm.length()-2);
639  name_hddm += "ties";
640  }else if(name_hddm.substr(name_hddm.length()-3, 3) == "tum"){
641  name_hddm.erase(name_hddm.length()-3);
642  name_hddm += "ta";
643  }else if(name_hddm.substr(name_hddm.length()-1, 1) == "s"){
644  name_hddm += "es";
645  }else{
646  name_hddm += "s";
647  }
648 
649  return name_hddm;
650 }
651 
652 //--------------
653 // Usage
654 //--------------
655 void Usage(void)
656 {
657  cout<<endl;
658  cout<<endl;
659  cout<<"Usage:"<<endl;
660  cout<<" hddm2root [-depth d] filename"<<endl;
661  cout<<endl;
662  cout<<" Generate a tool for converting an HDDM formatted"<<endl;
663  cout<<"file into a ROOT file. This does not convert the"<<endl;
664  cout<<"file itself, but rather, generates a program than"<<endl;
665  cout<<"can be used to convert a file."<<endl;
666  cout<<endl;
667  cout<<" The file specified by \"filename\" can be either"<<endl;
668  cout<<"the original XML file, or an existing HDDM file."<<endl;
669  cout<<"If the latter is used, the XML is extracted from"<<endl;
670  cout<<"beginning of the file."<<endl;
671  cout<<endl;
672  cout<<" options:"<<endl;
673  cout<<" -depth d Set the target depth for objects to"<<endl;
674  cout<<" be written to the ROOT file"<<endl;
675  cout<<endl;
676  cout<<" -h Print this Usage statement"<<endl;
677  cout<<endl;
678  cout<<endl;
679  cout<<"There are several limitations to this system:"<<endl;
680  cout<<endl;
681  cout<<"1. ROOT does not allow nested containers more"<<endl;
682  cout<<" than a few levels deep. In other words, you can"<<endl;
683  cout<<" have a container of containers, but not a"<<endl;
684  cout<<" container of containers of containers .... For"<<endl;
685  cout<<" practical purposes, this means any tag in "<<endl;
686  cout<<" XML with more than 2 parents having maxOccurs"<<endl;
687  cout<<" set to \"unbounded\" will not be accessible in"<<endl;
688  cout<<" the file. Use the -depth d option to try and"<<endl;
689  cout<<" get around this."<<endl;
690  cout<<endl;
691  cout<<"2. All tags with a maxOccurs=1 will be treated"<<endl;
692  cout<<" as though a single object of that type exists."<<endl;
693  cout<<" This means that the if there are zero objects"<<endl;
694  cout<<" of that type in the event, values will be written"<<endl;
695  cout<<" anyway, not saving any disk space. The values"<<endl;
696  cout<<" will be filled with zeros and empty strings"<<endl;
697  cout<<" (false for bool types)."<<endl;
698  cout<<endl;
699  cout<<"3. Top-level objects can only have single objects."<<endl;
700  cout<<" In other words, if you specify a depth where an"<<endl;
701  cout<<" object at that depth is \"unbounded\", the tool"<<endl;
702  cout<<" will not try and loop over all instances of the"<<endl;
703  cout<<" object type, just the first may be taken."<<endl;
704  cout<<endl;
705  cout<<"e.g."<<endl;
706  cout<<" > hddm2root $HALLD_RECON_HOME/src/libraries/HDDM/rest.xml"<<endl;
707  cout<<" > hddm2root_r file.hddm"<<endl;
708  cout<<endl;
709 
710  exit(0);
711 }
712 
713 //--------------
714 // ParseCommandLineArguments
715 //--------------
716 void ParseCommandLineArguments(int narg, char *argv[])
717 {
718  if(narg<2)Usage();
719 
720  for(int i=1; i<narg; i++){
721  string arg = argv[i];
722 
723  if(arg.find("-depth") != arg.npos){
724  if(++i >= narg){
725  cerr<<endl<<" -depth requires and argument!"<<endl;
726  exit(-1);
727  }
728  TARGET_DEPTH = atoi(argv[i]);
729  continue;
730  }
731 
732  if(arg.find("-h") != arg.npos){
733  Usage();
734  }
735 
736  XML_FILENAME = arg;
737  }
738 }
739 
740 
741 
742 
char string[256]
unsigned int depth
Definition: DClassDef.h:25
void CreateCopyRoutines(void)
Definition: hddm2root.cc:296
string HDDM_CLASS
Definition: hddm2root.cc:18
void startElement(void *data, const char *el, const char **attr)
Definition: hddm2root.cc:221
unsigned int TARGET_DEPTH
Definition: hddm2root.cc:24
void CreateHDDM2ROOT_tool(void)
Definition: hddm2root.cc:481
string HDDMPlural(string name_hddm)
Definition: hddm2root.cc:626
void ParseCommandLineArguments(int &narg, char *argv[])
Definition: hd_dump.cc:124
string XML_FILENAME
Definition: hddm2root.cc:17
string NameToHDDMname(string name)
Definition: hddm2root.cc:613
map< string, string > members
Definition: DClassDef.h:23
map< string, DClassDef > CLASSES
Definition: hddm2root.cc:22
unsigned int MAX_DEPTH
Definition: hddm2root.cc:23
string CXXFLAGS
Definition: hddm2root.cc:19
void endElement(void *data, const char *el)
Definition: hddm2root.cc:286
void Usage(JApplication &app)
Definition: hd_ana.cc:33
int main(int argc, char *argv[])
Definition: gendoc.cc:6