#ifdef ROOTTREE /*----------------------------------------------------------------------------- * Copyright (c) 1999 Thomas Jefferson National Accelerator Facility * * This software was developed under a United States Government license * described in the NOTICE file included as part of this distribution. * * Stephen A. Wood, 12000 Jefferson Ave., Newport News, VA 23606 * Email: saw@jlab.org Tel: (758) 269-7367 Fax: (757) 269-5235 *----------------------------------------------------------------------------- * * Description: * Book ROOT trees. * * Author: Stephen Wood, CEBAF Hall C * * Revision History: * $Log: thTree.c,v $ * Revision 1.1 2002/07/31 20:07:48 saw * Add files for ROOT Trees * * Revision 1.1 1999/08/25 13:16:07 saw * *** empty log message *** * */ #include #include #include #include #include "daVar.h" #include "th.h" #include "thInternal.h" #include "thUtils.h" extern daVarStatus thTreeRHandler(); struct thLeafList { /* Variable and index list */ struct thLeafList *next; char *name; int leafsize; /* Number of bytes in leaf */ char leaftype; /* Single letter with leaf type */ daVarStruct *varp; int index; }; typedef struct thLeafList thLeafList; struct thTreeBranchList { struct thTreeBranchList *next; char *branchname; /* Block name without the "block.hist" */ void *evstruct; /* Event structure to fill with data */ struct thLeafList *leaflistp; }; typedef struct thTreeBranchList thTreeBranchList; struct thTreeOpaque { /* Opaque structure for histogram definition */ void *file; /* void *file Need to point to structure that has file info. File structures will also be on a linked list so that we a new file is opened, you can see if it exists. Wait, we should just use davars. Make a new class for files? ? */ void *treeptr; /* Pointer to tree object */ daVarStruct *test; int testindex; thTreeBranchList *branchlistP; }; typedef struct thTreeOpaque thTreeOpaque; struct thRBlockList { struct thRBlockList *next; char *blockname; /* Block name without the "block.tree" */ daVarStruct *var; /* Varptr points to # times called Title is code from file. opaque is pointer to hist speclist */ }; typedef struct thRBlockList thRBlockList; thRBlockList *thRBlockListP; /* Pointer to list of tree blocks */ thStatus thBookaBranch(thTreeOpaque *tree, char *line, thTreeBranchList **thBranchNext); /*thStatus thExecuteaHist(thHistSpecList *Hist);*/ thStatus thRemoveTree(char *block_name); thStatus thBookTree(daVarStruct *var) { char *lines,*eol; int line_count; thTreeBranchList **thBranchNext; char *blockname; thTreeOpaque *treedef; int i; int isopen; char *lbuf=0; /* thHistZeroLastId(); */ printf("In booktrees\n"); /* Get the name without the block.test on it */ blockname = var->name; /* If name doesn't fit pattern, use whole */ if(strcasestr(var->name,BLOCKSTR)==var->name){ i = strlen(BLOCKSTR) + 1; if(strcasestr((var->name + i),TREESTR)==(var->name + i)){ i += strlen(TREESTR); if(*(var->name + i) == '.'){ blockname += i + 1; } } } printf("Booking tree %s\n",blockname); if(var->opaque) thRemoveTree(blockname); /* We assume for now that thRemoveTree completely removed the opaque definition) */ treedef = var->opaque = (thTreeOpaque *) malloc(sizeof(thTreeOpaque)); thBranchNext = (thTreeBranchList **) &treedef->branchlistP; lines = var->title; line_count = 0; isopen = 0; while(*lines){ char *lcopy; line_count++; eol = strchr(lines,'\n'); if(!eol) { fprintf(stderr,"L %d: Last line of hist block %s has no newline\n" ,line_count,var->name); break; } if(*(eol+1)=='\0'){ /* This is the last line */ if(strcasestr(lines,ENDSTR) == 0) fprintf(stderr,"L %d: Last line of tree block %s is not an END\n" ,line_count,var->name); break; } if(line_count == 1) { char *fname=0; if(strcasestr(lines,BEGINSTR) !=0) { char *p; if(p = strcasestr(lines,"file=")) { p += 5; /* If " or ', grab to next matching char */ /* other interpret as variable. But interpret as file if variable not found */ if(*p == QUOTECHAR1 || *p == QUOTECHAR2) { char *s; int len; s = p+1; while(*s && *s != *p && *s !='\n') s++; len = (s - p) - 1; fname = malloc(len+1); strncpy(fname,p+1,len); fname[len] = '\0'; } else { /* Probably a variable */ char *varname=0; char *s; int len; int index; daVarStruct *varp; s = p; while(*s && !isspace(*s) && *s !='\n') s++; len = (s-p); varname = malloc(len+1); strncpy(varname,p,len); varname[len] = '\0'; if(thVarResolve(varname,&varp,&index,1,0)==S_SUCCESS) { printf("%s,type=%d, size=%d\n",varp->name,varp->type,varp->size); printf("%s\n",(char *) varp->varptr); if(varp->type == DAVARSTRING) { fname = malloc(strlen((char *)varp->varptr)+1); strcpy(fname,(char *)varp->varptr); } else if(varp->type == DAVARFSTRING) { fname = malloc(varp->size+1); strncpy(fname,(char *)varp->varptr,varp->size); fname[varp->size] = '\0'; p = fname; while(*p && !isspace(*p)) p++; *p = '\0'; /* Null terminate at first blank */ } } if(!fname) { fname = malloc(len+1); strncpy(fname,p,len); fname[len] = '\0'; } } } } if(fname) { /*printf("Opening Root file %s\n",fname);*/ treedef->file = (void *) thRoot_TFile__FPc(fname); free(fname); } else { /*printf("Opening Root file %s\n","ctp.tree");*/ treedef->file = (void *) thRoot_TFile__FPc("ctp.root"); } /*printf("Call to TTree(\"%s\",\"title\") goes here\n",blockname);*/ treedef->treeptr = (void *) thRoot_TTree__FPc(blockname); if(strcasestr(lines,BEGINSTR) != 0){ /* printf("Is a begin\n");*/ lines = eol + 1; continue; } else fprintf(stderr,"First line of tree block %s is not a BEGIN\n",var->name); } /* Ready to book the line, Add continuation lines later */ lcopy = (char *) malloc(eol-lines+1); strncpy(lcopy,lines,(eol-lines)); *(lcopy + (eol-lines)) = '\0'; if(!thCleanLine(lcopy)){ if(strchr(lcopy,'=')) { /* Start of a new branch */ if(lbuf) { /* Do we have a pending branch */ /*printf("Passing 1 |%s|\n",lbuf);*/ if(thBookaBranch(treedef,lbuf,thBranchNext)==S_SUCCESS){ thBranchNext = &((*thBranchNext)->next); } else { fprintf(stderr,"(%s): Tree booking error in line %d\n",var->name,line_count); } free(lbuf); lbuf = 0; } } if(lbuf) { /* Append */ char *lastcomma; char *firstcomma; int addcomma=0; lastcomma = lbuf + strlen(lbuf) - 1; while(*lastcomma == ' ') lastcomma--; if(*lastcomma != ',' && *lastcomma != '=') lastcomma = 0; firstcomma = lcopy; while(*firstcomma == ' ') firstcomma++; if(*firstcomma != ',') firstcomma = 0; if(firstcomma && lastcomma) { *firstcomma = ' '; } else if (!firstcomma && !lastcomma) { addcomma = 1; } lbuf = realloc(lbuf,strlen(lbuf) + strlen(lcopy) + 2); if(addcomma) strcat(lbuf,","); strcat(lbuf,lcopy); } else { /* Make new lbuf */ lbuf = malloc(strlen(lcopy)+1); strcpy(lbuf,lcopy); } } free(lcopy); lines = eol+1; } if(lbuf) { /* Do the last branch we were building */ /*printf("Passing 2 |%s|\n",lbuf);*/ if(thBookaBranch(treedef,lbuf,thBranchNext)==S_SUCCESS){ thBranchNext = &((*thBranchNext)->next); } else { fprintf(stderr,"(%s): Tree booking error in line %d\n",var->name,line_count); } free(lbuf); } /* Update internal table of trees. */ { thRBlockList *thisblock,*nextblock,**lastblockp; nextblock = thRBlockListP; lastblockp = &thRBlockListP; thisblock = thRBlockListP; while(thisblock){ if((strcasecmp(thisblock->var->name,var->name)) == 0){ /* Replacing a block with a new definition */ fprintf(stderr,"Replacing %s with new definition\n",var->name); if(thisblock->var != var){ fprintf(stderr,"ERR: Same name, different var pointer\n"); } break; } lastblockp = &thisblock->next; thisblock = thisblock->next; } if(!thisblock){ /* Create entry for New block */ *lastblockp = thisblock = (thRBlockList *) malloc(sizeof(thRBlockList)); thisblock->var = var; thisblock->next = (thRBlockList *) NULL; thisblock->blockname = (char *) malloc(strlen(blockname) + 1); strcpy(thisblock->blockname,blockname); } } /* printf("Returning from booking a tree\n");*/ return(S_SUCCESS); } thStatus thBookaBranch(thTreeOpaque *treedef, char *line, thTreeBranchList **thBranchNext) /* Interpret a branch def of the form branch=leaf1,leaf2,leaf3,... */ /* For now require the "branch=" part */ { /* char *long_title;*/ int n,nleafs; int lenbrancharg; char *brancharg; char *sleafs,*branchname; thTreeBranchList *Branch; thLeafList **LeafNext; thLeafList *thisleaf; daVarStruct *varp; int vind; char *args[100]; /*printf("In thBookaBranch\n");*/ if(!(sleafs = strchr(line,'='))) { return(S_FAILURE); } *sleafs=0; sleafs++; /* Pointer to list of leaves */ nleafs = thCommas(sleafs,args); if(nleafs <=0) { return(S_FAILURE); } Branch = *thBranchNext = (thTreeBranchList *) malloc(sizeof(thTreeBranchList)); Branch->next = (thTreeBranchList *) NULL; branchname = thSpaceStrip(line); Branch->branchname = malloc(strlen(branchname)+1); LeafNext = (thLeafList **) &Branch->leaflistp; strcpy(Branch->branchname,branchname); lenbrancharg = 0; for(n=0;nnext = (thLeafList *) NULL; thisleaf->varp = varp; thisleaf->index = vind; /* Pick a good name */ if(nameptr) { thisleaf->name = (char *) malloc(strlen(nameptr)+1); strcpy(thisleaf->name,nameptr); } else { if(p=strpbrk(args[n],"()[]")) { sprintf(snum,"%d",vind+1); thisleaf->name = (char *) malloc(strlen(args[n])+strlen(snum)+2); strncpy(thisleaf->name,args[n],p-args[n]); thisleaf->name[p-args[n]] = '\0'; strcat(thisleaf->name,"_"); strcat(thisleaf->name,snum); } else { thisleaf->name = (char *) malloc(strlen(args[n])+1); strcpy(thisleaf->name,args[n]); } } LeafNext = &((*LeafNext)->next); lenbrancharg += strlen(args[n]) + 3; } else { fprintf(stderr,"Bad variable %s\n",args[n]); } } /* Walk down the leaf list and build the Branch call argument */ /* What do I do about leaf names with subscripts? */ thisleaf = Branch->leaflistp; brancharg = malloc(lenbrancharg+10); brancharg[0] = '\0'; while(thisleaf) { /* printf("thisleaf = %x\n",thisleaf);*/ /*printf("Adding %s to branchlist\n",thisleaf->name);*/ strcat(brancharg,thisleaf->name); if(thisleaf->varp->type == DAVARINT) { strcat(brancharg,"/I"); thisleaf->leafsize=4; } else if(thisleaf->varp->type == DAVARFLOAT) { strcat(brancharg,"/F"); thisleaf->leafsize=4; } else if(thisleaf->varp->type == DAVARDOUBLE) { strcat(brancharg,"/D"); thisleaf->leafsize=8; } else { fprintf(stderr,"Variable %s has unknown type\n"); } if(thisleaf->next) { strcat(brancharg,":"); } thisleaf = thisleaf->next; } /* Reserve enough space as if they were all double */ Branch->evstruct = (void *) malloc(lenbrancharg*sizeof(double)); /* * leaflist is the concatenation of all the variable names and types separated by a colon character : The variable name and the variable type are separated by a slash (/). The variable type may be 0,1 or 2 characters. If no type is given, the type of the variable is assumed to be the same as the previous variable. If the first variable does not have a type, it is assumed of type F by default. The list of currently supported types is given below: - C : a character string terminated by the 0 character - B : an 8 bit signed integer (Char_t) - b : an 8 bit unsigned integer (UChar_t) - S : a 16 bit signed integer (Short_t) - s : a 16 bit unsigned integer (UShort_t) - I : a 32 bit signed integer (Int_t) - i : a 32 bit unsigned integer (UInt_t) - F : a 32 bit floating point (Float_t) - D : a 64 bit floating point (Double_t) */ /*printf("Branch=%s Leafs=%s\n",Branch->branchname,brancharg);*/ thRoot_Branch__FP5TTreePcPvT1(treedef->treeptr,Branch->branchname,(Branch->evstruct),brancharg); free(brancharg); /*printf("Exiting book a branch\n");*/ return(S_SUCCESS); } thStatus thFillTreeV(daVarStruct *var){ thTreeOpaque *treedef; thTreeBranchList *thisbranch; thLeafList *thisleaf; void *structp; /* printf("Executing Tree %s\n",var->name);*/ treedef = ((thTreeOpaque *)(var->opaque)); thisbranch = treedef->branchlistP; while(thisbranch) { structp = thisbranch->evstruct; /* printf("Filling branch %s at %x\n",thisbranch->branchname,structp);*/ thisleaf = thisbranch->leaflistp; while(thisleaf) { if(thisleaf->varp->type == DAVARINT) { *((DAINT *)(structp))++ = *((DAINT *)thisleaf->varp->varptr + thisleaf->index); /* printf(" %s=%d\n",thisleaf->name,*((DAINT *)thisleaf->varp->varptr + thisleaf->index));*/ } else if(thisleaf->varp->type == DAVARFLOAT) { *((DAFLOAT *)(structp))++ = *((DAFLOAT *)thisleaf->varp->varptr + thisleaf->index); /* printf(" %s=%f\n",thisleaf->name,*((DAFLOAT *)thisleaf->varp->varptr + thisleaf->index));*/ } else if(thisleaf->varp->type == DAVARDOUBLE) { *((DADOUBLE *)(structp))++ = *((DADOUBLE *)thisleaf->varp->varptr + thisleaf->index); /* printf(" %s=%lf\n",thisleaf->name,*((DADOUBLE *)thisleaf->varp->varptr + thisleaf->index));*/ } thisleaf = thisleaf->next; } thisbranch = thisbranch->next; } thRoot_Fill__FP5TTree(treedef->treeptr); (*((DAINT *)var->varptr))++; /* Increment block counter */ return(S_SUCCESS); } thStatus thClearTreeV(daVarStruct *var){ printf("Clearing Tree %s\n",var->name); (*((DAINT *)var->varptr)) = 0; /* Increment block counter */ return(S_SUCCESS); } thStatus thWriteTreeV(daVarStruct *var){ printf("Writing Tree %s\n",var->name); thRoot_Write__FP14thRootFileList(((thTreeOpaque *)(var->opaque))->file); (*((DAINT *)var->varptr)) = 0; /* Increment block counter */ return(S_SUCCESS); } thStatus thCloseTreeV(daVarStruct *var){ printf("Closing Tree %s\n",var->name); thRoot_Close__FP14thRootFileList(((thTreeOpaque *)(var->opaque))->file); (*((DAINT *)var->varptr)) = 0; /* Increment block counter */ return(S_SUCCESS); } thStatus thRemoveTree(char *treename) { printf("Dummy routine to remove tree %s\n",treename); return(S_SUCCESS); } /* int thtreewrite_() { thRoot_Write__Fv(); } */ #endif