diff --git a/.gitignore b/.gitignore index 2603f0df93e17739368bab554e6ccaf4a47de015..aca04a8a200f82339110d7cd4898be45a44fc409 100644 --- a/.gitignore +++ b/.gitignore @@ -33,6 +33,7 @@ examples/*.root examples/*.log.* # This is auto generated by hodtest.C examples/db_cratemap.dat +examples/report.out # Working directory work diff --git a/Makefile b/Makefile index 96eeb7a45b67149f99e50bf9be87ee8c7f041a95..0b86cf7a6e7325acd369ee1caa32f80635ca3f15 100644 --- a/Makefile +++ b/Makefile @@ -22,7 +22,8 @@ SRC = src/THcInterface.cxx src/THcParmList.cxx src/THcAnalyzer.cxx \ src/THcSpacePoint.cxx src/THcDCTrack.cxx \ src/THcShower.cxx src/THcShowerPlane.cxx \ src/THcRawShowerHit.cxx \ - src/THcAerogel.cxx src/THcAerogelHit.cxx + src/THcAerogel.cxx src/THcAerogelHit.cxx \ + src/THcFormula.cxx # Name of your package. # The shared library that will be built will get the name lib$(PACKAGE).so diff --git a/SConscript.py b/SConscript.py index e346e9aac0d0f7de3c0d8328dd9fabe985d4cf83..63f47f41a8552c57c6725a803ec2ec1416b02db4 100644 --- a/SConscript.py +++ b/SConscript.py @@ -17,6 +17,7 @@ hcheaders = Split(""" src/THcDriftChamber.h src/THcRawDCHit.h src/THcDCHit.h src/THcDCWire.h src/THcSpacePoint.h src/THcDCLookupTTDConv.h src/THcDCTimeToDistConv.h src/THcShower.h src/THcShowerPlane.h src/THcRawShowerHit.h src/THcAerogel.h src/THcAerogelHit.h src/THcGlobals.h src/THcDCTrack.h + src/THcFormula.h src/HallC_LinkDef.h """) pbaseenv.RootCint(roothcdict,hcheaders) diff --git a/examples/hodtest.C b/examples/hodtest.C index 982e284adffdc261d98dec97cbf39ec5f105b017..bac859d6ad0a95f8560874f3ba8bda6b2b138151 100644 --- a/examples/hodtest.C +++ b/examples/hodtest.C @@ -76,4 +76,5 @@ // analyzer->SetSummaryFile("summary_example.log"); // optional analyzer->Process(run); // start the actual analysis + analyzer->PrintReport("report.template","report.out"); } diff --git a/examples/report.template b/examples/report.template new file mode 100644 index 0000000000000000000000000000000000000000..5856b9fa3ddd981872b1450616f7bd56e24a7278 --- /dev/null +++ b/examples/report.template @@ -0,0 +1,34 @@ + + This is a report template file. + +It can be used to create simple run summary/statistics output files. + +To produce a report, put in your analysis steering script, the line + + analyzer->PrintReport(templatefilename, reportfilename); + +where analyzer is your analyzer object. + +The template file is copied to the output file, except that anything +inside of the braces gets evaluated. If the braces contain a string variable, +the value of variable replaces the braced name. Otherwise what is +in the braces is evaluated as an expression. Currently the expression can be +composed of Hall C style parameter variables, cut results (not really too usefull) +and cut statistics. (Number of times called and number of times passed.) + +For example, {100*Pedestal_event.npassed/Pedestal_event.ncalled:%.2f}% is the percentage of events that were pedestal events. + +Horizontal drift chamber z positions: +Chamber 1: {hdc_zpos[0]:%6.2f} {hdc_zpos[1]:%6.2f} {hdc_zpos[2]:%6.2f} {hdc_zpos[3]:%6.2f} {hdc_zpos[4]:%6.2f} {hdc_zpos[5]:%6.2f} +Chamber 2: {hdc_zpos[6]:%6.2f} {hdc_zpos[7]:%6.2f} {hdc_zpos[8]:%6.2f} {hdc_zpos[9]:%6.2f} {hdc_zpos[10]:%6.2f} {hdc_zpos[11]:%6.2f} + +The expression result can be formatted by putting a ":" followed by +a c-style format after the expression. + +The HMS reconstruction coefficient file name is {h_recon_coeff_filename} +The names of the HMS drift chamber planes are: {hdc_plane_names} + +Later, such things as hardware scalers will be added to the set of variables +that can be used in expressions. + + diff --git a/src/HallC_LinkDef.h b/src/HallC_LinkDef.h index 53a5b40a5c2f265f7b3f326ea2590a8b1c8ad329..7a49293269021fffad2ba8283b1f6df74218a61a 100644 --- a/src/HallC_LinkDef.h +++ b/src/HallC_LinkDef.h @@ -33,5 +33,6 @@ #pragma link C++ class THcRawShowerHit+; #pragma link C++ class THcAerogel+; #pragma link C++ class THcAerogelHit+; +#pragma link C++ class THcFormula+; #endif diff --git a/src/THcAnalyzer.cxx b/src/THcAnalyzer.cxx index de063359287e3a9b2ff323dbf890aefe47cf0c32..d238146d4de58a6f40c9e3ff1a4c2a4cca7fe0dc 100644 --- a/src/THcAnalyzer.cxx +++ b/src/THcAnalyzer.cxx @@ -24,11 +24,16 @@ #include "THcAnalyzer.h" #include "THaBenchmark.h" #include "TList.h" +#include "THcParmList.h" +#include "THcFormula.h" +#include "THcGlobals.h" +#include "TMath.h" #include <fstream> #include <algorithm> #include <iomanip> #include <cstring> +#include <iostream> using namespace std; @@ -52,6 +57,78 @@ THcAnalyzer::~THcAnalyzer() } +//_____________________________________________________________________________ +void THcAnalyzer::PrintReport(const char* templatefile, const char* ofile) +{ + // Copy template to ofile, replacing {stuff} with the evaluated + // value of stuff. + ifstream ifile; + ifile.open(templatefile); + + if(!ifile.is_open()) { + cout << "Error opening template file " << templatefile << endl; + return; + } + + ofstream ostr(ofile); + + if(!ostr.is_open()) { + cout << "Error opening report output file " << ofile << endl; + } + + // In principle, we should allow braces to be escaped. But for + // now we won't. Existing template files don't seem to output + // any braces + for(string line; getline(ifile, line);) { + // cout << line << endl; + string::size_type start; + while((start = line.find('{',0)) != string::npos) { + // cout << start << endl; + string::size_type end = line.find('}',start); + if(end==string::npos) break; // No more expressions on the line + string expression=line.substr(start+1,end-start-1); + string::size_type formatpos = expression.find(':',0); + string format; + if(formatpos != string::npos) { + format=expression.substr(formatpos+1); + expression=expression.substr(0,formatpos); + // cout << "|" << expression << "|" << format << "|" << endl; + } + // Should we first check if the expression can be simply a variable + // or index into variable? + // For now, first check if it is a string. + // If not, then evaluate as an expression. + string replacement; + if(const char *textstring=gHcParms->GetString(expression)) { + // cout << expression << " is a string with value " << textstring << endl; + if(format.empty()) format = "%s"; + replacement=Form(format.c_str(),textstring); + } else { + THcFormula* formula = new THcFormula("temp",expression.c_str(),gHcParms, gHaCuts); + Double_t value=formula->Eval(); + // If the value is close to integer and no format is defined + // use "%.0f" to print out integer + if(format.empty()) { + if(TMath::Abs(value-TMath::Nint(value)) < 0.0000001) { + format = "%.0f"; + } else { + format = "%f"; + } + } + replacement=Form(format.c_str(),value); + } + // cout << "Replacement:" << replacement << endl; + line.replace(start,end-start+1,replacement); + } + ostr << line << endl; + } + ostr.close(); + ifile.close(); + + return; +} + + //_____________________________________________________________________________ ClassImp(THcAnalyzer) diff --git a/src/THcAnalyzer.h b/src/THcAnalyzer.h index 3506ac50ef33db55e40ad69cb2a264b7c6c43b0b..e57d75e361826b42c4c310bfaaa4c76ef7c71992 100644 --- a/src/THcAnalyzer.h +++ b/src/THcAnalyzer.h @@ -18,6 +18,8 @@ public: void SetPedestalEvtype( Int_t evtype ) { fPedestalEvtype = evtype; } + void PrintReport( const char* templatefile, const char* ofile); + protected: Int_t fPedestalEvtype; diff --git a/src/THcFormula.cxx b/src/THcFormula.cxx new file mode 100644 index 0000000000000000000000000000000000000000..a46b0282d208374148ac26f2e7556d00e5cc66f6 --- /dev/null +++ b/src/THcFormula.cxx @@ -0,0 +1,145 @@ +//*-- Author : Stephen Wood 17-Oct-2013 + +////////////////////////////////////////////////////////////////////////// +// +// THcFormula +// +// Tweaked THaFormula. If cutname.scaler is used in a formula, then +// it is evaluated as the number of times that the cut passed. +// Use EVariableType of kUndefined to indicate cut scaler in list of +// variables used in the formula +// +////////////////////////////////////////////////////////////////////////// + +#include "THcFormula.h" +#include "THaVarList.h" +#include "THaCutList.h" +#include "THaCut.h" + +#include <iostream> + +using namespace std; + +static const Double_t kBig = 1e38; // Error value + +//_____________________________________________________________________________ +THcFormula::THcFormula(const char* name, const char* expression, + const THaVarList* vlst, const THaCutList* clst ) : + THaFormula() +{ + + // We have to duplicate the TFormula constructor code here because of + // the calls DefinedVariable. Our version will only get called if + // to Compile(). Compile() only works if fVarList is set. + fVarList = vlst; + fCutList = clst; + + SetName(name); + + //eliminate blanks in expression + Int_t nch = strlen(expression); + char *expr = new char[nch+1]; + Int_t j = 0; + for (Int_t i=0;i<nch;i++) { + if (expression[i] == ' ') continue; + if (i > 0 && (expression[i] == '*') && (expression[i-1] == '*')) { + expr[j-1] = '^'; + continue; + } + expr[j] = expression[i]; j++; + } + expr[j] = 0; + if (j) SetTitle(expr); + delete [] expr; + + Compile(); // This calls our own Compile() +} + + +//_____________________________________________________________________________ +THcFormula::~THcFormula() +{ + // Destructor +} + +//_____________________________________________________________________________ +Int_t THcFormula::DefinedCut( const TString& name ) +{ + // Check if 'name' is a known cut. If so, enter it in the local list of + // variables used in this formula. + + EVariableType thistype; + TString realname; + Int_t period = name.Index('.'); + if(period < 0) { + realname = name; + thistype = kCut; + } else { + realname = name(0,period); + TString attribute(name(period+1,name.Length()-period-1)); + if(attribute.CompareTo("scaler")==0 || attribute.CompareTo("npassed")==0) { + thistype = (EVariableType) kCutScaler; + } else if (attribute.CompareTo("ncalled")==0) { + thistype = (EVariableType) kCutNCalled; + } else { + thistype = kUndefined; + } + } + + // Cut names are obviously only valid if there is a list of existing cuts + if( fCutList ) { + const THaCut* pcut = fCutList->FindCut( realname ); + if( pcut ) { + if( fNcodes >= kMAXCODES ) return -1; + // See if this cut already used earlier in this new cut + FVarDef_t* def = fVarDef; + for( Int_t i=0; i<fNcodes; i++, def++ ) { + if( def->type == thistype && pcut == def->code ) + return i; + } + def->type = thistype; + def->code = pcut; + def->index = 0; + fNpar = 0; + return fNcodes++; + } + } + return -1; +} + +//_____________________________________________________________________________ +Double_t THcFormula::DefinedValue( Int_t i ) +{ + // Get value of i-th variable in the formula + // If the i-th variable is a cut, return its last result + // (calculated at the last evaluation). + // If the variable is a string, return value of its character value + +#ifdef WITH_DEBUG + R__ASSERT( i>=0 && i<fNcodes ); +#endif + FVarDef_t* def = fVarDef+i; + const void* ptr = def->code; + if( !ptr ) return kBig; + switch( def->type ) { + case kVariable: + case kString: + return reinterpret_cast<const THaVar*>(ptr)->GetValue( def->index ); + break; + case kCut: + return reinterpret_cast<const THaCut*>(ptr)->GetResult(); + break; + case kCutScaler: + return reinterpret_cast<const THaCut*>(ptr)->GetNPassed(); + break; + case kCutNCalled: + return reinterpret_cast<const THaCut*>(ptr)->GetNCalled(); + break; + default: + return kBig; + } +} + +//_____________________________________________________________________________ + +ClassImp(THcFormula) diff --git a/src/THcFormula.h b/src/THcFormula.h new file mode 100644 index 0000000000000000000000000000000000000000..13e854c1320cd6dd397834bce0202e20106442ae --- /dev/null +++ b/src/THcFormula.h @@ -0,0 +1,30 @@ +#ifndef ROOT_THcFormula +#define ROOT_THcFormula + +////////////////////////////////////////////////////////////////////////// +// +// THcFormula +// +////////////////////////////////////////////////////////////////////////// + +#include "THaFormula.h" + +class THcFormula : public THaFormula { + +public: + + THcFormula( const char* name, const char* formula, + const THaVarList*, const THaCutList* clst); + virtual ~THcFormula(); + + virtual Double_t DefinedValue( Int_t i); + virtual Int_t DefinedCut( const TString& variable); + +protected: + + enum {kCutScaler = kString+1}; + enum {kCutNCalled = kCutScaler+1}; + ClassDef(THcFormula,0) // Formula with cut scalers +}; + +#endif