1 saw 1.1 /*-----------------------------------------------------------------------------
2 * Copyright (c) 1999 Thomas Jefferson National Accelerator Facility
3 *
4 * This software was developed under a United States Government license
5 * described in the NOTICE file included as part of this distribution.
6 *
7 * Stephen A. Wood, 12000 Jefferson Ave., Newport News, VA 23606
8 * Email: saw@jlab.org Tel: (758) 269-7367 Fax: (757) 269-5235
9 *-----------------------------------------------------------------------------
10 *
11 * Description:
12 * Book ROOT trees.
13 *
14 * Author: Stephen Wood, CEBAF Hall C
15 *
16 * Revision History:
17 * $Log: thTree.c,v $
|
18 saw 1.5 *
19 * Revision 1.1.16.2 2004/07/09 20:41:50 saw
20 * Can now put a test on a tree block
21 *
22 * Revision 1.1.16.1 2004/07/09 14:12:11 saw
23 * Add ability for CTP to make ROOT Trees
24 *
25 * Revision 1.4 2004/07/08 20:07:00 saw
26 * Supply dummy routines when ROOTSYS not defined
27 *
|
28 saw 1.4 * Revision 1.3 2004/07/07 18:16:30 saw
29 * Use properly exported names from thRootStuff.cpp
30 *
|
31 saw 1.3 * Revision 1.2 2004/07/02 18:46:29 saw
32 * Update ugly cpp routine for gcc 3.2.3. Need to find a better way to
33 * reference C++ routines.
34 *
|
35 saw 1.2 * Revision 1.1 2002/07/31 20:07:48 saw
36 * Add files for ROOT Trees
37 *
|
38 saw 1.1 * Revision 1.1 1999/08/25 13:16:07 saw
39 * *** empty log message ***
40 *
41 */
42
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <math.h>
47 #include "daVar.h"
48 #include "th.h"
49 #include "thInternal.h"
50 #include "thUtils.h"
51
|
52 saw 1.4 #ifdef ROOTTREE
|
53 saw 1.1 extern daVarStatus thTreeRHandler();
54
55 struct thLeafList { /* Variable and index list */
56 struct thLeafList *next;
57 char *name;
58 int leafsize; /* Number of bytes in leaf */
59 char leaftype; /* Single letter with leaf type */
60 daVarStruct *varp; int index;
61 };
62 typedef struct thLeafList thLeafList;
63
64 struct thTreeBranchList {
65 struct thTreeBranchList *next;
66 char *branchname; /* Block name without the "block.hist" */
67 void *evstruct; /* Event structure to fill with data */
68 struct thLeafList *leaflistp;
69 };
70 typedef struct thTreeBranchList thTreeBranchList;
71
72 struct thTreeOpaque { /* Opaque structure for histogram definition */
73 void *file;
74 saw 1.1 /* void *file Need to point to structure that has file info. File structures will also
75 be on a linked list so that we a new file is opened, you can see if it exists. Wait, we
76 should just use davars. Make a new class for files? ?
77 */
78 void *treeptr; /* Pointer to tree object */
79 daVarStruct *test; int testindex;
80 thTreeBranchList *branchlistP;
81 };
82 typedef struct thTreeOpaque thTreeOpaque;
83
84 struct thRBlockList {
85 struct thRBlockList *next;
86 char *blockname; /* Block name without the "block.tree" */
87 daVarStruct *var; /* Varptr points to # times called
88 Title is code from file.
89 opaque is pointer to hist speclist */
90 };
91 typedef struct thRBlockList thRBlockList;
92
93 thRBlockList *thRBlockListP; /* Pointer to list of tree blocks */
94
95 saw 1.1 thStatus thBookaBranch(thTreeOpaque *tree, char *line, thTreeBranchList **thBranchNext);
96 /*thStatus thExecuteaHist(thHistSpecList *Hist);*/
97 thStatus thRemoveTree(char *block_name);
98
99 thStatus thBookTree(daVarStruct *var)
100 {
101 char *lines,*eol;
102 int line_count;
103 thTreeBranchList **thBranchNext;
104 char *blockname;
105 thTreeOpaque *treedef;
106 int i;
107 int isopen;
108 char *lbuf=0;
109
110 /* thHistZeroLastId(); */
111
|
112 saw 1.3 /* printf("In booktrees\n");*/
|
113 saw 1.1 /* Get the name without the block.test on it */
114 blockname = var->name; /* If name doesn't fit pattern, use whole */
115 if(strcasestr(var->name,BLOCKSTR)==var->name){
116 i = strlen(BLOCKSTR) + 1;
117 if(strcasestr((var->name + i),TREESTR)==(var->name + i)){
118 i += strlen(TREESTR);
119 if(*(var->name + i) == '.'){
120 blockname += i + 1;
121 }
122 }
123 }
124
|
125 saw 1.3 /*printf("Booking tree %s\n",blockname);*/
|
126 saw 1.1
127 if(var->opaque) thRemoveTree(blockname);
128
129 /* We assume for now that thRemoveTree completely removed the opaque definition)
130 */
131 treedef = var->opaque = (thTreeOpaque *) malloc(sizeof(thTreeOpaque));
132 thBranchNext = (thTreeBranchList **) &treedef->branchlistP;
133
134 lines = var->title;
135 line_count = 0;
136 isopen = 0;
137 while(*lines){
138 char *lcopy;
139
140 line_count++;
141 eol = strchr(lines,'\n');
142 if(!eol) {
143 fprintf(stderr,"L %d: Last line of hist block %s has no newline\n"
144 ,line_count,var->name);
145 break;
146 }
147 saw 1.1 if(*(eol+1)=='\0'){ /* This is the last line */
148 if(strcasestr(lines,ENDSTR) == 0)
149 fprintf(stderr,"L %d: Last line of tree block %s is not an END\n"
150 ,line_count,var->name);
151 break;
152 }
153 if(line_count == 1) {
154 char *fname=0;
155 if(strcasestr(lines,BEGINSTR) !=0) {
156 char *p;
157 if(p = strcasestr(lines,"file=")) {
158 p += 5;
159 /* If " or ', grab to next matching char */
160 /* other interpret as variable. But interpret as file if variable not found */
161 if(*p == QUOTECHAR1 || *p == QUOTECHAR2) {
162 char *s; int len;
163 s = p+1;
164 while(*s && *s != *p && *s !='\n') s++;
165 len = (s - p) - 1;
166 fname = malloc(len+1);
167 strncpy(fname,p+1,len);
168 saw 1.1 fname[len] = '\0';
169 } else { /* Probably a variable */
170 char *varname=0; char *s; int len; int index;
171 daVarStruct *varp;
172 s = p;
173 while(*s && !isspace(*s) && *s !='\n') s++;
174 len = (s-p);
175 varname = malloc(len+1);
176 strncpy(varname,p,len);
177 varname[len] = '\0';
178 if(thVarResolve(varname,&varp,&index,1,0)==S_SUCCESS) {
179 printf("%s,type=%d, size=%d\n",varp->name,varp->type,varp->size);
180 printf("%s\n",(char *) varp->varptr);
181 if(varp->type == DAVARSTRING) {
182 fname = malloc(strlen((char *)varp->varptr)+1);
183 strcpy(fname,(char *)varp->varptr);
184 } else if(varp->type == DAVARFSTRING) {
185 fname = malloc(varp->size+1);
186 strncpy(fname,(char *)varp->varptr,varp->size);
187 fname[varp->size] = '\0';
188 p = fname;
189 saw 1.1 while(*p && !isspace(*p)) p++;
190 *p = '\0'; /* Null terminate at first blank */
191 }
192 }
193 if(!fname) {
194 fname = malloc(len+1);
195 strncpy(fname,p,len);
196 fname[len] = '\0';
197 }
198 }
199 }
|
200 saw 1.5 if(p = strcasestr(lines,"test=")) {
201 /* RHS must be a variable */
202 char *varname=0; char *s; int len, testindex;
203 daVarStruct *testp;
204 p += 5;
205 s = p;
206 while(*s && !isspace(*s) && *s !='\n') s++;
207 len = (s-p);
208 varname = (char *) malloc(len+1);
209 strncpy(varname,p,len);
210 varname[len] = '\0';
211 if(thVarResolve(varname,&testp,&testindex,1,0) != S_SUCCESS) {
212 return(S_FAILURE); /* Test flag not registered */
213 /* ASAP we must change this to register variables as they are needed */
214 /* If the variable exists, then we also must check to make sure that
215 the requested index does not exceed the size of the array.
216 a new thVarResolve should also increase the size of the array if
217 it was created by CTP */
218 }
219 treedef->test = testp;
220 treedef->testindex = testindex;
221 saw 1.5 } else {
222 treedef->test = 0; /* No test, always true */
223 }
|
224 saw 1.1 }
225
226 if(fname) {
227 /*printf("Opening Root file %s\n",fname);*/
|
228 saw 1.3 treedef->file = (void *) thRoot_TFile(fname);
|
229 saw 1.1 free(fname);
230 } else {
231 /*printf("Opening Root file %s\n","ctp.tree");*/
|
232 saw 1.3 treedef->file = (void *) thRoot_TFile("ctp.root");
|
233 saw 1.1 }
234
235 /*printf("Call to TTree(\"%s\",\"title\") goes here\n",blockname);*/
|
236 saw 1.3 treedef->treeptr = (void *) thRoot_TTree(blockname);
|
237 saw 1.1
238 if(strcasestr(lines,BEGINSTR) != 0){
239 /* printf("Is a begin\n");*/
240 lines = eol + 1;
241 continue;
242 } else
243 fprintf(stderr,"First line of tree block %s is not a BEGIN\n",var->name);
244 }
245 /* Ready to book the line, Add continuation lines later */
246 lcopy = (char *) malloc(eol-lines+1);
247 strncpy(lcopy,lines,(eol-lines));
248 *(lcopy + (eol-lines)) = '\0';
249 if(!thCleanLine(lcopy)){
250 if(strchr(lcopy,'=')) { /* Start of a new branch */
251 if(lbuf) { /* Do we have a pending branch */
252 /*printf("Passing 1 |%s|\n",lbuf);*/
253 if(thBookaBranch(treedef,lbuf,thBranchNext)==S_SUCCESS){
254 thBranchNext = &((*thBranchNext)->next);
255 } else {
256 fprintf(stderr,"(%s): Tree booking error in line %d\n",var->name,line_count);
257 }
258 saw 1.1 free(lbuf);
259 lbuf = 0;
260 }
261 }
262 if(lbuf) { /* Append */
263 char *lastcomma;
264 char *firstcomma;
265 int addcomma=0;
266 lastcomma = lbuf + strlen(lbuf) - 1;
267 while(*lastcomma == ' ') lastcomma--;
268 if(*lastcomma != ',' && *lastcomma != '=') lastcomma = 0;
269 firstcomma = lcopy;
270 while(*firstcomma == ' ') firstcomma++;
271 if(*firstcomma != ',') firstcomma = 0;
272 if(firstcomma && lastcomma) {
273 *firstcomma = ' ';
274 } else if (!firstcomma && !lastcomma) {
275 addcomma = 1;
276 }
277 lbuf = realloc(lbuf,strlen(lbuf) + strlen(lcopy) + 2);
278 if(addcomma) strcat(lbuf,",");
279 saw 1.1 strcat(lbuf,lcopy);
280 } else { /* Make new lbuf */
281 lbuf = malloc(strlen(lcopy)+1);
282 strcpy(lbuf,lcopy);
283 }
284 }
285 free(lcopy);
286 lines = eol+1;
287 }
288 if(lbuf) { /* Do the last branch we were building */
289 /*printf("Passing 2 |%s|\n",lbuf);*/
290 if(thBookaBranch(treedef,lbuf,thBranchNext)==S_SUCCESS){
291 thBranchNext = &((*thBranchNext)->next);
292 } else {
293 fprintf(stderr,"(%s): Tree booking error in line %d\n",var->name,line_count);
294 }
295 free(lbuf);
296 }
297 /* Update internal table of trees. */
298 {
299 thRBlockList *thisblock,*nextblock,**lastblockp;
300 saw 1.1 nextblock = thRBlockListP;
301 lastblockp = &thRBlockListP;
302 thisblock = thRBlockListP;
303 while(thisblock){
304 if((strcasecmp(thisblock->var->name,var->name)) == 0){
305 /* Replacing a block with a new definition */
306 fprintf(stderr,"Replacing %s with new definition\n",var->name);
307 if(thisblock->var != var){
308 fprintf(stderr,"ERR: Same name, different var pointer\n");
309 }
310 break;
311 }
312 lastblockp = &thisblock->next;
313 thisblock = thisblock->next;
314 }
315 if(!thisblock){ /* Create entry for New block */
316 *lastblockp = thisblock = (thRBlockList *) malloc(sizeof(thRBlockList));
317 thisblock->var = var;
318 thisblock->next = (thRBlockList *) NULL;
319 thisblock->blockname = (char *) malloc(strlen(blockname) + 1);
320 strcpy(thisblock->blockname,blockname);
321 saw 1.1 }
322 }
|
323 saw 1.3 /*printf("Returning from booking a tree\n");*/
|
324 saw 1.1 return(S_SUCCESS);
325 }
326
327 thStatus thBookaBranch(thTreeOpaque *treedef, char *line, thTreeBranchList **thBranchNext)
328 /* Interpret a branch def of the form branch=leaf1,leaf2,leaf3,... */
329 /* For now require the "branch=" part */
330 {
331
332 /* char *long_title;*/
333 int n,nleafs;
334 int lenbrancharg;
335 char *brancharg;
336 char *sleafs,*branchname;
337 thTreeBranchList *Branch;
338 thLeafList **LeafNext;
339 thLeafList *thisleaf;
340 daVarStruct *varp;
341 int vind;
342 char *args[100];
343
344 /*printf("In thBookaBranch\n");*/
345 saw 1.1 if(!(sleafs = strchr(line,'='))) {
346 return(S_FAILURE);
347 }
348 *sleafs=0;
349 sleafs++; /* Pointer to list of leaves */
350 nleafs = thCommas(sleafs,args);
351 if(nleafs <=0) {
352 return(S_FAILURE);
353 }
354 Branch = *thBranchNext = (thTreeBranchList *) malloc(sizeof(thTreeBranchList));
355 Branch->next = (thTreeBranchList *) NULL;
356 branchname = thSpaceStrip(line);
357 Branch->branchname = malloc(strlen(branchname)+1);
358 LeafNext = (thLeafList **) &Branch->leaflistp;
359 strcpy(Branch->branchname,branchname);
360 lenbrancharg = 0;
361 for(n=0;n<nleafs;n++) {
362 char *nameptr;
363 /* Need to look for $name here. name will be the name given to root */
364 args[n] = thSpaceStrip(args[n]);
365 /*printf("Leaf %s\n",args[n]);*/
366 saw 1.1 if(nameptr=strchr(args[n],'$')) *nameptr++=0;
367 if(thVarResolve(args[n],&varp,&vind,0,0) == S_SUCCESS) {
368 char *p, snum[25];
369 /*printf("Index=%d\n",vind);*/
370 thisleaf = *LeafNext = (thLeafList *) malloc(sizeof(thLeafList));
371 /*printf("thisleaf = %x\n",thisleaf);*/
372 thisleaf->next = (thLeafList *) NULL;
373 thisleaf->varp = varp;
374 thisleaf->index = vind;
375 /* Pick a good name */
376 if(nameptr) {
377 thisleaf->name = (char *) malloc(strlen(nameptr)+1);
378 strcpy(thisleaf->name,nameptr);
379 } else {
380 if(p=strpbrk(args[n],"()[]")) {
381 sprintf(snum,"%d",vind+1);
382 thisleaf->name = (char *) malloc(strlen(args[n])+strlen(snum)+2);
383 strncpy(thisleaf->name,args[n],p-args[n]);
384 thisleaf->name[p-args[n]] = '\0';
385 strcat(thisleaf->name,"_");
386 strcat(thisleaf->name,snum);
387 saw 1.1 } else {
388 thisleaf->name = (char *) malloc(strlen(args[n])+1);
389 strcpy(thisleaf->name,args[n]);
390 }
391 }
392 LeafNext = &((*LeafNext)->next);
393 lenbrancharg += strlen(args[n]) + 3;
394 } else {
395 fprintf(stderr,"Bad variable %s\n",args[n]);
396 }
397 }
398 /* Walk down the leaf list and build the Branch call argument */
399 /* What do I do about leaf names with subscripts? */
400 thisleaf = Branch->leaflistp;
401 brancharg = malloc(lenbrancharg+10);
402 brancharg[0] = '\0';
403 while(thisleaf) {
|
404 saw 1.3 /*printf("thisleaf = %x\n",thisleaf);
405 printf("Adding %s to branchlist\n",thisleaf->name);*/
|
406 saw 1.1 strcat(brancharg,thisleaf->name);
407 if(thisleaf->varp->type == DAVARINT) {
408 strcat(brancharg,"/I");
409 thisleaf->leafsize=4;
410 } else if(thisleaf->varp->type == DAVARFLOAT) {
411 strcat(brancharg,"/F");
412 thisleaf->leafsize=4;
413 } else if(thisleaf->varp->type == DAVARDOUBLE) {
414 strcat(brancharg,"/D");
415 thisleaf->leafsize=8;
416 } else {
417 fprintf(stderr,"Variable %s has unknown type\n");
418 }
419
420 if(thisleaf->next) {
421 strcat(brancharg,":");
422 }
423 thisleaf = thisleaf->next;
424 }
425
426 /* Reserve enough space as if they were all double */
427 saw 1.1 Branch->evstruct = (void *) malloc(lenbrancharg*sizeof(double));
428
429 /*
430 * leaflist is the concatenation of all the variable names and types
431 separated by a colon character :
432 The variable name and the variable type are separated by a slash (/).
433 The variable type may be 0,1 or 2 characters. If no type is given,
434 the type of the variable is assumed to be the same as the previous
435 variable. If the first variable does not have a type, it is assumed
436 of type F by default. The list of currently supported types is given below:
437 - C : a character string terminated by the 0 character
438 - B : an 8 bit signed integer (Char_t)
439 - b : an 8 bit unsigned integer (UChar_t)
440 - S : a 16 bit signed integer (Short_t)
441 - s : a 16 bit unsigned integer (UShort_t)
442 - I : a 32 bit signed integer (Int_t)
443 - i : a 32 bit unsigned integer (UInt_t)
444 - F : a 32 bit floating point (Float_t)
445 - D : a 64 bit floating point (Double_t)
446 */
447
|
448 saw 1.3 printf("Branch=%s Leafs=%s\n",Branch->branchname,brancharg);
449 thRoot_Branch(treedef->treeptr,Branch->branchname,(Branch->evstruct),brancharg);
|
450 saw 1.1
451 free(brancharg);
|
452 saw 1.3 printf("Exiting book a branch\n");
|
453 saw 1.1 return(S_SUCCESS);
454 }
455
456 thStatus thFillTreeV(daVarStruct *var){
457 thTreeOpaque *treedef;
458 thTreeBranchList *thisbranch;
459 thLeafList *thisleaf;
460 void *structp;
|
461 saw 1.3 /* printf("Executing Tree %s\n",var->name);*/
|
462 saw 1.1 treedef = ((thTreeOpaque *)(var->opaque));
463 thisbranch = treedef->branchlistP;
|
464 saw 1.5 if(! (treedef->test ? *((DAINT *) treedef->test->varptr
465 + treedef->testindex) : 1)) {
466 return(S_SUCCESS); /* Test was false */
467 }
|
468 saw 1.1 while(thisbranch) {
469 structp = thisbranch->evstruct;
470 /* printf("Filling branch %s at %x\n",thisbranch->branchname,structp);*/
471 thisleaf = thisbranch->leaflistp;
472 while(thisleaf) {
473 if(thisleaf->varp->type == DAVARINT) {
474 *((DAINT *)(structp))++ = *((DAINT *)thisleaf->varp->varptr
475 + thisleaf->index);
476 /* printf(" %s=%d\n",thisleaf->name,*((DAINT *)thisleaf->varp->varptr
477 + thisleaf->index));*/
478 } else if(thisleaf->varp->type == DAVARFLOAT) {
479 *((DAFLOAT *)(structp))++ = *((DAFLOAT *)thisleaf->varp->varptr
480 + thisleaf->index);
481 /* printf(" %s=%f\n",thisleaf->name,*((DAFLOAT *)thisleaf->varp->varptr
482 + thisleaf->index));*/
483 } else if(thisleaf->varp->type == DAVARDOUBLE) {
484 *((DADOUBLE *)(structp))++ = *((DADOUBLE *)thisleaf->varp->varptr
485 + thisleaf->index);
486 /* printf(" %s=%lf\n",thisleaf->name,*((DADOUBLE *)thisleaf->varp->varptr
487 + thisleaf->index));*/
488 }
489 saw 1.1 thisleaf = thisleaf->next;
490 }
491 thisbranch = thisbranch->next;
492 }
|
493 saw 1.3 thRoot_Fill(treedef->treeptr);
|
494 saw 1.1
495 (*((DAINT *)var->varptr))++; /* Increment block counter */
496 return(S_SUCCESS);
497 }
498 thStatus thClearTreeV(daVarStruct *var){
499
|
500 saw 1.3 /* printf("Clearing Tree %s\n",var->name); */
|
501 saw 1.1
502 (*((DAINT *)var->varptr)) = 0; /* Increment block counter */
503 return(S_SUCCESS);
504 }
505 thStatus thWriteTreeV(daVarStruct *var){
506
|
507 saw 1.3 /* printf("Writing Tree %s\n",var->name); */
508 thRoot_Write(((thTreeOpaque *)(var->opaque))->file);
|
509 saw 1.1
510 (*((DAINT *)var->varptr)) = 0; /* Increment block counter */
511 return(S_SUCCESS);
512 }
513 thStatus thCloseTreeV(daVarStruct *var){
514
|
515 saw 1.3 /*printf("Closing Tree %s\n",var->name);*/
516 thRoot_Close(((thTreeOpaque *)(var->opaque))->file);
|
517 saw 1.1
518 (*((DAINT *)var->varptr)) = 0; /* Increment block counter */
519 return(S_SUCCESS);
520 }
521
522 thStatus thRemoveTree(char *treename) {
523 printf("Dummy routine to remove tree %s\n",treename);
524 return(S_SUCCESS);
525 }
526
527 /*
528 int thtreewrite_()
529 {
|
530 saw 1.3 thRoot_Write();
|
531 saw 1.1 }
532 */
|
533 saw 1.4
534 #else
535
536 thStatus thBookTree(daVarStruct *var) {
537 return(S_SUCCESS);
538 }
539
540 thStatus thFillTreeV(daVarStruct *var) {
541 return(S_SUCCESS);
542 }
543 thStatus thClearTreeV(daVarStruct *var) {
544 return(S_SUCCESS);
545 }
546 thStatus thWriteTreeV(daVarStruct *var) {
547 return(S_SUCCESS);
548 }
549 thStatus thCloseTreeV(daVarStruct *var) {
550 return(S_SUCCESS);
551 }
|
552 saw 1.1
553 #endif
|