#include "THaOutput.h"
#include "TROOT.h"
#include "THaVform.h"
#include "THaVhist.h"
#include "THaVarList.h"
#include "THaVar.h"
#include "THaGlobals.h"
#include "TH1.h"
#include "TH2.h"
#include "TTree.h"
#include "TFile.h"
#include "TRegexp.h"
#include "TError.h"
#include "THaScalerGroup.h"
#include "THaScaler.h"
#include "THaEvData.h"
#include "THaString.h"
#include <algorithm>
#include <fstream>
#include <cstring>
#include <iostream>
#include "THaBenchmark.h"
using namespace std;
using namespace THaString;
typedef vector<THaOdata*>::iterator Iter_o_t;
typedef vector<THaVform*>::iterator Iter_f_t;
typedef vector<THaVhist*>::iterator Iter_h_t;
typedef vector<string>::iterator Iter_s_t;
Int_t THaOutput::fgVerbose = 1;
static Bool_t fgDoBench = kFALSE;
static THaBenchmark fgBench;
class THaEpicsKey {
public:
THaEpicsKey(const std::string &nm) : fName(nm)
{ fAssign.clear(); }
void AddAssign(const std::string& input) {
typedef map<string, double>::value_type valType;
string::size_type pos;
string sdata,temp1,temp2;
sdata = findQuotes(input);
pos = sdata.find("=");
if (pos != string::npos) {
temp1.assign(sdata.substr(0,pos));
temp2.assign(sdata.substr(pos+1,sdata.length()));
if (temp2.find("=") != string::npos)
temp2.assign
(sdata.substr(pos+2,sdata.length()));
if (strlen(temp2.c_str()) > 0) {
double tdat = atof(temp2.c_str());
fAssign.insert(valType(temp1,tdat));
} else {
fAssign.insert(valType(temp1,0));
}
}
};
string findQuotes(const string& input) {
string result,temp1;
string::size_type pos1,pos2;
result = input;
pos1 = input.find("'");
if (pos1 != string::npos) {
temp1.assign(input.substr(pos1+1,input.length()));
pos2 = temp1.find("'");
if (pos2 != string::npos) {
result.assign(temp1.substr(0,pos2));
result += temp1.substr(pos2+1,temp1.length());
}
}
return result;
};
Bool_t IsString() { return !fAssign.empty(); };
Double_t Eval(const string& input) {
if (fAssign.empty()) return 0;
for (map<string,Double_t>::iterator pm = fAssign.begin();
pm != fAssign.end(); pm++) {
if (input == pm->first) {
return pm->second;
}
}
return 0;
};
const string& GetName() { return fName; };
private:
string fName;
map<string,Double_t> fAssign;
};
class THaScalerKey {
public:
THaScalerKey(const string& nm, const string& bk, Int_t rc,
Int_t hel, Int_t sl, Int_t ch) :
fData(0.0), fName(nm), fBank(bk), fRC(rc), fHelicity(hel),
fSlot(sl), fChan(ch) {}
THaScalerKey(const string& nm, const string& bk) :
fData(0.0), fName(nm), fBank(bk), fRC(0), fHelicity(0),
fSlot(-1), fChan(-1) {}
virtual ~THaScalerKey() {}
void AddBranches(TTree *T, Bool_t addprefix = kTRUE);
void Fill(Double_t dat) { fData = dat; };
void Print() const;
Double_t GetData() { return fData; };
const string& GetChanName() { return fName; };
const string& GetBank() { return fBank; };
Bool_t SlotDefined() { return (fSlot >= 0); };
Bool_t IsRate() { return (fRC == 0); };
Bool_t IsCounts() { return !IsRate(); };
Int_t GetHelicity() { return fHelicity; };
Int_t GetSlot() { return fSlot; };
Int_t GetChan() { return fChan; };
private:
THaScalerKey(const THaScalerKey& key);
THaScalerKey& operator=(const THaScalerKey& key);
static string DashToUbar(const string& var);
Double_t fData;
string fName, fBank;
Int_t fRC, fHelicity, fSlot, fChan;
};
void THaScalerKey::AddBranches(TTree *T, Bool_t addprefix )
{
string name;
if (addprefix) name = fBank + "_";
if (GetHelicity() > 0) name += "P_";
if (GetHelicity() < 0) name += "M_";
name += fName;
name = DashToUbar(name);
string tinfo = name + "/D";
T->Branch(name.c_str(), &fData, tinfo.c_str(), 4000);
}
void THaScalerKey::Print() const
{
cout << "Scaler key name = "<<fName<<" bank = "<<fBank;
cout << " sl = "<<fSlot;
cout << " ch = "<<fChan<<" RC = "<<fRC<<" hel = "<<fHelicity;
cout << " data = "<<fData<<endl;
}
string THaScalerKey::DashToUbar(const string& var)
{
int pos,pos0=0;
string output = var;
while (1) {
pos = output.find("-");
if (pos > pos0) {
output.replace(pos, 1, "_"); pos0 = pos;
} else { break; }
}
return output;
}
THaOdata::THaOdata( const THaOdata& other )
: tree(other.tree), name(other.name), nsize(other.nsize)
{
data = new Double_t[nsize]; ndata = other.ndata;
memcpy( data, other.data, nsize*sizeof(Double_t));
}
THaOdata& THaOdata::operator=(const THaOdata& rhs )
{
if( this != &rhs ) {
tree = rhs.tree; name = rhs.name;
if( nsize < rhs.nsize ) {
nsize = rhs.nsize; delete [] data; data = new Double_t[nsize];
}
ndata = rhs.ndata; memcpy( data, rhs.data, nsize*sizeof(Double_t));
}
return *this;
}
void THaOdata::AddBranches( TTree* _tree, string _name )
{
name = _name;
tree = _tree;
string sname = "Ndata." + name;
string leaf = sname;
tree->Branch(sname.c_str(),&ndata,(leaf+"/I").c_str());
leaf = "data["+leaf+"]/D";
tree->Branch(name.c_str(),data,leaf.c_str());
}
Bool_t THaOdata::Resize(Int_t i)
{
static const Int_t MAX = 4096;
if( i > MAX ) return true;
Int_t newsize = nsize;
while ( i >= newsize ) { newsize *= 2; }
Double_t* tmp = new Double_t[newsize];
memcpy( tmp, data, nsize*sizeof(Double_t) );
delete [] data; data = tmp; nsize = newsize;
if( tree )
tree->SetBranchAddress( name.c_str(), data );
return false;
}
THaOutput::THaOutput() :
fNvar(0), fVar(NULL), fEpicsVar(0), fTree(NULL),
fEpicsTree(NULL), fInit(false)
{
}
THaOutput::~THaOutput()
{
Bool_t alive = TROOT::Initialized();
if( alive ) {
if (fTree) delete fTree;
if (fEpicsTree) delete fEpicsTree;
}
if (fVar) delete [] fVar;
if (fEpicsVar) delete [] fEpicsVar;
if( alive ) {
for (map<string, TTree*>::iterator mt = fScalTree.begin();
mt != fScalTree.end(); mt++) delete mt->second;
}
for (Iter_o_t od = fOdata.begin();
od != fOdata.end(); od++) delete *od;
for (Iter_f_t itf = fFormulas.begin();
itf != fFormulas.end(); itf++) delete *itf;
for (Iter_f_t itf = fCuts.begin();
itf != fCuts.end(); itf++) delete *itf;
for (Iter_h_t ith = fHistos.begin();
ith != fHistos.end(); ith++) delete *ith;
for (vector<THaScalerKey* >::iterator isca = fScalerKey.begin();
isca != fScalerKey.end(); isca++) delete *isca;
for (vector<THaEpicsKey* >::iterator iep = fEpicsKey.begin();
iep != fEpicsKey.end(); iep++) delete *iep;
}
Int_t THaOutput::Init( const char* filename )
{
if( fInit ) {
cout << "\nTHaOutput::Init: Info: THaOutput cannot be completely"
<< " re-initialized. Keeping existing definitions." << endl;
cout << "Global Variables are being re-attached and formula/cuts"
<< " are being re-compiled." << endl;
if ( Attach() ) return -4;
Print();
return 1;
}
if( !gHaVars ) return -2;
if( fgDoBench ) fgBench.Begin("Init");
fTree = new TTree("T","Hall A Analyzer Output DST");
fTree->SetAutoSave(200000000);
fOpenEpics = kFALSE;
fOpenScal = kFALSE;
fFirstEpics = kTRUE;
fFirstScal = kTRUE;
fScalBank = "nothing";
fScalRC = kRate;
Int_t err = LoadFile( filename );
if( fgDoBench && err != 0 ) fgBench.Stop("Init");
if( err == -1 ) {
return 0;
}
else if( err != 0 ) {
delete fTree; fTree = NULL;
return -3;
}
fNvar = fVarnames.size();
fArrayNames.clear();
fVNames.clear();
THaVar *pvar;
for (Int_t ivar = 0; ivar < fNvar; ivar++) {
pvar = gHaVars->Find(fVarnames[ivar].c_str());
if (pvar) {
if (pvar->IsArray()) {
fArrayNames.push_back(fVarnames[ivar]);
fOdata.push_back(new THaOdata());
} else {
fVNames.push_back(fVarnames[ivar]);
}
} else {
cout << "\nTHaOutput::Init: WARNING: Global variable ";
cout << fVarnames[ivar] << " does not exist. "<< endl;
cout << "There is probably a typo error... "<<endl;
}
}
string tinfo;
Int_t status;
Int_t k = 0;
for (Iter_s_t inam = fFormnames.begin(); inam != fFormnames.end(); inam++, k++) {
tinfo = Form("f%d",k);
fFormulas.push_back(new THaVform("formula",inam->c_str(),fFormdef[k].c_str()));
THaVform* pform = fFormulas[k];
status = pform->Init();
if ( status != 0) {
cout << "THaOutput::Init: WARNING: Error in formula ";
cout << *inam << endl;
cout << "There is probably a typo error... " << endl;
if( fgVerbose<=2 )
pform->ErrPrint(status);
else
pform->LongPrint();
} else {
pform->SetOutput(fTree);
vector<string> avar = pform->GetVars();
for (Iter_s_t it = avar.begin(); it != avar.end(); it++) {
string svar = StripBracket(*it);
pvar = gHaVars->Find(svar.c_str());
if (pvar) {
if (pvar->IsArray()) {
Iter_s_t it = find(fArrayNames.begin(),fArrayNames.end(),svar);
if( it == fArrayNames.end() ) {
fArrayNames.push_back(svar);
fOdata.push_back(new THaOdata());
}
} else {
Iter_s_t it = find(fVNames.begin(),fVNames.end(),svar);
if( it == fVNames.end() )
fVNames.push_back(svar);
}
}
}
}
}
k = 0;
for(Iter_o_t iodat = fOdata.begin(); iodat != fOdata.end(); iodat++, k++)
(*iodat)->AddBranches(fTree, fArrayNames[k]);
fNvar = fVNames.size();
fVar = new Double_t[fNvar];
for (k = 0; k < fNvar; k++) {
tinfo = fVNames[k] + "/D";
fTree->Branch(fVNames[k].c_str(), &fVar[k], tinfo.c_str(), kNbout);
}
k = 0;
for (Iter_s_t inam = fCutnames.begin(); inam != fCutnames.end(); inam++, k++ ) {
fCuts.push_back(new THaVform("cut", inam->c_str(), fCutdef[k].c_str()));
THaVform* pcut = fCuts[k];
status = pcut->Init();
if ( status != 0 ) {
cout << "THaOutput::Init: WARNING: Error in formula ";
cout << *inam << endl;
cout << "There is probably a typo error... " << endl;
pcut->ErrPrint(status);
} else {
pcut->SetOutput(fTree);
}
if( fgVerbose>2 )
pcut->LongPrint();
}
for (Iter_h_t ihist = fHistos.begin(); ihist != fHistos.end(); ihist++) {
sfvarx = (*ihist)->GetVarX();
sfvary = (*ihist)->GetVarY();
for (Iter_f_t iform = fFormulas.begin(); iform != fFormulas.end(); iform++) {
string stemp((*iform)->GetName());
if (CmpNoCase(sfvarx,stemp) == 0) {
(*ihist)->SetX(*iform);
}
if (CmpNoCase(sfvary,stemp) == 0) {
(*ihist)->SetY(*iform);
}
}
if ((*ihist)->HasCut()) {
scut = (*ihist)->GetCutStr();
for (Iter_f_t icut = fCuts.begin(); icut != fCuts.end(); icut++) {
string stemp((*icut)->GetName());
if (CmpNoCase(scut,stemp) == 0) {
(*ihist)->SetCut(*icut);
}
}
}
(*ihist)->Init();
}
if (!fEpicsKey.empty()) {
vector<THaEpicsKey*>::size_type siz = fEpicsKey.size();
fEpicsVar = new Double_t[siz+1];
UInt_t i = 0;
for (vector<THaEpicsKey*>::iterator it = fEpicsKey.begin();
it != fEpicsKey.end(); it++, i++) {
fEpicsVar[i] = -1e32;
string epicsbr = CleanEpicsName((*it)->GetName());
tinfo = epicsbr + "/D";
fTree->Branch(epicsbr.c_str(), &fEpicsVar[i],
tinfo.c_str(), kNbout);
fEpicsTree->Branch(epicsbr.c_str(), &fEpicsVar[i],
tinfo.c_str(), kNbout);
}
fEpicsVar[siz] = -1e32;
fEpicsTree->Branch("timestamp",&fEpicsVar[siz],"timestamp/D", kNbout);
}
for (vector<THaScalerKey*>::iterator it = fScalerKey.begin();
it != fScalerKey.end(); it++) {
THaScalerKey* pkey(*it);
pkey->AddBranches(fTree);
for (map<string, TTree*>::iterator mt = fScalTree.begin();
mt != fScalTree.end(); mt++) {
string thisbank(mt->first);
TTree *sctree = mt->second;
if ( CmpNoCase(thisbank,pkey->GetBank()) != 0)
continue;
pkey->AddBranches(sctree,kFALSE);
}
}
Print();
fInit = true;
if( fgDoBench ) fgBench.Stop("Init");
if( fgDoBench ) fgBench.Begin("Attach");
Int_t st = Attach();
if( fgDoBench ) fgBench.Stop("Attach");
if ( st )
return -4;
for (Iter_f_t icut=fCuts.begin(); icut!=fCuts.end(); icut++)
(*icut)->SetOutput(fTree);
for (Iter_f_t iform=fFormulas.begin(); iform!=fFormulas.end(); iform++)
(*iform)->SetOutput(fTree);
return 0;
}
void THaOutput::BuildList( const vector<string>& vdata)
{
if (vdata.empty()) return;
if (CmpNoCase(vdata[0],"begin") == 0) {
if (vdata.size() < 2) return;
if (CmpNoCase(vdata[1],"epics") == 0) fOpenEpics = kTRUE;
if (CmpNoCase(vdata[1],"scalers") == 0) fOpenScal = kTRUE;
}
if (CmpNoCase(vdata[0],"end") == 0) {
if (vdata.size() < 2) return;
if (CmpNoCase(vdata[1],"epics") == 0) fOpenEpics = kFALSE;
if (CmpNoCase(vdata[1],"scalers") == 0) fOpenScal = kFALSE;
}
if (fOpenEpics && fOpenScal) {
cout << "THaOutput::ERROR: Syntax error in output.def"<<endl;
cout << "Must 'begin' and 'end' before 'begin' again."<<endl;
cout << "e.g. 'begin epics' ..... 'end epics'"<<endl;
return ;
}
if (fOpenEpics) {
if (fFirstEpics) {
if (!fEpicsTree)
fEpicsTree = new TTree("E","Hall A Epics Data");
fFirstEpics = kFALSE;
return;
} else {
fEpicsKey.push_back(new THaEpicsKey(vdata[0]));
if (vdata.size() > 1) {
std::vector<string> esdata = reQuote(vdata);
for (int k = 1; k < (int)esdata.size(); k++) {
fEpicsKey[fEpicsKey.size()-1]->AddAssign(esdata[k]);
}
}
}
} else {
fFirstEpics = kTRUE;
}
if (fOpenScal) {
if (fFirstScal) {
fFirstScal = kFALSE;
if (vdata.size() < 3) {
cout << "THaOutput: ERROR: need to specify scaler bank."<<endl;
cout << "Syntax is 'begin scaler right' for right bank."<<endl;
return;
}
fScalBank = ToLower( vdata[2] );
string desc = "Hall A Scalers on " + fScalBank;
fScalTree.insert
( make_pair(fScalBank,
new TTree( ToUpper(fScalBank).c_str(), desc.c_str() )
)
);
return;
} else {
fScalRC = kRate;
if (vdata.size() >= 3) {
if (vdata.size() >= 4) {
if ((CmpNoCase(vdata[3],"count") == 0) ||
(CmpNoCase(vdata[3],"counts") == 0)) {
fScalRC = kCount;
}
}
AddScaler(vdata[0], fScalBank, 0,
atoi(vdata[1].c_str()),atoi(vdata[2].c_str()));
} else {
fScalRC = kRate;
if (vdata.size() >= 2) {
if ((CmpNoCase(vdata[1],"count") == 0) ||
(CmpNoCase(vdata[1],"counts") == 0)) {
fScalRC = kCount;
}
}
if (CmpNoCase(vdata[0],"default") == 0) {
DefScaler();
return;
} else if (CmpNoCase(vdata[0],"default_helicity") == 0) {
DefScaler(1);
return;
} else {
AddScaler(vdata[0],fScalBank);
}
}
}
} else {
fFirstScal = kTRUE;
}
return;
}
void THaOutput::DefScaler(Int_t hel) {
string norm_scaler[] = {"trigger-1", "trigger-2", "trigger-3",
"trigger-4", "trigger-5", "trigger-6",
"trigger-7", "trigger-8", "trigger-9",
"trigger-10", "trigger-11", "trigger-12",
"bcm_u1", "bcm_u3", "bcm_u10",
"bcm_d1", "bcm_d3", "bcm_d10",
"clock", "TS-accept", "edtpulser",
"strobe", "dclock" };
Int_t nscal = 1;
Int_t jhel = 0;
if (hel == 1) {
nscal = 2; jhel = -1;
}
Int_t numchan = sizeof(norm_scaler)/sizeof(string);
for (Int_t i = 0; i < nscal; i++) {
jhel = jhel + 2*i;
for (Int_t j = 0; j < numchan; j++) {
AddScaler(norm_scaler[j], fScalBank, jhel);
}
}
}
void THaOutput::AddScaler(const string& name, const string& bank,
Int_t helicity, Int_t slot, Int_t chan)
{
Int_t scal_rc = 0;
if (fScalRC == kCount) scal_rc = 1;
fScalerKey.push_back(new THaScalerKey(name, bank, scal_rc,
helicity, slot, chan));
}
Int_t THaOutput::Attach()
{
if( !gHaVars ) return -2;
THaVar *pvar;
Int_t NAry = fArrayNames.size();
Int_t NVar = fVNames.size();
fVariables.resize(NVar);
fArrays.resize(NAry);
for (Int_t ivar = 0; ivar < NVar; ivar++) {
pvar = gHaVars->Find(fVNames[ivar].c_str());
if (pvar) {
if ( !pvar->IsArray() ) {
fVariables[ivar] = pvar;
} else {
cout << "\tTHaOutput::Attach: ERROR: Global variable " << fVNames[ivar]
<< " changed from simple to array!! Leaving empty space for variable"
<< endl;
fVariables[ivar] = 0;
}
} else {
cout << "\nTHaOutput::Attach: WARNING: Global variable ";
cout << fVarnames[ivar] << " NO LONGER exists (it did before). "<< endl;
cout << "This is not supposed to happen... "<<endl;
}
}
for (Int_t ivar = 0; ivar < NAry; ivar++) {
pvar = gHaVars->Find(fArrayNames[ivar].c_str());
if (pvar) {
if ( pvar->IsArray() ) {
fArrays[ivar] = pvar;
} else {
cout << "\tTHaOutput::Attach: ERROR: Global variable " << fVNames[ivar]
<< " changed from ARRAY to Simple!! Leaving empty space for variable"
<< endl;
fArrays[ivar] = 0;
}
} else {
cout << "\nTHaOutput::Attach: WARNING: Global variable ";
cout << fVarnames[ivar] << " NO LONGER exists (it did before). "<< endl;
cout << "This is not supposed to happen... "<<endl;
}
}
for (Iter_f_t iform=fFormulas.begin(); iform!=fFormulas.end(); iform++) {
(*iform)->ReAttach();
}
for (Iter_f_t icut=fCuts.begin(); icut!=fCuts.end(); icut++) {
(*icut)->ReAttach();
}
for (Iter_h_t ihist = fHistos.begin(); ihist != fHistos.end(); ihist++) {
(*ihist)->ReAttach();
}
return 0;
}
Int_t THaOutput::ProcEpics(THaEvData *evdata)
{
if ( !evdata->IsEpicsEvent()
|| fEpicsKey.empty() || !fEpicsTree ) return 0;
if( fgDoBench ) fgBench.Begin("EPICS");
fEpicsVar[fEpicsKey.size()] = -1e32;
for (UInt_t i = 0; i < fEpicsKey.size(); i++) {
if (evdata->IsLoadedEpics(fEpicsKey[i]->GetName().c_str())) {
if (fEpicsKey[i]->IsString()) {
fEpicsVar[i] = fEpicsKey[i]->Eval(
evdata->GetEpicsString(
fEpicsKey[i]->GetName().c_str()));
} else {
fEpicsVar[i] =
evdata->GetEpicsData(
fEpicsKey[i]->GetName().c_str());
}
fEpicsVar[fEpicsKey.size()] =
evdata->GetEpicsTime(
fEpicsKey[i]->GetName().c_str());
} else {
fEpicsVar[i] = -1e32;
}
}
if (fEpicsTree != 0) fEpicsTree->Fill();
if( fgDoBench ) fgBench.Stop("EPICS");
return 1;
}
Int_t THaOutput::ProcScaler(THaScalerGroup *scagrp)
{
THaScaler *scaler = scagrp->GetScalerObj();
if (!scaler || !scaler->IsRenewed()) return 0;
if( fgDoBench ) fgBench.Begin("Scalers");
Bool_t did_fill = kFALSE;
string thisbank(scaler->GetName());
for (vector<THaScalerKey*>::iterator it = fScalerKey.begin();
it != fScalerKey.end(); it++) {
THaScalerKey* pkey(*it);
if (CmpNoCase( thisbank,pkey->GetBank()) != 0) continue;
did_fill = kTRUE;
if (pkey->SlotDefined()) {
if (pkey->IsRate()) {
pkey->Fill(scaler->GetScalerRate(pkey->GetSlot(), pkey->GetChan()));
} else {
pkey->Fill(scaler->GetScaler(pkey->GetSlot(), pkey->GetChan()));
}
} else {
if (pkey->GetChanName()=="dclock") {
pkey->Fill(scaler->GetNormData(pkey->GetHelicity(),
"clock",0) -
scaler->GetNormData(pkey->GetHelicity(),
"clock",1) );
} else
if (pkey->IsRate()) {
pkey->Fill(scaler->GetNormRate(pkey->GetHelicity(),
pkey->GetChanName().c_str()));
} else {
pkey->Fill(scaler->GetNormData(pkey->GetHelicity(),
pkey->GetChanName().c_str(), 0));
}
}
}
string key = ToLower(thisbank);
TTree *sctree = fScalTree[key];
if (did_fill && sctree) sctree->Fill();
if( fgDoBench ) fgBench.Stop("Scalers");
return 1;
}
Int_t THaOutput::Process()
{
if( fgDoBench ) fgBench.Begin("Formulas");
for (Iter_f_t iform = fFormulas.begin(); iform != fFormulas.end(); iform++)
if (*iform) (*iform)->Process();
if( fgDoBench ) fgBench.Stop("Formulas");
if( fgDoBench ) fgBench.Begin("Cuts");
for (Iter_f_t icut = fCuts.begin(); icut != fCuts.end(); icut++)
if (*icut) (*icut)->Process();
if( fgDoBench ) fgBench.Stop("Cuts");
if( fgDoBench ) fgBench.Begin("Variables");
THaVar *pvar;
for (Int_t ivar = 0; ivar < fNvar; ivar++) {
pvar = fVariables[ivar];
if (pvar) fVar[ivar] = pvar->GetValue();
}
Int_t k = 0;
for (Iter_o_t it = fOdata.begin(); it != fOdata.end(); it++, k++) {
THaOdata* pdat(*it);
pdat->Clear();
pvar = fArrays[k];
if ( pvar == NULL ) continue;
Int_t i = pvar->GetLen();
bool first = true;
while( i-- > 0 ) {
if (pdat->Fill(i,pvar->GetValue(i)) != 1) {
if( fgVerbose>0 && first ) {
cerr << "THaOutput::ERROR: storing too much variable sized data: "
<< pvar->GetName() <<" "<<pvar->GetLen()<<endl;
first = false;
}
}
}
}
if( fgDoBench ) fgBench.Stop("Variables");
if( fgDoBench ) fgBench.Begin("Histos");
for ( Iter_h_t it = fHistos.begin(); it != fHistos.end(); it++ )
(*it)->Process();
if( fgDoBench ) fgBench.Stop("Histos");
if( fgDoBench ) fgBench.Begin("TreeFill");
if (fTree != 0) fTree->Fill();
if( fgDoBench ) fgBench.Stop("TreeFill");
return 0;
}
Int_t THaOutput::End()
{
if( fgDoBench ) fgBench.Begin("End");
if (fTree != 0) fTree->Write();
if (fEpicsTree != 0) fEpicsTree->Write();
if( fgVerbose>1 )
cout << "End:: fScalTree size "<<fScalTree.size()<<endl;
for (map<string, TTree*>::iterator mt = fScalTree.begin();
mt != fScalTree.end(); mt++) {
TTree* tree = mt->second;
if (tree) tree->Write();
}
for (Iter_h_t ihist = fHistos.begin(); ihist != fHistos.end(); ihist++)
(*ihist)->End();
if( fgDoBench ) fgBench.Stop("End");
if( fgDoBench ) {
cout << "Output timing summary:" << endl;
fgBench.Print("Init");
fgBench.Print("Attach");
fgBench.Print("Variables");
fgBench.Print("Formulas");
fgBench.Print("Cuts");
fgBench.Print("Histos");
fgBench.Print("TreeFill");
fgBench.Print("EPICS");
fgBench.Print("Scalers");
fgBench.Print("End");
}
return 0;
}
Int_t THaOutput::LoadFile( const char* filename )
{
if( !filename || !*filename || strspn(filename," ") == strlen(filename) ) {
::Error( "THaOutput::LoadFile", "invalid file name, "
"no output definition loaded" );
return -1;
}
string loadfile(filename);
ifstream* odef = new ifstream(loadfile.c_str());
if ( ! (*odef) ) {
ErrFile(-1, loadfile);
return -1;
}
const string comment = "#";
const string whitespace( " \t" );
string::size_type pos;
vector<string> strvect;
string sline;
while (getline(*odef,sline)) {
if( sline.empty()
|| (pos = sline.find_first_not_of( whitespace )) == string::npos
|| comment.find(sline[pos]) != string::npos )
continue;
if( (pos = sline.find_first_of( comment )) != string::npos )
sline.erase(pos);
strvect = Split(sline);
BuildList(strvect);
if (strvect.size() < 2) {
ErrFile(0, sline);
continue;
}
Int_t ikey = FindKey(strvect[0]);
string sname = StripBracket(strvect[1]);
switch (ikey) {
case kVar:
fVarnames.push_back(sname);
break;
case kForm:
if (strvect.size() < 3) {
ErrFile(ikey, sline);
continue;
}
fFormnames.push_back(sname);
fFormdef.push_back(strvect[2]);
break;
case kCut:
if (strvect.size() < 3) {
ErrFile(ikey, sline);
continue;
}
fCutnames.push_back(sname);
fCutdef.push_back(strvect[2]);
break;
case kH1f:
case kH1d:
case kH2f:
case kH2d:
if( ChkHistTitle(ikey, sline) != 1) {
ErrFile(ikey, sline);
continue;
}
fHistos.push_back(
new THaVhist(strvect[0],sname,stitle));
fHistos.back()->SetX(nx, xlo, xhi, sfvarx);
if (ikey == kH2f || ikey == kH2d) {
fHistos.back()->SetY(ny, ylo, yhi, sfvary);
}
if (iscut != fgNocut) fHistos.back()->SetCut(scut);
break;
case kBlock:
if( BuildBlock(strvect[1]) == 0 ) {
cout << "\nTHaOutput::Init: WARNING: Block ";
cout << strvect[1] << " does not match any variables. " << endl;
cout << "There is probably a typo error... "<<endl;
}
break;
case kBegin:
case kEnd:
break;
default:
if (!fOpenEpics && !fOpenScal)
cout << "Warning: keyword "<<strvect[0]<<" undefined "<<endl;
}
}
delete odef;
if( fVarnames.size() > 1 ) {
sort(fVarnames.begin(),fVarnames.end());
vector<string>::iterator Vi = fVarnames.begin();
while ( (Vi+1)!=fVarnames.end() ) {
if ( *Vi == *(Vi+1) ) {
fVarnames.erase(Vi+1);
} else {
Vi++;
}
}
}
return 0;
}
Int_t THaOutput::FindKey(const string& key) const
{
struct KeyMap {
const char* name;
EId keyval;
};
static const KeyMap keymap[] = {
{ "variable", kVar },
{ "formula", kForm },
{ "cut", kCut },
{ "th1f", kH1f },
{ "th1d", kH1d },
{ "th2f", kH2f },
{ "th2d", kH2d },
{ "block", kBlock },
{ "begin", kBegin },
{ "end", kEnd },
{ 0 }
};
if( const KeyMap* it = keymap ) {
while( it->name ) {
if( CmpNoCase( key, it->name ) == 0 )
return it->keyval;
it++;
}
}
return -1;
}
string THaOutput::StripBracket(const string& var) const
{
string::size_type pos1,pos2;
string open_brack("[");
string close_brack("]");
string result;
pos1 = var.find(open_brack,0);
pos2 = var.find(close_brack,0);
if ((pos1 != string::npos) &&
(pos2 != string::npos)) {
result = var.substr(0,pos1);
result += var.substr(pos2+1,var.length());
} else {
result = var;
}
return result;
}
std::vector<string> THaOutput::reQuote(const std::vector<string> input) const {
std::vector<string> result;
result.clear();
int first_quote = 1;
int to_add = 0;
string temp1,temp2,temp3;
string::size_type pos1,pos2;
for (vector<string>::const_iterator str = input.begin(); str !=
input.end(); ++str ) {
temp1 = *str;
pos1 = temp1.find("'");
if (pos1 != string::npos) {
if (first_quote) {
temp2.assign(temp1.substr(pos1,temp1.length()));
temp3.assign(temp1.substr(pos1+1,temp1.length()));
pos2 = temp3.find("'");
if (pos2 != string::npos) {
temp1.assign(temp3.substr(0,pos2));
temp2.assign(temp3.substr
(pos2+1,temp3.length()));
temp3 = temp1+temp2;
result.push_back(temp3);
continue;
}
first_quote = 0;
to_add = 1;
} else {
temp2 = temp2 + " " + temp1;
result.push_back(temp2);
temp2.clear();
first_quote = 1;
to_add = 0;
}
} else {
if (to_add) {
temp2 = temp2 + " " + temp1;
} else {
result.push_back(temp1);
}
}
}
return result;
}
string THaOutput::CleanEpicsName(const string& input) const
{
static const char badchar[]=":+-*/=";
static const string goodchar = "_";
int numbad = sizeof(badchar)/sizeof(char) - 1;
string output = input;
for (int i = 0; i < numbad; i++) {
string sbad(&badchar[i]);
sbad.erase(1,sbad.size());
string::size_type pos = input.find(sbad,0);
while (pos != string::npos) {
output.replace(pos,1,goodchar);
pos = input.find(sbad,pos+1);
}
}
return output;
}
void THaOutput::ErrFile(Int_t iden, const string& sline) const
{
if (iden == -1) {
cerr << "<THaOutput::LoadFile> WARNING: file " << sline;
cerr << " does not exist." << endl;
cerr << "See $ANALYZER/examples/output.def for an example.\n";
cerr << "Output will only contain event objects "
"(this may be all you want).\n";
return;
}
if (fOpenEpics || fOpenScal) return;
cerr << "THaOutput::ERROR: Syntax error in output definition file."<<endl;
cerr << "The offending line is :\n"<<sline<<endl<<endl;
switch (iden) {
case kVar:
cerr << "For variables, the syntax is: "<<endl;
cerr << " variable variable-name"<<endl;
cerr << "Example: "<<endl;
cerr << " variable R.vdc.v2.nclust"<<endl;;
case kCut:
case kForm:
cerr << "For formulas or cuts, the syntax is: "<<endl;
cerr << " formula(or cut) formula-name formula-expression"<<endl;
cerr << "Example: "<<endl;
cerr << " formula targetX 1.464*B.bpm4b.x-0.464*B.bpm4a.x"<<endl;
case kH1f:
case kH1d:
cerr << "For 1D histograms, the syntax is: "<<endl;
cerr << " TH1F(or TH1D) name 'title' ";
cerr << "variable nbin xlo xhi [cut-expr]"<<endl;
cerr << "Example: "<<endl;
cerr << " TH1F tgtx 'target X' targetX 100 -2 2"<<endl;
cerr << "(Title in single quotes. Variable can be a formula)"<<endl;
cerr << "optionally can impose THaCut expression 'cut-expr'"<<endl;
break;
case kH2f:
case kH2d:
cerr << "For 2D histograms, the syntax is: "<<endl;
cerr << " TH2F(or TH2D) name 'title' varx vary";
cerr << " nbinx xlo xhi nbiny ylo yhi [cut-expr]"<<endl;
cerr << "Example: "<<endl;
cerr << " TH2F t12 't1 vs t2' D.timeroc1 D.timeroc2";
cerr << " 100 0 20000 100 0 35000"<<endl;
cerr << "(Title in single quotes. Variable can be a formula)"<<endl;
cerr << "optionally can impose THaCut expression 'cut-expr'"<<endl;
break;
default:
cerr << "See the documentation or ask Bob Michaels"<<endl;
break;
}
}
void THaOutput::Print() const
{
typedef vector<string>::const_iterator Iterc_s_t;
typedef vector<THaVform*>::const_iterator Iterc_f_t;
typedef vector<THaVhist*>::const_iterator Iterc_h_t;
if( fgVerbose > 0 ) {
if( fVarnames.size() == 0 && fFormulas.size() == 0 &&
fCuts.size() == 0 && fHistos.size() == 0 ) {
::Warning("THaOutput", "no output defined");
} else {
cout << endl << "THaOutput definitions: " << endl;
if( !fVarnames.empty() ) {
cout << "=== Number of variables "<<fVarnames.size()<<endl;
if( fgVerbose > 1 ) {
cout << endl;
UInt_t i = 0;
for (Iterc_s_t ivar = fVarnames.begin(); ivar != fVarnames.end();
i++, ivar++ ) {
cout << "Variable # "<<i<<" = "<<(*ivar)<<endl;
}
}
}
if( !fFormulas.empty() ) {
cout << "=== Number of formulas "<<fFormulas.size()<<endl;
if( fgVerbose > 1 ) {
cout << endl;
UInt_t i = 0;
for (Iterc_f_t iform = fFormulas.begin();
iform != fFormulas.end(); i++, iform++ ) {
cout << "Formula # "<<i<<endl;
if( fgVerbose>2 )
(*iform)->LongPrint();
else
(*iform)->ShortPrint();
}
}
}
if( !fCuts.empty() ) {
cout << "=== Number of cuts "<<fCuts.size()<<endl;
if( fgVerbose > 1 ) {
cout << endl;
UInt_t i = 0;
for (Iterc_f_t icut = fCuts.begin(); icut != fCuts.end();
i++, icut++ ) {
cout << "Cut # "<<i<<endl;
if( fgVerbose>2 )
(*icut)->LongPrint();
else
(*icut)->ShortPrint();
}
}
}
if( !fHistos.empty() ) {
cout << "=== Number of histograms "<<fHistos.size()<<endl;
if( fgVerbose > 1 ) {
cout << endl;
UInt_t i = 0;
for (Iterc_h_t ihist = fHistos.begin(); ihist != fHistos.end();
i++, ihist++) {
cout << "Histogram # "<<i<<endl;
(*ihist)->Print();
}
}
}
cout << endl;
}
}
}
Int_t THaOutput::ChkHistTitle(Int_t iden, const string& sline)
{
Int_t result = -1;
stitle = ""; sfvarx = ""; sfvary = "";
iscut = fgNocut; scut = "";
nx = 0; ny = 0; xlo = 0; xhi = 0; ylo = 0; yhi = 0;
string::size_type pos1 = sline.find_first_of("'");
string::size_type pos2 = sline.find_last_of("'");
if (pos1 != string::npos && pos2 > pos1) {
stitle = sline.substr(pos1+1,pos2-pos1-1);
}
string ctemp = sline.substr(pos2+1,sline.size()-pos2);
vector<string> stemp = Split(ctemp);
if (stemp.size() > 1) {
sfvarx = stemp[0];
Int_t ssize = stemp.size();
if (ssize == 4 || ssize == 5) {
sscanf(stemp[1].c_str(),"%d",&nx);
sscanf(stemp[2].c_str(),"%f",&xlo);
sscanf(stemp[3].c_str(),"%f",&xhi);
if (ssize == 5) {
iscut = 1; scut = stemp[4];
}
result = 1;
}
if (ssize == 8 || ssize == 9) {
sfvary = stemp[1];
sscanf(stemp[2].c_str(),"%d",&nx);
sscanf(stemp[3].c_str(),"%f",&xlo);
sscanf(stemp[4].c_str(),"%f",&xhi);
sscanf(stemp[5].c_str(),"%d",&ny);
sscanf(stemp[6].c_str(),"%f",&ylo);
sscanf(stemp[7].c_str(),"%f",&yhi);
if (ssize == 9) {
iscut = 1; scut = stemp[8];
}
result = 2;
}
}
if (result != 1 && result != 2) return -1;
if ((iden == kH1f || iden == kH1d) &&
result == 1) return 1;
if ((iden == kH2f || iden == kH2d) &&
result == 2) return 1;
return -1;
}
Int_t THaOutput::BuildBlock(const string& blockn)
{
TRegexp re(blockn.c_str(),kTRUE);
TIter next(gHaVars);
TObject *obj;
Int_t nvars=0;
while ((obj = next())) {
TString s = obj->GetName();
if ( s.Index(re) != kNPOS ) {
s.Append('\0');
string vn(s.Data());
fVarnames.push_back(vn);
nvars++;
}
}
return nvars;
}
void THaOutput::SetVerbosity( Int_t level )
{
fgVerbose = level;
}
ClassImp(THaOutput)
Last change: Sat Nov 7 21:26:48 2009
Last generated: 2009-11-07 21:26
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.