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