Skip to content
Snippets Groups Projects
Commit f0efa3a6 authored by Stephen A. Wood's avatar Stephen A. Wood
Browse files

Add template driven end of run reports to analyzer class

Inspired by ENGINE/CTP report generator
  Reports generated by
    THcAnalyzer::PrintReport(templatefilename,outputfilename)
    template is copied to output, {stuff} is replaced by the
       value of stuff.  Value can be formated with c formater, eg.
           {stuff:%.2f}
  ThcFormula added to allow more flexibility of variables.
    Can get number of times cuts pass or are called with:
       cutname.npassed (or cutname.scaler) and cutname.ncalled
parent a3ae0ff1
No related branches found
No related tags found
No related merge requests found
...@@ -33,6 +33,7 @@ examples/*.root ...@@ -33,6 +33,7 @@ examples/*.root
examples/*.log.* examples/*.log.*
# This is auto generated by hodtest.C # This is auto generated by hodtest.C
examples/db_cratemap.dat examples/db_cratemap.dat
examples/report.out
# Working directory # Working directory
work work
...@@ -22,7 +22,8 @@ SRC = src/THcInterface.cxx src/THcParmList.cxx src/THcAnalyzer.cxx \ ...@@ -22,7 +22,8 @@ SRC = src/THcInterface.cxx src/THcParmList.cxx src/THcAnalyzer.cxx \
src/THcSpacePoint.cxx src/THcDCTrack.cxx \ src/THcSpacePoint.cxx src/THcDCTrack.cxx \
src/THcShower.cxx src/THcShowerPlane.cxx \ src/THcShower.cxx src/THcShowerPlane.cxx \
src/THcRawShowerHit.cxx \ src/THcRawShowerHit.cxx \
src/THcAerogel.cxx src/THcAerogelHit.cxx src/THcAerogel.cxx src/THcAerogelHit.cxx \
src/THcFormula.cxx
# Name of your package. # Name of your package.
# The shared library that will be built will get the name lib$(PACKAGE).so # The shared library that will be built will get the name lib$(PACKAGE).so
......
...@@ -17,6 +17,7 @@ hcheaders = Split(""" ...@@ -17,6 +17,7 @@ hcheaders = Split("""
src/THcDriftChamber.h src/THcRawDCHit.h src/THcDCHit.h src/THcDCWire.h src/THcSpacePoint.h 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/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/THcRawShowerHit.h src/THcAerogel.h src/THcAerogelHit.h src/THcGlobals.h src/THcDCTrack.h
src/THcFormula.h
src/HallC_LinkDef.h src/HallC_LinkDef.h
""") """)
pbaseenv.RootCint(roothcdict,hcheaders) pbaseenv.RootCint(roothcdict,hcheaders)
......
...@@ -76,4 +76,5 @@ ...@@ -76,4 +76,5 @@
// analyzer->SetSummaryFile("summary_example.log"); // optional // analyzer->SetSummaryFile("summary_example.log"); // optional
analyzer->Process(run); // start the actual analysis analyzer->Process(run); // start the actual analysis
analyzer->PrintReport("report.template","report.out");
} }
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.
...@@ -33,5 +33,6 @@ ...@@ -33,5 +33,6 @@
#pragma link C++ class THcRawShowerHit+; #pragma link C++ class THcRawShowerHit+;
#pragma link C++ class THcAerogel+; #pragma link C++ class THcAerogel+;
#pragma link C++ class THcAerogelHit+; #pragma link C++ class THcAerogelHit+;
#pragma link C++ class THcFormula+;
#endif #endif
...@@ -24,11 +24,16 @@ ...@@ -24,11 +24,16 @@
#include "THcAnalyzer.h" #include "THcAnalyzer.h"
#include "THaBenchmark.h" #include "THaBenchmark.h"
#include "TList.h" #include "TList.h"
#include "THcParmList.h"
#include "THcFormula.h"
#include "THcGlobals.h"
#include "TMath.h"
#include <fstream> #include <fstream>
#include <algorithm> #include <algorithm>
#include <iomanip> #include <iomanip>
#include <cstring> #include <cstring>
#include <iostream>
using namespace std; using namespace std;
...@@ -52,6 +57,78 @@ THcAnalyzer::~THcAnalyzer() ...@@ -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) ClassImp(THcAnalyzer)
......
...@@ -18,6 +18,8 @@ public: ...@@ -18,6 +18,8 @@ public:
void SetPedestalEvtype( Int_t evtype ) { fPedestalEvtype = evtype; } void SetPedestalEvtype( Int_t evtype ) { fPedestalEvtype = evtype; }
void PrintReport( const char* templatefile, const char* ofile);
protected: protected:
Int_t fPedestalEvtype; Int_t fPedestalEvtype;
......
//*-- 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)
#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
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment