// The RooWorkspace is a persistable container for RooFit projects. A workspace
// can contain and own variables, p.d.f.s, functions and datasets. All objects
// that live in the workspace are owned by the workspace. The import() method
// enforces consistency of objects upon insertion into the workspace (e.g. no
// duplicate object with the same name are allowed) and makes sure all objects
// in the workspace are connected to each other. Easy accessor methods like
// pdf(), var() and data() allow to refer to the contents of the workspace by
// object name. The entire RooWorkspace can be saved into a ROOT TFile and organises
// the consistent streaming of its contents without duplication.
// <p>
// If a RooWorkspace contains custom classes, i.e. classes not in the
// ROOT distribution, portability of workspaces can be enhanced by
// storing the source code of those classes in the workspace as well.
// This process is also organized by the workspace through the
// importClassCode() method.
// END_HTML
#include "RooFit.h"
#include "RooWorkspace.h"
#include "RooAbsPdf.h"
#include "RooRealVar.h"
#include "RooCategory.h"
#include "RooAbsData.h"
#include "RooCmdConfig.h"
#include "RooMsgService.h"
#include "TInterpreter.h"
#include "TClassTable.h"
#include "TBaseClass.h"
#include "TSystem.h"
#include "TRegexp.h"
#include <map>
#include <string>
#include <list>
using namespace std ;
#if ROOT_VERSION_CODE <= ROOT_VERSION(5,19,02)
#include "Api.h"
#endif
#include "TClass.h"
#include "Riostream.h"
#include <string.h>
#include <assert.h>
ClassImp(RooWorkspace)
;
ClassImp(RooWorkspace::CodeRepo)
;
ClassImp(RooWorkspace::WSDir)
;
list<string> RooWorkspace::_classDeclDirList ;
list<string> RooWorkspace::_classImplDirList ;
string RooWorkspace::_classFileExportDir = ".wscode.%s" ;
Bool_t RooWorkspace::_autoClass = kFALSE ;
void RooWorkspace::addClassDeclImportDir(const char* dir)
{
_classDeclDirList.push_back(dir) ;
}
void RooWorkspace::addClassImplImportDir(const char* dir)
{
_classImplDirList.push_back(dir) ;
}
void RooWorkspace::setClassFileExportDir(const char* dir)
{
if (dir) {
_classFileExportDir = dir ;
} else {
_classFileExportDir = ".wscode.%s" ;
}
}
void RooWorkspace::autoImportClassCode(Bool_t flag)
{
_autoClass = flag ;
}
RooWorkspace::RooWorkspace() : _classes(this), _dir(0)
{
}
RooWorkspace::RooWorkspace(const char* name, const char* title) : TNamed(name,title?title:name), _classes(this), _dir(0)
{
}
RooWorkspace::RooWorkspace(const RooWorkspace& other) : TNamed(other), _classes(this), _dir(0)
{
other._allOwnedNodes.snapshot(_allOwnedNodes,kTRUE) ;
TIterator* iter = other._dataList.MakeIterator() ;
TObject* data2 ;
while((data2=iter->Next())) {
_dataList.Add(data2->Clone()) ;
}
delete iter ;
TIterator* iter2 = other._snapshots.MakeIterator() ;
RooArgSet* snap ;
while((snap=(RooArgSet*)iter2->Next())) {
RooArgSet* snapClone = (RooArgSet*) snap->snapshot() ;
snapClone->setName(snap->GetName()) ;
_snapshots.Add(snapClone) ;
}
delete iter2 ;
}
RooWorkspace::~RooWorkspace()
{
_dataList.Delete() ;
if (_dir) {
delete _dir ;
}
_snapshots.Delete() ;
}
Bool_t RooWorkspace::import(const RooArgSet& args, const RooCmdArg& arg1, const RooCmdArg& arg2, const RooCmdArg& arg3)
{
TIterator* iter = args.createIterator() ;
RooAbsArg* oneArg ;
Bool_t ret(kFALSE) ;
while((oneArg=(RooAbsArg*)iter->Next())) {
ret |= import(*oneArg,arg1,arg2,arg3) ;
}
return ret ;
}
Bool_t RooWorkspace::import(const RooAbsArg& inArg, const RooCmdArg& arg1, const RooCmdArg& arg2, const RooCmdArg& arg3)
{
RooLinkedList args ;
args.Add((TObject*)&arg1) ;
args.Add((TObject*)&arg2) ;
args.Add((TObject*)&arg3) ;
RooCmdConfig pc(Form("RooWorkspace::import(%s)",GetName())) ;
pc.defineString("conflictSuffix","RenameConflictNodes",0) ;
pc.defineString("allSuffix","RenameAllNodes",0) ;
pc.defineString("allVarsSuffix","RenameAllVariables",0) ;
pc.defineString("varChangeIn","RenameVar",0,"",kTRUE) ;
pc.defineString("varChangeOut","RenameVar",1,"",kTRUE) ;
pc.defineInt("useExistingNodes","RecycleConflictNodes",0,0) ;
pc.defineMutex("RenameConflictNodes","RenameAllNodes") ;
pc.defineMutex("RenameConflictNodes","RecycleConflictNodes") ;
pc.defineMutex("RenameAllNodes","RecycleConflictNodes") ;
pc.defineMutex("RenameVariable","RenameAllVariables") ;
pc.process(args) ;
if (!pc.ok(kTRUE)) {
return kTRUE ;
}
const char* suffixC = pc.getString("conflictSuffix") ;
const char* suffixA = pc.getString("allSuffix") ;
const char* suffixV = pc.getString("allVarsSuffix") ;
const char* varChangeIn = pc.getString("varChangeIn") ;
const char* varChangeOut = pc.getString("varChangeOut") ;
Int_t useExistingNodes = pc.getInt("useExistingNodes") ;
if (suffixC && strlen(suffixC)==0) suffixC = 0 ;
if (suffixA && strlen(suffixA)==0) suffixA = 0 ;
Bool_t conflictOnly = suffixA ? kFALSE : kTRUE ;
const char* suffix = suffixA ? suffixA : suffixC ;
map<string,string> varMap ;
if (strlen(varChangeIn)>0) {
char tmp[1024] ;
strcpy(tmp,varChangeIn) ;
list<string> tmpIn,tmpOut ;
char* ptr = strtok(tmp,",") ;
while (ptr) {
tmpIn.push_back(ptr) ;
ptr = strtok(0,",") ;
}
strcpy(tmp,varChangeOut) ;
ptr = strtok(tmp,",") ;
while (ptr) {
tmpOut.push_back(ptr) ;
ptr = strtok(0,",") ;
}
list<string>::iterator iin = tmpIn.begin() ;
list<string>::iterator iout = tmpOut.begin() ;
for (;iin!=tmpIn.end() ; ++iin,++iout) {
varMap[*iin]=*iout ;
}
}
if (suffixV != 0 && strlen(suffixV)>0) {
RooArgSet* vars = inArg.getVariables() ;
TIterator* iter = vars->createIterator() ;
RooAbsArg* v ;
while((v=(RooAbsArg*)iter->Next())) {
varMap[v->GetName()] = Form("%s_%s",v->GetName(),suffixV) ;
}
delete iter ;
delete vars ;
}
RooAbsArg* wsarg = _allOwnedNodes.find(inArg.GetName()) ;
if (!suffix && wsarg && !useExistingNodes && !(inArg.isFundamental() && varMap[inArg.GetName()]!="")) {
if (wsarg!=&inArg) {
coutE(ObjectHandling) << "RooWorkSpace::import(" << GetName() << ") ERROR importing object named " << inArg.GetName()
<< ": another instance with same name already in the workspace and no conflict resolution protocol specified" << endl ;
return kTRUE ;
} else {
coutI(ObjectHandling) << "RooWorkSpace::import(" << GetName() << ") Object " << inArg.GetName() << " is already in workspace!" << endl ;
return kTRUE ;
}
}
RooArgSet conflictNodes ;
RooArgSet branchSet ;
inArg.branchNodeServerList(&branchSet) ;
TIterator* iter = branchSet.createIterator() ;
RooAbsArg* branch ;
while ((branch=(RooAbsArg*)iter->Next())) {
RooAbsArg* wsbranch = _allOwnedNodes.find(branch->GetName()) ;
if (wsbranch && wsbranch!=branch) {
conflictNodes.add(*branch) ;
}
}
delete iter ;
if (conflictNodes.getSize()>0 && !suffix && !useExistingNodes) {
coutE(ObjectHandling) << "RooWorkSpace::import(" << GetName() << ") ERROR object named " << inArg.GetName() << ": component(s) "
<< conflictNodes << " already in the workspace and no conflict resolution protocol specified" << endl ;
return kTRUE ;
}
RooArgSet* cloneSet = (RooArgSet*) RooArgSet(inArg).snapshot(kTRUE) ;
RooAbsArg* cloneTop = cloneSet->find(inArg.GetName()) ;
if (!conflictOnly) {
conflictNodes.removeAll() ;
conflictNodes.add(branchSet) ;
}
TIterator* citer = conflictNodes.createIterator() ;
string topName2 = cloneTop->GetName() ;
RooAbsArg* cnode ;
while ((cnode=(RooAbsArg*)citer->Next())) {
RooAbsArg* cnode2 = cloneSet->find(cnode->GetName()) ;
string origName = cnode2->GetName() ;
cnode2->SetName(Form("%s_%s",cnode2->GetName(),suffix)) ;
cnode2->SetTitle(Form("%s (%s)",cnode2->GetTitle(),suffix)) ;
string tag = Form("ORIGNAME:%s",origName.c_str()) ;
cnode2->setAttribute(tag.c_str()) ;
if (cnode2==cloneTop) {
topName2 = cnode2->GetName() ;
}
coutI(ObjectHandling) << "RooWorkspace::import(" << GetName()
<< ") Resolving name conflict in workspace by changing name of imported node "
<< origName << " to " << cnode2->GetName() << endl ;
}
delete citer ;
if (strlen(varChangeIn)>0 || (suffixV && strlen(suffixV)>0)) {
TIterator* cliter = cloneSet->createIterator() ;
while ((cnode=(RooAbsArg*)cliter->Next())) {
if (varMap.find(cnode->GetName())!=varMap.end()) {
string origName = cnode->GetName() ;
cnode->SetName(varMap[cnode->GetName()].c_str()) ;
string tag = Form("ORIGNAME:%s",origName.c_str()) ;
cnode->setAttribute(tag.c_str()) ;
coutI(ObjectHandling) << "RooWorkspace::import(" << GetName() << ") Changing name of variable "
<< origName << " to " << cnode->GetName() << " on request" << endl ;
if (cnode==cloneTop) {
topName2 = cnode->GetName() ;
}
}
}
delete cliter ;
}
RooArgSet* cloneSet2 = (RooArgSet*) RooArgSet(*cloneTop).snapshot(kTRUE) ;
RooAbsArg* cloneTop2 = cloneSet2->find(topName2.c_str()) ;
RooArgSet conflictNodes2 ;
RooArgSet branchSet2 ;
inArg.branchNodeServerList(&branchSet) ;
TIterator* iter2 = branchSet2.createIterator() ;
RooAbsArg* branch2 ;
while ((branch2=(RooAbsArg*)iter2->Next())) {
if (_allOwnedNodes.find(branch2->GetName())) {
conflictNodes2.add(*branch2) ;
}
}
delete iter2 ;
if (conflictNodes2.getSize()) {
coutE(ObjectHandling) << "RooWorkSpace::import(" << GetName() << ") ERROR object named " << inArg.GetName() << ": component(s) "
<< conflictNodes2 << " cause naming conflict after conflict resolution protocol was executed" << endl ;
return kTRUE ;
}
iter = cloneSet2->createIterator() ;
RooAbsArg* node ;
RooArgSet recycledNodes ;
while((node=(RooAbsArg*)iter->Next())) {
if (_autoClass) {
if (!_classes.autoImportClass(node->IsA())) {
coutW(ObjectHandling) << "RooWorkspace::import(" << GetName() << ") WARNING: problems import class code of object "
<< node->IsA()->GetName() << "::" << node->GetName() << ", reading of workspace will require external definition of class" << endl ;
}
}
RooExpensiveObjectCache& oldCache = node->expensiveObjectCache() ;
node->setExpensiveObjectCache(_eocache) ;
_eocache.importCacheObjects(oldCache,node->GetName(),kTRUE) ;
if (_allOwnedNodes.find(node->GetName())) {
coutI(ObjectHandling) << "RooWorkspace::import(" << GetName() << ") using existing copy of " << node->IsA()->GetName()
<< "::" << node->GetName() << " for import of " << cloneTop2->IsA()->GetName() << "::"
<< cloneTop2->GetName() << endl ;
recycledNodes.add(*_allOwnedNodes.find(node->GetName())) ;
} else {
coutI(ObjectHandling) << "RooWorkspace::import(" << GetName() << ") importing " << node->IsA()->GetName() << "::"
<< node->GetName() << endl ;
_allOwnedNodes.addOwned(*node) ;
if (_dir) {
_dir->InternalAppend(node) ;
}
}
}
delete cloneSet ;
if (recycledNodes.getSize()>0) {
iter->Reset() ;
while((node=(RooAbsArg*)iter->Next())) {
node->redirectServers(recycledNodes) ;
}
}
delete iter ;
return kFALSE ;
}
Bool_t RooWorkspace::import(RooAbsData& inData, const RooCmdArg& arg1, const RooCmdArg& arg2, const RooCmdArg& arg3)
{
coutI(ObjectHandling) << "RooWorkspace::import(" << GetName() << ") importing dataset " << inData.GetName() << endl ;
RooLinkedList args ;
args.Add((TObject*)&arg1) ;
args.Add((TObject*)&arg2) ;
args.Add((TObject*)&arg3) ;
RooCmdConfig pc(Form("RooWorkspace::import(%s)",GetName())) ;
pc.defineString("dsetName","RenameDataset",0,"") ;
pc.defineString("varChangeIn","RenameVar",0,"",kTRUE) ;
pc.defineString("varChangeOut","RenameVar",1,"",kTRUE) ;
pc.process(args) ;
if (!pc.ok(kTRUE)) {
return kTRUE ;
}
const char* dsetName = pc.getString("dsetName") ;
const char* varChangeIn = pc.getString("varChangeIn") ;
const char* varChangeOut = pc.getString("varChangeOut") ;
if (dsetName && strlen(dsetName)==0) {
dsetName=0 ;
}
RooAbsData* clone ;
if (dsetName) {
coutI(ObjectHandling) << "RooWorkSpace::import(" << GetName() << ") changing name of dataset from " << inData.GetName() << " to " << dsetName << endl ;
clone = (RooAbsData*) inData.Clone(dsetName) ;
} else {
clone = (RooAbsData*) inData.Clone(inData.GetName()) ;
}
if (strlen(varChangeIn)>0) {
char tmp[1024] ;
strcpy(tmp,varChangeIn) ;
list<string> tmpIn,tmpOut ;
char* ptr = strtok(tmp,",") ;
while (ptr) {
tmpIn.push_back(ptr) ;
ptr = strtok(0,",") ;
}
strcpy(tmp,varChangeOut) ;
ptr = strtok(tmp,",") ;
while (ptr) {
tmpOut.push_back(ptr) ;
ptr = strtok(0,",") ;
}
list<string>::iterator iin = tmpIn.begin() ;
list<string>::iterator iout = tmpOut.begin() ;
for (; iin!=tmpIn.end() ; ++iin,++iout) {
coutI(ObjectHandling) << "RooWorkSpace::import(" << GetName() << ") changing name of dataset observable " << *iin << " to " << *iout << endl ;
clone->changeObservableName(iin->c_str(),iout->c_str()) ;
}
}
TIterator* iter = clone->get()->createIterator() ;
RooAbsArg* carg ;
while((carg=(RooAbsArg*)iter->Next())) {
import(*carg) ;
}
delete iter ;
_dataList.Add(clone) ;
return kFALSE ;
}
Bool_t RooWorkspace::importClassCode(TClass* theClass, Bool_t doReplace)
{
return _classes.autoImportClass(theClass,doReplace) ;
}
Bool_t RooWorkspace::importClassCode(const char* pat, Bool_t doReplace)
{
Bool_t ret(kTRUE) ;
TRegexp re(pat,kTRUE) ;
TIterator* iter = componentIterator() ;
RooAbsArg* carg ;
while((carg=(RooAbsArg*)iter->Next())) {
TString className = carg->IsA()->GetName() ;
if (className.Index(re)>=0 && !_classes.autoImportClass(carg->IsA(),doReplace)) {
coutW(ObjectHandling) << "RooWorkspace::import(" << GetName() << ") WARNING: problems import class code of object "
<< carg->IsA()->GetName() << "::" << carg->GetName() << ", reading of workspace will require external definition of class" << endl ;
ret = kFALSE ;
}
}
delete iter ;
return ret ;
}
Bool_t RooWorkspace::saveSnapshot(const char* name, const RooArgSet& params, Bool_t importValues)
{
RooArgSet* actualParams = (RooArgSet*) _allOwnedNodes.selectCommon(params) ;
RooArgSet* snapshot = (RooArgSet*) actualParams->snapshot() ;
delete actualParams ;
snapshot->setName(name) ;
if (importValues) {
*snapshot = params ;
}
RooArgSet* oldSnap = (RooArgSet*) _snapshots.FindObject(name) ;
if (oldSnap) {
coutI(ObjectHandling) << "RooWorkspace::saveSnaphot(" << GetName() << ") replacing previous snapshot with name " << name << endl ;
_snapshots.Remove(oldSnap) ;
delete oldSnap ;
}
_snapshots.Add(snapshot) ;
return kTRUE ;
}
Bool_t RooWorkspace::loadSnapshot(const char* name)
{
RooArgSet* snap = (RooArgSet*) _snapshots.find(name) ;
if (!snap) {
coutE(ObjectHandling) << "RooWorkspace::loadSnapshot(" << GetName() << ") no snapshot with name " << name << " is available" << endl ;
return kFALSE ;
}
RooArgSet* actualParams = (RooArgSet*) _allOwnedNodes.selectCommon(*snap) ;
*actualParams = *snap ;
delete actualParams ;
return kTRUE ;
}
Bool_t RooWorkspace::merge(const RooWorkspace& )
{
return kFALSE ;
}
Bool_t RooWorkspace::join(const RooWorkspace& )
{
return kFALSE ;
}
RooAbsPdf* RooWorkspace::pdf(const char* name)
{
return dynamic_cast<RooAbsPdf*>(_allOwnedNodes.find(name)) ;
}
RooAbsReal* RooWorkspace::function(const char* name)
{
return dynamic_cast<RooAbsReal*>(_allOwnedNodes.find(name)) ;
}
RooRealVar* RooWorkspace::var(const char* name)
{
return dynamic_cast<RooRealVar*>(_allOwnedNodes.find(name)) ;
}
RooCategory* RooWorkspace::cat(const char* name)
{
return dynamic_cast<RooCategory*>(_allOwnedNodes.find(name)) ;
}
RooAbsCategory* RooWorkspace::catfunc(const char* name)
{
return dynamic_cast<RooAbsCategory*>(_allOwnedNodes.find(name)) ;
}
RooAbsArg* RooWorkspace::arg(const char* name)
{
return _allOwnedNodes.find(name) ;
}
RooAbsArg* RooWorkspace::fundArg(const char* name)
{
RooAbsArg* tmp = arg(name) ;
if (!tmp) {
return 0 ;
}
return tmp->isFundamental() ? tmp : 0 ;
}
RooAbsData* RooWorkspace::data(const char* name)
{
return (RooAbsData*)_dataList.FindObject(name) ;
}
Bool_t RooWorkspace::CodeRepo::autoImportClass(TClass* tc, Bool_t doReplace)
{
oocxcoutD(_wspace,ObjectHandling) << "RooWorkspace::CodeRepo(" << _wspace->GetName() << ") request to import code of class " << tc->GetName() << endl ;
if (!doReplace && _c2fmap.find(tc->GetName())!=_c2fmap.end()) {
oocxcoutD(_wspace,ObjectHandling) << "RooWorkspace::CodeRepo(" << _wspace->GetName() << ") code of class " << tc->GetName() << " already imported, skipping" << endl ;
return kTRUE ;
}
string implfile = tc->GetImplFileName() ;
string declfile = tc->GetDeclFileName() ;
if (implfile.empty() || declfile.empty()) {
oocoutE(_wspace,ObjectHandling) << "RooWorkspace::CodeRepo(" << _wspace->GetName() << ") ERROR: cannot retrieve code file names for class "
<< tc->GetName() << " through ROOT TClass interface, unable to import code" << endl ;
return kFALSE ;
}
TString rootsys = gSystem->Getenv("ROOTSYS") ;
char* implpath = gSystem->ConcatFileName(rootsys.Data(),implfile.c_str()) ;
if (!gSystem->AccessPathName(implpath)) {
oocxcoutD(_wspace,ObjectHandling) << "RooWorkspace::CodeRepo(" << _wspace->GetName() << ") code of class " << tc->GetName() << " is in ROOT distribution, skipping " << endl ;
delete[] implpath ;
return kTRUE ;
}
delete[] implpath ;
implpath=0 ;
#if ROOT_VERSION_CODE <= ROOT_VERSION(5,19,02)
if (!(tc->GetClassInfo()->Property()&G__BIT_ISABSTRACT) && !tc->HasDefaultConstructor()) {
#else
if (!(gCint->ClassInfo_Property(tc->GetClassInfo())&G__BIT_ISABSTRACT) && !tc->HasDefaultConstructor()) {
#endif
oocoutW(_wspace,ObjectHandling) << "RooWorkspace::autoImportClass(" << _wspace->GetName() << ") WARNING cannot import class "
<< tc->GetName() << " : it cannot be persisted because it doesn't have a default constructor. Please fix " << endl ;
return kFALSE ;
}
char* declpath = 0 ;
if (gSystem->AccessPathName(declfile.c_str())) {
list<string>::iterator diter = RooWorkspace::_classDeclDirList.begin() ;
while(diter!= RooWorkspace::_classDeclDirList.end()) {
declpath = gSystem->ConcatFileName(diter->c_str(),declfile.c_str()) ;
if (!gSystem->AccessPathName(declpath)) {
break ;
}
delete[] declpath ;
declpath=0 ;
++diter ;
}
if (!declpath) {
oocoutW(_wspace,ObjectHandling) << "RooWorkspace::autoImportClass(" << _wspace->GetName() << ") WARNING Cannot access code of class "
<< tc->GetName() << " because header file " << declfile << " is not found in current directory nor in $ROOTSYS" ;
if (_classDeclDirList.size()>0) {
ooccoutW(_wspace,ObjectHandling) << ", nor in the search path " ;
diter = RooWorkspace::_classDeclDirList.begin() ;
while(diter!= RooWorkspace::_classDeclDirList.end()) {
if (diter!=RooWorkspace::_classDeclDirList.begin()) {
ooccoutW(_wspace,ObjectHandling) << "," ;
}
ooccoutW(_wspace,ObjectHandling) << diter->c_str() ;
++diter ;
}
}
ooccoutW(_wspace,ObjectHandling) << ". To fix this problem add the required directory to the search "
<< "path using RooWorkspace::addClassDeclDir(const char* dir)" << endl ;
return kFALSE ;
}
}
if (gSystem->AccessPathName(implfile.c_str())) {
list<string>::iterator iiter = RooWorkspace::_classImplDirList.begin() ;
while(iiter!= RooWorkspace::_classImplDirList.end()) {
implpath = gSystem->ConcatFileName(iiter->c_str(),implfile.c_str()) ;
if (!gSystem->AccessPathName(implpath)) {
break ;
}
delete[] implpath ;
implpath=0 ;
++iiter ;
}
if (!implpath) {
oocoutW(_wspace,ObjectHandling) << "RooWorkspace::autoImportClass(" << _wspace->GetName() << ") WARNING Cannot access code of class "
<< tc->GetName() << " because implementation file " << implfile << " is not found in current directory nor in $ROOTSYS" ;
if (_classDeclDirList.size()>0) {
ooccoutW(_wspace,ObjectHandling) << ", nor in the search path " ;
iiter = RooWorkspace::_classImplDirList.begin() ;
while(iiter!= RooWorkspace::_classImplDirList.end()) {
if (iiter!=RooWorkspace::_classImplDirList.begin()) {
ooccoutW(_wspace,ObjectHandling) << "," ;
}
ooccoutW(_wspace,ObjectHandling) << iiter->c_str() ;
++iiter ;
}
}
ooccoutW(_wspace,ObjectHandling) << ". To fix this problem add the required directory to the search "
<< "path using RooWorkspace::addClassImplDir(const char* dir)" << endl ;
return kFALSE ;
}
}
char buf[1024] ;
string declfilename = declpath?gSystem->BaseName(declpath):gSystem->BaseName(declfile.c_str()) ;
int dotpos2 = strrchr(declfilename.c_str(),'.') - declfilename.c_str() ;
string declfilebase = declfilename.substr(0,dotpos2) ;
string declfileext = declfilename.substr(dotpos2+1) ;
if (_fmap.find(declfilebase) == _fmap.end()) {
fstream fdecl(declpath?declpath:declfile.c_str()) ;
if (!fdecl) {
oocoutE(_wspace,ObjectHandling) << "RooWorkspace::autoImportClass(" << _wspace->GetName()
<< ") ERROR opening declaration file " << declfile << endl ;
return kFALSE ;
}
oocoutI(_wspace,ObjectHandling) << "RooWorkspace::autoImportClass(" << _wspace->GetName()
<< ") importing code of class " << tc->GetName()
<< " from " << (implpath?implpath:implfile.c_str())
<< " and " << (declpath?declpath:declfile.c_str()) << endl ;
string decl ;
while(fdecl.getline(buf,1023)) {
decl += buf ;
decl += '\n' ;
}
fstream fimpl(implpath?implpath:implfile.c_str()) ;
if (!fimpl) {
oocoutE(_wspace,ObjectHandling) << "RooWorkspace::autoImportClass(" << _wspace->GetName()
<< ") ERROR opening implementation file " << implfile << endl ;
return kFALSE ;
}
string impl ;
while(fimpl.getline(buf,1023)) {
Bool_t foundSelfInclude=kFALSE ;
if (strstr(buf,"#include")) {
char tmp[1024] ;
strcpy(tmp,buf) ;
strtok(tmp," <\"") ;
char* incfile = strtok(0," <\"") ;
if (strstr(incfile,declfilename.c_str())) {
foundSelfInclude=kTRUE ;
}
}
if (foundSelfInclude) {
impl += Form("#include \"%s.%s\"\n",declfilebase.c_str(),declfileext.c_str()) ;
} else {
impl += buf ;
impl += '\n' ;
}
}
_fmap[declfilebase]._hfile = decl ;
_fmap[declfilebase]._cxxfile = impl ;
_fmap[declfilebase]._hext = declfileext ;
} else {
oocoutI(_wspace,ObjectHandling) << "RooWorkspace::autoImportClass(" << _wspace->GetName()
<< ") code of class " << tc->GetName()
<< " was already imported from " << (implpath?implpath:implfile.c_str())
<< " and " << (declpath?declpath:declfile.c_str()) << endl ;
}
TString baseNameList ;
TList* bl = tc->GetListOfBases() ;
TIterator* iter = bl->MakeIterator() ;
TBaseClass* base ;
list<TClass*> bases ;
while((base=(TBaseClass*)iter->Next())) {
if (baseNameList.Length()>0) {
baseNameList += "," ;
}
baseNameList += base->GetClassPointer()->GetName() ;
bases.push_back(base->GetClassPointer()) ;
}
_c2fmap[tc->GetName()]._baseName = baseNameList ;
_c2fmap[tc->GetName()]._fileBase = declfilebase ;
list<TClass*>::iterator biter = bases.begin() ;
while(biter!=bases.end()) {
autoImportClass(*biter,doReplace) ;
++biter ;
}
if (implpath) {
delete[] implpath ;
}
if (declpath) {
delete[] declpath ;
}
return kTRUE ;
}
Bool_t RooWorkspace::makeDir()
{
if (_dir) return kTRUE ;
TString name = Form("%sDir",GetName()) ;
TString title= Form("TDirectory representation of RooWorkspace %s",GetName()) ;
_dir = new WSDir(name.Data(),title.Data(),this) ;
TIterator* iter = componentIterator() ;
RooAbsArg* darg ;
while((darg=(RooAbsArg*)iter->Next())) {
_dir->InternalAppend(darg) ;
}
return kTRUE ;
}
void RooWorkspace::Print(Option_t* ) const
{
cout << endl << "RooWorkspace(" << GetName() << ") " << GetTitle() << " contents" << endl << endl ;
RooAbsArg* parg ;
RooArgSet pdfSet ;
RooArgSet funcSet ;
RooArgSet varSet ;
RooArgSet catfuncSet ;
TIterator* iter = _allOwnedNodes.createIterator() ;
while((parg=(RooAbsArg*)iter->Next())) {
if (parg->IsA()->InheritsFrom(RooAbsPdf::Class())) {
pdfSet.add(*parg) ;
}
if (parg->IsA()->InheritsFrom(RooAbsReal::Class()) &&
!parg->IsA()->InheritsFrom(RooAbsPdf::Class()) &&
!parg->IsA()->InheritsFrom(RooRealVar::Class())) {
funcSet.add(*parg) ;
}
if (parg->IsA()->InheritsFrom(RooRealVar::Class())) {
varSet.add(*parg) ;
}
if (parg->IsA()->InheritsFrom(RooAbsCategory::Class()) &&
!parg->IsA()->InheritsFrom(RooCategory::Class())) {
catfuncSet.add(*parg) ;
}
if (parg->IsA()->InheritsFrom(RooCategory::Class())) {
varSet.add(*parg) ;
}
}
delete iter ;
if (varSet.getSize()>0) {
cout << "variables" << endl ;
cout << "---------" << endl ;
cout << varSet << endl ;
cout << endl ;
}
if (pdfSet.getSize()>0) {
cout << "p.d.f.s" << endl ;
cout << "-------" << endl ;
iter = pdfSet.createIterator() ;
while((parg=(RooAbsArg*)iter->Next())) {
parg->Print() ;
}
delete iter ;
cout << endl ;
}
if (funcSet.getSize()>0) {
cout << "functions" << endl ;
cout << "--------" << endl ;
iter = funcSet.createIterator() ;
while((parg=(RooAbsArg*)iter->Next())) {
parg->Print() ;
}
delete iter ;
cout << endl ;
}
if (catfuncSet.getSize()>0) {
cout << "category functions" << endl ;
cout << "------------------" << endl ;
iter = catfuncSet.createIterator() ;
while((parg=(RooAbsArg*)iter->Next())) {
parg->Print() ;
}
delete iter ;
cout << endl ;
}
if (_dataList.GetSize()>0) {
cout << "datasets" << endl ;
cout << "--------" << endl ;
iter = _dataList.MakeIterator() ;
RooAbsData* data2 ;
while((data2=(RooAbsData*)iter->Next())) {
cout << data2->IsA()->GetName() << "::" << data2->GetName() << *data2->get() << endl ;
}
delete iter ;
cout << endl ;
}
if (_snapshots.GetSize()>0) {
cout << "parameter snapshots" << endl ;
cout << "-------------------" << endl ;
iter = _snapshots.MakeIterator() ;
RooArgSet* snap ;
while((snap=(RooArgSet*)iter->Next())) {
cout << snap->GetName() << " = (" ;
TIterator* aiter = snap->createIterator() ;
RooAbsArg* a ;
Bool_t first(kTRUE) ;
while((a=(RooAbsArg*)aiter->Next())) {
if (first) { first=kFALSE ; } else { cout << "," ; }
cout << a->GetName() << "=" ;
a->printValue(cout) ;
if (a->isConstant()) {
cout << "[C]" ;
}
}
cout << ")" << endl ;
delete aiter ;
}
delete iter ;
cout << endl ;
}
if (_classes.listOfClassNames().size()>0) {
cout << "embedded class code" << endl ;
cout << "-------------------" << endl ;
cout << _classes.listOfClassNames() << endl ;
cout << endl ;
}
if (_eocache.size()>0) {
cout << "embedded precalculated expensive components" << endl ;
cout << "-------------------------------------------" << endl ;
_eocache.print() ;
}
return ;
}
void RooWorkspace::CodeRepo::Streamer(TBuffer &R__b)
{
typedef ::RooWorkspace::CodeRepo thisClass;
if (R__b.IsReading()) {
UInt_t R__s, R__c;
R__b.ReadVersion(&R__s, &R__c);
Int_t count(0) ;
R__b >> count ;
while(count--) {
TString name ;
name.Streamer(R__b) ;
_fmap[name]._hext.Streamer(R__b) ;
_fmap[name]._hfile.Streamer(R__b) ;
_fmap[name]._cxxfile.Streamer(R__b) ;
}
count=0 ;
R__b >> count ;
while(count--) {
TString name,bname,fbase ;
name.Streamer(R__b) ;
_c2fmap[name]._baseName.Streamer(R__b) ;
_c2fmap[name]._fileBase.Streamer(R__b) ;
}
R__b.CheckByteCount(R__s, R__c, thisClass::IsA());
_compiledOK = !compileClasses() ;
} else {
UInt_t R__c;
R__c = R__b.WriteVersion(thisClass::IsA(), kTRUE);
UInt_t count = _fmap.size() ;
R__b << count ;
map<TString,ClassFiles>::iterator iter = _fmap.begin() ;
while(iter!=_fmap.end()) {
TString key_copy(iter->first) ;
key_copy.Streamer(R__b) ;
iter->second._hext.Streamer(R__b) ;
iter->second._hfile.Streamer(R__b);
iter->second._cxxfile.Streamer(R__b);
++iter ;
}
count = _c2fmap.size() ;
R__b << count ;
map<TString,ClassRelInfo>::iterator iter2 = _c2fmap.begin() ;
while(iter2!=_c2fmap.end()) {
TString key_copy(iter2->first) ;
key_copy.Streamer(R__b) ;
iter2->second._baseName.Streamer(R__b) ;
iter2->second._fileBase.Streamer(R__b);
++iter2 ;
}
R__b.SetByteCount(R__c, kTRUE);
}
}
std::string RooWorkspace::CodeRepo::listOfClassNames() const
{
string ret ;
map<TString,ClassRelInfo>::const_iterator iter = _c2fmap.begin() ;
while(iter!=_c2fmap.end()) {
if (ret.size()>0) {
ret += ", " ;
}
ret += iter->first ;
++iter ;
}
return ret ;
}
Bool_t RooWorkspace::CodeRepo::compileClasses()
{
Bool_t haveDir=kFALSE ;
string dirName = Form(_classFileExportDir.c_str(),_wspace->GetName()) ;
map<TString,ClassRelInfo>::iterator iter = _c2fmap.begin() ;
while(iter!=_c2fmap.end()) {
oocxcoutD(_wspace,ObjectHandling) << "RooWorkspace::CodeRepo::compileClasses() now processing class " << iter->first.Data() << endl ;
if (gClassTable->GetDict(iter->first.Data())) {
oocoutI(_wspace,ObjectHandling) << "RooWorkspace::CodeRepo::compileClasses() Embedded class "
<< iter->first << " already in ROOT class table, skipping" << endl ;
++iter ;
continue ;
}
if (!haveDir) {
if (!gSystem->AccessPathName(dirName.c_str())) {
oocoutI(_wspace,ObjectHandling) << "RooWorkspace::CodeRepo::compileClasses() reusing code export directory " << dirName.c_str()
<< " to extract coded embedded in workspace" << endl ;
} else {
if (gSystem->MakeDirectory(dirName.c_str())==0) {
oocoutI(_wspace,ObjectHandling) << "RooWorkspace::CodeRepo::compileClasses() creating code export directory " << dirName.c_str()
<< " to extract coded embedded in workspace" << endl ;
} else {
oocoutE(_wspace,ObjectHandling) << "RooWorkspace::CodeRepo::compileClasses() ERROR creating code export directory " << dirName.c_str()
<< " to extract coded embedded in workspace" << endl ;
return kFALSE ;
}
}
haveDir=kTRUE ;
}
ClassFiles& cfinfo = _fmap[iter->second._fileBase] ;
oocxcoutD(_wspace,ObjectHandling) << "RooWorkspace::CodeRepo::compileClasses() now processing file with base " << iter->second._fileBase << endl ;
if (cfinfo._extracted) {
oocxcoutD(_wspace,ObjectHandling) << "RooWorkspace::CodeRepo::compileClasses() file with base name " << iter->second._fileBase
<< " has already been extracted, skipping to next class" << endl ;
continue ;
}
Bool_t needDeclWrite=kTRUE ;
string fdname = Form("%s/%s.%s",dirName.c_str(),iter->second._fileBase.Data(),cfinfo._hext.Data()) ;
ifstream ifdecl(fdname.c_str()) ;
if (ifdecl) {
TString contents ;
char buf[1024] ;
while(ifdecl.getline(buf,1024)) {
contents += buf ;
contents += "\n" ;
}
UInt_t crcFile = RooAbsArg::crc32(contents.Data()) ;
UInt_t crcWS = RooAbsArg::crc32(cfinfo._hfile.Data()) ;
needDeclWrite = (crcFile!=crcWS) ;
}
if (needDeclWrite) {
oocoutI(_wspace,ObjectHandling) << "RooWorkspace::CodeRepo::compileClasses() Extracting declaration code of class " << iter->first << ", file " << fdname << endl ;
ofstream fdecl(fdname.c_str()) ;
if (!fdecl) {
oocoutE(_wspace,ObjectHandling) << "RooWorkspace::CodeRepo::compileClasses() ERROR opening file"
<< fdname << " for writing" << endl ;
return kFALSE ;
}
fdecl << cfinfo._hfile ;
fdecl.close() ;
}
Bool_t needImplWrite=kTRUE ;
string finame = Form("%s/%s.cxx",dirName.c_str(),iter->second._fileBase.Data()) ;
ifstream ifimpl(finame.c_str()) ;
if (ifimpl) {
TString contents ;
char buf[1024] ;
while(ifimpl.getline(buf,1024)) {
contents += buf ;
contents += "\n" ;
}
UInt_t crcFile = RooAbsArg::crc32(contents.Data()) ;
UInt_t crcWS = RooAbsArg::crc32(cfinfo._cxxfile.Data()) ;
needImplWrite = (crcFile!=crcWS) ;
}
if (needImplWrite) {
oocoutI(_wspace,ObjectHandling) << "RooWorkspace::CodeRepo::compileClasses() Extracting implementation code of class " << iter->first << ", file " << finame << endl ;
ofstream fimpl(finame.c_str()) ;
if (!fimpl) {
oocoutE(_wspace,ObjectHandling) << "RooWorkspace::CodeRepo::compileClasses() ERROR opening file"
<< finame << " for writing" << endl ;
return kFALSE ;
}
fimpl << cfinfo._cxxfile ;
fimpl.close() ;
}
cfinfo._extracted = kTRUE ;
oocxcoutD(_wspace,ObjectHandling) << "RooWorkspace::CodeRepo::compileClasses() marking code unit " << iter->second._fileBase << " as extracted" << endl ;
oocoutI(_wspace,ObjectHandling) << "RooWorkspace::CodeRepo::compileClasses() Compiling code unit " << iter->second._fileBase.Data() << " to define class " << iter->first << endl ;
Bool_t ok = gSystem->CompileMacro(finame.c_str(),"k") ;
if (!ok) {
oocoutE(_wspace,ObjectHandling) << "RooWorkspace::CodeRepo::compileClasses() ERROR compiling class " << iter->first.Data() << ", to fix this you can do the following: " << endl
<< " 1) Fix extracted source code files in directory " << dirName.c_str() << "/" << endl
<< " 2) In clean ROOT session compiled fixed classes by hand using '.x " << dirName.c_str() << "/ClassName.cxx+'" << endl
<< " 3) Reopen file with RooWorkspace with broken source code in UPDATE mode. Access RooWorkspace to force loading of class" << endl
<< " Broken instances in workspace will _not_ be compiled, instead precompiled fixed instances will be used." << endl
<< " 4) Reimport fixed code in workspace using 'RooWorkspace::importClassCode(\"*\",kTRUE)' method, Write() updated workspace to file and close file" << endl
<< " 5) Reopen file in clean ROOT session to confirm that problems are fixed" << endl ;
return kFALSE ;
}
++iter ;
}
return kTRUE ;
}
void RooWorkspace::WSDir::InternalAppend(TObject* obj)
{
#if ROOT_VERSION_CODE <= ROOT_VERSION(5,19,02)
TDirectory::Append(obj) ;
#else
TDirectory::Append(obj,kFALSE) ;
#endif
}
#if ROOT_VERSION_CODE <= ROOT_VERSION(5,19,02)
void RooWorkspace::WSDir::Add(TObject*)
#else
void RooWorkspace::WSDir::Add(TObject*,Bool_t)
#endif
{
coutE(ObjectHandling) << "RooWorkspace::WSDir::Add(" << GetName() << ") ERROR: Directory is read-only representation of a RooWorkspace, use RooWorkspace::import() to add objects" << endl ;
}
#if ROOT_VERSION_CODE <= ROOT_VERSION(5,19,02)
void RooWorkspace::WSDir::Append(TObject*)
#else
void RooWorkspace::WSDir::Append(TObject*,Bool_t)
#endif
{
coutE(ObjectHandling) << "RooWorkspace::WSDir::Add(" << GetName() << ") ERROR: Directory is read-only representation of a RooWorkspace, use RooWorkspace::import() to add objects" << endl ;
}
Last change: Fri Nov 14 16:34:10 2008
Last generated: 2008-11-14 16:34
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.