Logo ROOT  
Reference Guide
RooWorkspace.cxx
Go to the documentation of this file.
1/*****************************************************************************
2 * Project: RooFit *
3 * Package: RooFitCore *
4 * @(#)root/roofitcore:$Id$
5 * Authors: *
6 * WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu *
7 * *
8 * Copyright (c) 2000-2005, Regents of the University of California *
9 * and Stanford University. All rights reserved. *
10 * *
11 * Redistribution and use in source and binary forms, *
12 * with or without modification, are permitted according to the terms *
13 * listed in LICENSE (http://roofit.sourceforge.net/license.txt) *
14 *****************************************************************************/
15
16/**
17\file RooWorkspace.cxx
18\class RooWorkspace
19\ingroup Roofitcore
20
21The RooWorkspace is a persistable container for RooFit projects. A workspace
22can contain and own variables, p.d.f.s, functions and datasets. All objects
23that live in the workspace are owned by the workspace. The `import()` method
24enforces consistency of objects upon insertion into the workspace (e.g. no
25duplicate object with the same name are allowed) and makes sure all objects
26in the workspace are connected to each other. Easy accessor methods like
27`pdf()`, `var()` and `data()` allow to refer to the contents of the workspace by
28object name. The entire RooWorkspace can be saved into a ROOT TFile and organises
29the consistent streaming of its contents without duplication.
30If a RooWorkspace contains custom classes, i.e. classes not in the
31ROOT distribution, portability of workspaces can be enhanced by
32storing the source code of those classes in the workspace as well.
33This process is also organized by the workspace through the
34`importClassCode()` method.
35
36### Seemingly random rashes when reading large workspaces
37When reading or loading workspaces with deeply nested PDFs, one can encounter
38ouf-of-memory errors if the stack size is too small. This manifests in crashes
39at seemingly random locations, or in the process silently ending.
40Unfortunately, ROOT neither recover from this situation, nor warn or give useful
41instructions. When suspecting to have run out of stack memory, check
42```
43ulimit -s
44```
45and try reading again.
46**/
47
48#include "RooWorkspace.h"
49#include "RooHelpers.h"
50#include "RooFit.h"
51#include "RooWorkspaceHandle.h"
52#include "RooAbsPdf.h"
53#include "RooRealVar.h"
54#include "RooCategory.h"
55#include "RooAbsData.h"
56#include "RooCmdConfig.h"
57#include "RooMsgService.h"
58#include "RooConstVar.h"
59#include "RooResolutionModel.h"
60#include "RooPlot.h"
61#include "RooRandom.h"
62#include "TBuffer.h"
63#include "TInterpreter.h"
64#include "TClassTable.h"
65#include "TBaseClass.h"
66#include "TSystem.h"
67#include "TRegexp.h"
68#include "RooFactoryWSTool.h"
69#include "RooAbsStudy.h"
70#include "RooTObjWrap.h"
72#include "TROOT.h"
73#include "TFile.h"
74#include "TH1.h"
75#include <map>
76#include <sstream>
77#include <string>
78
79using namespace std ;
80
81#include "TClass.h"
82#include "Riostream.h"
83#include <string.h>
84
86
87////////////////////////////////////////////////////////////////////////////////
88
90
91////////////////////////////////////////////////////////////////////////////////
92
94
97string RooWorkspace::_classFileExportDir = ".wscode.%s.%s" ;
99
100
101////////////////////////////////////////////////////////////////////////////////
102/// Add `dir` to search path for class declaration (header) files. This is needed
103/// to find class headers custom classes are imported into the workspace.
105{
106 _classDeclDirList.push_back(dir) ;
107}
108
109
110////////////////////////////////////////////////////////////////////////////////
111/// Add `dir` to search path for class implementation (.cxx) files. This is needed
112/// to find class headers custom classes are imported into the workspace.
114{
115 _classImplDirList.push_back(dir) ;
116}
117
118
119////////////////////////////////////////////////////////////////////////////////
120/// Specify the name of the directory in which embedded source
121/// code is unpacked and compiled. The specified string may contain
122/// one '%s' token which will be substituted by the workspace name
123
125{
126 if (dir) {
127 _classFileExportDir = dir ;
128 } else {
129 _classFileExportDir = ".wscode.%s.%s" ;
130 }
131}
132
133
134////////////////////////////////////////////////////////////////////////////////
135/// If flag is true, source code of classes not the the ROOT distribution
136/// is automatically imported if on object of such a class is imported
137/// in the workspace
138
140{
141 _autoClass = flag ;
142}
143
144
145
146////////////////////////////////////////////////////////////////////////////////
147/// Default constructor
148
149RooWorkspace::RooWorkspace() : _classes(this), _dir(nullptr), _factory(nullptr), _doExport(kFALSE), _openTrans(kFALSE)
150{
151}
152
153
154
155////////////////////////////////////////////////////////////////////////////////
156/// Construct empty workspace with given name and title
157
158RooWorkspace::RooWorkspace(const char* name, const char* title) :
159 TNamed(name,title?title:name), _classes(this), _dir(nullptr), _factory(nullptr), _doExport(kFALSE), _openTrans(kFALSE)
160{
161}
162
163
164RooWorkspace::RooWorkspace(const char* name, Bool_t doCINTExport) :
165 TNamed(name,name), _classes(this), _dir(nullptr), _factory(nullptr), _doExport(kFALSE), _openTrans(kFALSE)
166{
167 // Construct empty workspace with given name and option to export reference to all workspace contents to a CINT namespace with the same name
168 if (doCINTExport) {
170 }
171}
172
173
174////////////////////////////////////////////////////////////////////////////////
175/// Workspace copy constructor
176
178 TNamed(other), _uuid(other._uuid), _classes(other._classes,this), _dir(nullptr), _factory(nullptr), _doExport(kFALSE), _openTrans(kFALSE)
179{
180 // Copy owned nodes
182
183 // Copy datasets
184 TIterator* iter = other._dataList.MakeIterator() ;
185 TObject* data2 ;
186 while((data2=iter->Next())) {
187 _dataList.Add(data2->Clone()) ;
188 }
189 delete iter ;
190
191 // Copy snapshots
192 TIterator* iter2 = other._snapshots.MakeIterator() ;
193 RooArgSet* snap ;
194 while((snap=(RooArgSet*)iter2->Next())) {
195 RooArgSet* snapClone = (RooArgSet*) snap->snapshot() ;
196 snapClone->setName(snap->GetName()) ;
197 _snapshots.Add(snapClone) ;
198 }
199 delete iter2 ;
200
201 // Copy named sets
202 for (map<string,RooArgSet>::const_iterator iter3 = other._namedSets.begin() ; iter3 != other._namedSets.end() ; ++iter3) {
203 // Make RooArgSet with equivalent content of this workspace
204 RooArgSet* tmp = (RooArgSet*) _allOwnedNodes.selectCommon(iter3->second) ;
205 _namedSets[iter3->first].add(*tmp) ;
206 delete tmp ;
207 }
208
209 // Copy generic objects
210 TIterator* iter4 = other._genObjects.MakeIterator() ;
211 TObject* gobj ;
212 while((gobj=iter4->Next())) {
213 TObject *theClone = gobj->Clone();
214
215 auto handle = dynamic_cast<RooWorkspaceHandle*>(theClone);
216 if (handle) {
217 handle->ReplaceWS(this);
218 }
219
220 _genObjects.Add(theClone);
221 }
222 delete iter4 ;
223
224}
225
226
227
228////////////////////////////////////////////////////////////////////////////////
229/// Workspace destructor
230
232{
233 // Delete references to variables that were declared in CINT
234 if (_doExport) {
235 unExport() ;
236 }
237
238 // Delete contents
239 _dataList.Delete() ;
240 if (_dir) {
241 delete _dir ;
242 }
244
245 // WVE named sets too?
246
248}
249
250
251////////////////////////////////////////////////////////////////////////////////
252/// Import a RooAbsArg or RooAbsData set from a workspace in a file. Filespec should be constructed as "filename:wspacename:objectname"
253/// The arguments will be passed to the relevant import() or import(RooAbsData&, ...) import calls
254/// \note From python, use `Import()`, since `import` is a reserved keyword.
255Bool_t RooWorkspace::import(const char* fileSpec,
256 const RooCmdArg& arg1, const RooCmdArg& arg2, const RooCmdArg& arg3,
257 const RooCmdArg& arg4, const RooCmdArg& arg5, const RooCmdArg& arg6,
258 const RooCmdArg& arg7, const RooCmdArg& arg8, const RooCmdArg& arg9)
259{
260 // Parse file/workspace/objectname specification
261 std::vector<std::string> tokens = RooHelpers::tokenise(fileSpec, ":");
262
263 // Check that parsing was successful
264 if (tokens.size() != 3) {
265 std::ostringstream stream;
266 for (const auto& token : tokens) {
267 stream << "\n\t" << token;
268 }
269 coutE(InputArguments) << "RooWorkspace(" << GetName() << ") ERROR in file specification, expecting 'filename:wsname:objname', but '" << fileSpec << "' given."
270 << "\nTokens read are:" << stream.str() << endl;
271 return kTRUE ;
272 }
273
274 const std::string& filename = tokens[0];
275 const std::string& wsname = tokens[1];
276 const std::string& objname = tokens[2];
277
278 // Check that file can be opened
279 TFile* f = TFile::Open(filename.c_str()) ;
280 if (f==0) {
281 coutE(InputArguments) << "RooWorkspace(" << GetName() << ") ERROR opening file " << filename << endl ;
282 return 0 ;
283 }
284
285 // That that file contains workspace
286 RooWorkspace* w = dynamic_cast<RooWorkspace*>(f->Get(wsname.c_str())) ;
287 if (w==0) {
288 coutE(InputArguments) << "RooWorkspace(" << GetName() << ") ERROR: No object named " << wsname << " in file " << filename
289 << " or object is not a RooWorkspace" << endl ;
290 return 0 ;
291 }
292
293 // Check that workspace contains object and forward to appropriate import method
294 RooAbsArg* warg = w->arg(objname.c_str()) ;
295 if (warg) {
296 Bool_t ret = import(*warg,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9) ;
297 delete f ;
298 return ret ;
299 }
300 RooAbsData* wdata = w->data(objname.c_str()) ;
301 if (wdata) {
302 Bool_t ret = import(*wdata,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9) ;
303 delete f ;
304 return ret ;
305 }
306
307 coutE(InputArguments) << "RooWorkspace(" << GetName() << ") ERROR: No RooAbsArg or RooAbsData object named " << objname
308 << " in workspace " << wsname << " in file " << filename << endl ;
309 return kTRUE ;
310}
311
312
313////////////////////////////////////////////////////////////////////////////////
314/// Import multiple RooAbsArg objects into workspace. For details on arguments see documentation
315/// of import() method for single RooAbsArg
316/// \note From python, use `Import()`, since `import` is a reserved keyword.
318 const RooCmdArg& arg1, const RooCmdArg& arg2, const RooCmdArg& arg3,
319 const RooCmdArg& arg4, const RooCmdArg& arg5, const RooCmdArg& arg6,
320 const RooCmdArg& arg7, const RooCmdArg& arg8, const RooCmdArg& arg9)
321{
322 unique_ptr<TIterator> iter(args.createIterator()) ;
323 RooAbsArg* oneArg ;
324 Bool_t ret(kFALSE) ;
325 while((oneArg=(RooAbsArg*)iter->Next())) {
326 ret |= import(*oneArg,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9) ;
327 }
328 return ret ;
329}
330
331
332
333////////////////////////////////////////////////////////////////////////////////
334/// Import a RooAbsArg object, e.g. function, p.d.f or variable into the workspace. This import function clones the input argument and will
335/// own the clone. If a composite object is offered for import, e.g. a p.d.f with parameters and observables, the
336/// complete tree of objects is imported. If any of the _variables_ of a composite object (parameters/observables) are already
337/// in the workspace the imported p.d.f. is connected to the already existing variables. If any of the _function_ objects (p.d.f, formulas)
338/// to be imported already exists in the workspace an error message is printed and the import of the entire tree of objects is cancelled.
339/// Several optional arguments can be provided to modify the import procedure.
340///
341/// <table>
342/// <tr><th> Accepted arguments
343/// <tr><td> `RenameConflictNodes(const char* suffix)` <td> Add suffix to branch node name if name conflicts with existing node in workspace
344/// <tr><td> `RenameAllNodes(const char* suffix)` <td> Add suffix to all branch node names including top level node.
345/// <tr><td> `RenameAllVariables(const char* suffix)` <td> Add suffix to all variables of objects being imported.
346/// <tr><td> `RenameAllVariablesExcept(const char* suffix, const char* exceptionList)` <td> Add suffix to all variables names, except ones listed
347/// <tr><td> `RenameVariable(const char* inputName, const char* outputName)` <td> Rename a single variable as specified upon import.
348/// <tr><td> `RecycleConflictNodes()` <td> If any of the function objects to be imported already exist in the name space, connect the
349/// imported expression to the already existing nodes.
350/// \attention Use with care! If function definitions do not match, this alters the definition of your function upon import
351///
352/// <tr><td> `Silence()` <td> Do not issue any info message
353/// </table>
354///
355/// The RenameConflictNodes, RenameNodes and RecycleConflictNodes arguments are mutually exclusive. The RenameVariable argument can be repeated
356/// as often as necessary to rename multiple variables. Alternatively, a single RenameVariable argument can be given with
357/// two comma separated lists.
358/// \note From python, use `Import()`, since `import` is a reserved keyword.
360 const RooCmdArg& arg1, const RooCmdArg& arg2, const RooCmdArg& arg3,
361 const RooCmdArg& arg4, const RooCmdArg& arg5, const RooCmdArg& arg6,
362 const RooCmdArg& arg7, const RooCmdArg& arg8, const RooCmdArg& arg9)
363{
364 RooLinkedList args ;
365 args.Add((TObject*)&arg1) ;
366 args.Add((TObject*)&arg2) ;
367 args.Add((TObject*)&arg3) ;
368 args.Add((TObject*)&arg4) ;
369 args.Add((TObject*)&arg5) ;
370 args.Add((TObject*)&arg6) ;
371 args.Add((TObject*)&arg7) ;
372 args.Add((TObject*)&arg8) ;
373 args.Add((TObject*)&arg9) ;
374
375 // Select the pdf-specific commands
376 RooCmdConfig pc(Form("RooWorkspace::import(%s)",GetName())) ;
377
378 pc.defineString("conflictSuffix","RenameConflictNodes",0) ;
379 pc.defineInt("renameConflictOrig","RenameConflictNodes",0,0) ;
380 pc.defineString("allSuffix","RenameAllNodes",0) ;
381 pc.defineString("allVarsSuffix","RenameAllVariables",0) ;
382 pc.defineString("allVarsExcept","RenameAllVariables",1) ;
383 pc.defineString("varChangeIn","RenameVar",0,"",kTRUE) ;
384 pc.defineString("varChangeOut","RenameVar",1,"",kTRUE) ;
385 pc.defineString("factoryTag","FactoryTag",0) ;
386 pc.defineInt("useExistingNodes","RecycleConflictNodes",0,0) ;
387 pc.defineInt("silence","Silence",0,0) ;
388 pc.defineInt("noRecursion","NoRecursion",0,0) ;
389 pc.defineMutex("RenameConflictNodes","RenameAllNodes") ;
390 pc.defineMutex("RenameConflictNodes","RecycleConflictNodes") ;
391 pc.defineMutex("RenameAllNodes","RecycleConflictNodes") ;
392 pc.defineMutex("RenameVariable","RenameAllVariables") ;
393
394 // Process and check varargs
395 pc.process(args) ;
396 if (!pc.ok(kTRUE)) {
397 return kTRUE ;
398 }
399
400 // Decode renaming logic into suffix string and boolean for conflictOnly mode
401 const char* suffixC = pc.getString("conflictSuffix") ;
402 const char* suffixA = pc.getString("allSuffix") ;
403 const char* suffixV = pc.getString("allVarsSuffix") ;
404 const char* exceptVars = pc.getString("allVarsExcept") ;
405 const char* varChangeIn = pc.getString("varChangeIn") ;
406 const char* varChangeOut = pc.getString("varChangeOut") ;
407 Bool_t renameConflictOrig = pc.getInt("renameConflictOrig") ;
408 Int_t useExistingNodes = pc.getInt("useExistingNodes") ;
409 Int_t silence = pc.getInt("silence") ;
410 Int_t noRecursion = pc.getInt("noRecursion") ;
411
412
413 // Turn zero length strings into null pointers
414 if (suffixC && strlen(suffixC)==0) suffixC = 0 ;
415 if (suffixA && strlen(suffixA)==0) suffixA = 0 ;
416
417 Bool_t conflictOnly = suffixA ? kFALSE : kTRUE ;
418 const char* suffix = suffixA ? suffixA : suffixC ;
419
420 // Process any change in variable names
421 map<string,string> varMap ;
422 if (strlen(varChangeIn)>0) {
423
424 // Parse comma separated lists into map<string,string>
425 const std::vector<std::string> tokIn = RooHelpers::tokenise(varChangeIn, ", ");
426 const std::vector<std::string> tokOut = RooHelpers::tokenise(varChangeOut, ", ");
427 for (unsigned int i=0; i < tokIn.size(); ++i) {
428 varMap.insert(std::make_pair(tokIn[i], tokOut[i]));
429 }
430
431 assert(tokIn.size() == tokOut.size());
432 }
433
434 // Process RenameAllVariables argument if specified
435 // First convert exception list if provided
436 std::set<string> exceptVarNames ;
437 if (exceptVars && strlen(exceptVars)) {
438 const std::vector<std::string> toks = RooHelpers::tokenise(exceptVars, ", ");
439 exceptVarNames.insert(toks.begin(), toks.end());
440 }
441
442 if (suffixV != 0 && strlen(suffixV)>0) {
443 RooArgSet* vars = inArg.getVariables() ;
444 for (const auto v : *vars) {
445 if (exceptVarNames.find(v->GetName())==exceptVarNames.end()) {
446 varMap[v->GetName()] = Form("%s_%s",v->GetName(),suffixV) ;
447 }
448 }
449 delete vars ;
450 }
451
452 // Scan for overlaps with current contents
453 RooAbsArg* wsarg = _allOwnedNodes.find(inArg.GetName()) ;
454
455 // Check for factory specification match
456 const char* tagIn = inArg.getStringAttribute("factory_tag") ;
457 const char* tagWs = wsarg ? wsarg->getStringAttribute("factory_tag") : 0 ;
458 Bool_t factoryMatch = (tagIn && tagWs && !strcmp(tagIn,tagWs)) ;
459 if (factoryMatch) {
460 ((RooAbsArg&)inArg).setAttribute("RooWorkspace::Recycle") ;
461 }
462
463 if (!suffix && wsarg && !useExistingNodes && !(inArg.isFundamental() && varMap[inArg.GetName()]!="")) {
464 if (!factoryMatch) {
465 if (wsarg!=&inArg) {
466 coutE(ObjectHandling) << "RooWorkSpace::import(" << GetName() << ") ERROR importing object named " << inArg.GetName()
467 << ": another instance with same name already in the workspace and no conflict resolution protocol specified" << endl ;
468 return kTRUE ;
469 } else {
470 if (!silence) {
471 coutI(ObjectHandling) << "RooWorkSpace::import(" << GetName() << ") Object " << inArg.GetName() << " is already in workspace!" << endl ;
472 }
473 return kTRUE ;
474 }
475 } else {
476 coutI(ObjectHandling) << "RooWorkSpace::import(" << GetName() << ") Recycling existing object " << inArg.GetName() << " created with identical factory specification" << endl ;
477 }
478 }
479
480 // Make list of conflicting nodes
481 RooArgSet conflictNodes ;
482 RooArgSet branchSet ;
483 if (noRecursion) {
484 branchSet.add(inArg) ;
485 } else {
486 inArg.branchNodeServerList(&branchSet) ;
487 }
488
489 for (const auto branch : branchSet) {
490 RooAbsArg* wsbranch = _allOwnedNodes.find(branch->GetName()) ;
491 if (wsbranch && wsbranch!=branch && !branch->getAttribute("RooWorkspace::Recycle") && !useExistingNodes) {
492 conflictNodes.add(*branch) ;
493 }
494 }
495
496 // Terminate here if there are conflicts and no resolution protocol
497 if (conflictNodes.getSize()>0 && !suffix && !useExistingNodes) {
498 coutE(ObjectHandling) << "RooWorkSpace::import(" << GetName() << ") ERROR object named " << inArg.GetName() << ": component(s) "
499 << conflictNodes << " already in the workspace and no conflict resolution protocol specified" << endl ;
500 return kTRUE ;
501 }
502
503 // Now create a working copy of the incoming object tree
504 RooArgSet* cloneSet = new RooArgSet();
505 cloneSet->useHashMapForFind(true); // Accelerate finding
506 RooArgSet(inArg).snapshot(*cloneSet, !noRecursion);
507 RooAbsArg* cloneTop = cloneSet->find(inArg.GetName()) ;
508
509 // Mark all nodes for renaming if we are not in conflictOnly mode
510 if (!conflictOnly) {
511 conflictNodes.removeAll() ;
512 conflictNodes.add(branchSet) ;
513 }
514
515 // Mark nodes that are to be renamed with special attribute
516 string topName2 = cloneTop->GetName() ;
517 if (!renameConflictOrig) {
518 // Mark all nodes to be imported for renaming following conflict resolution protocol
519 for (const auto cnode : conflictNodes) {
520 RooAbsArg* cnode2 = cloneSet->find(cnode->GetName()) ;
521 string origName = cnode2->GetName() ;
522 cnode2->SetName(Form("%s_%s",cnode2->GetName(),suffix)) ;
523 cnode2->SetTitle(Form("%s (%s)",cnode2->GetTitle(),suffix)) ;
524 string tag = Form("ORIGNAME:%s",origName.c_str()) ;
525 cnode2->setAttribute(tag.c_str()) ;
526 if (!cnode2->getStringAttribute("origName")) {
527 string tag2 = Form("%s",origName.c_str()) ;
528 cnode2->setStringAttribute("origName",tag2.c_str()) ;
529 }
530
531 // Save name of new top level node for later use
532 if (cnode2==cloneTop) {
533 topName2 = cnode2->GetName() ;
534 }
535
536 if (!silence) {
537 coutI(ObjectHandling) << "RooWorkspace::import(" << GetName()
538 << ") Resolving name conflict in workspace by changing name of imported node "
539 << origName << " to " << cnode2->GetName() << endl ;
540 }
541 }
542 } else {
543
544 // Rename all nodes already in the workspace to 'clear the way' for the imported nodes
545 for (const auto cnode : conflictNodes) {
546
547 string origName = cnode->GetName() ;
548 RooAbsArg* wsnode = _allOwnedNodes.find(origName.c_str()) ;
549 if (wsnode) {
550
551 if (!wsnode->getStringAttribute("origName")) {
552 wsnode->setStringAttribute("origName",wsnode->GetName()) ;
553 }
554
555 if (!_allOwnedNodes.find(Form("%s_%s",cnode->GetName(),suffix))) {
556 wsnode->SetName(Form("%s_%s",cnode->GetName(),suffix)) ;
557 wsnode->SetTitle(Form("%s (%s)",cnode->GetTitle(),suffix)) ;
558 } else {
559 // Name with suffix already taken, add additional suffix
560 for (unsigned int n=1; true; ++n) {
561 string newname = Form("%s_%s_%d",cnode->GetName(),suffix,n) ;
562 if (!_allOwnedNodes.find(newname.c_str())) {
563 wsnode->SetName(newname.c_str()) ;
564 wsnode->SetTitle(Form("%s (%s %d)",cnode->GetTitle(),suffix,n)) ;
565 break ;
566 }
567 }
568 }
569 if (!silence) {
570 coutI(ObjectHandling) << "RooWorkspace::import(" << GetName()
571 << ") Resolving name conflict in workspace by changing name of original node "
572 << origName << " to " << wsnode->GetName() << endl ;
573 }
574 } else {
575 coutW(ObjectHandling) << "RooWorkspce::import(" << GetName() << ") Internal error: expected to find existing node "
576 << origName << " to be renamed, but didn't find it..." << endl ;
577 }
578
579 }
580 }
581
582 // Process any change in variable names
583 if (strlen(varChangeIn)>0 || (suffixV && strlen(suffixV)>0)) {
584
585 // Process all changes in variable names
586 for (const auto cnode : *cloneSet) {
587
588 if (varMap.find(cnode->GetName())!=varMap.end()) {
589 string origName = cnode->GetName() ;
590 cnode->SetName(varMap[cnode->GetName()].c_str()) ;
591 string tag = Form("ORIGNAME:%s",origName.c_str()) ;
592 cnode->setAttribute(tag.c_str()) ;
593 if (!cnode->getStringAttribute("origName")) {
594 string tag2 = Form("%s",origName.c_str()) ;
595 cnode->setStringAttribute("origName",tag2.c_str()) ;
596 }
597
598 if (!silence) {
599 coutI(ObjectHandling) << "RooWorkspace::import(" << GetName() << ") Changing name of variable "
600 << origName << " to " << cnode->GetName() << " on request" << endl ;
601 }
602
603 if (cnode==cloneTop) {
604 topName2 = cnode->GetName() ;
605 }
606
607 }
608 }
609 }
610
611 // Now clone again with renaming effective
612 RooArgSet* cloneSet2 = new RooArgSet();
613 cloneSet2->useHashMapForFind(true); // Faster finding
614 RooArgSet(*cloneTop).snapshot(*cloneSet2, !noRecursion);
615 RooAbsArg* cloneTop2 = cloneSet2->find(topName2.c_str()) ;
616
617 // Make final check list of conflicting nodes
618 RooArgSet conflictNodes2 ;
619 RooArgSet branchSet2 ;
620 for (const auto branch2 : branchSet2) {
621 if (_allOwnedNodes.find(branch2->GetName())) {
622 conflictNodes2.add(*branch2) ;
623 }
624 }
625
626 // Terminate here if there are conflicts and no resolution protocol
627 if (conflictNodes2.getSize()) {
628 coutE(ObjectHandling) << "RooWorkSpace::import(" << GetName() << ") ERROR object named " << inArg.GetName() << ": component(s) "
629 << conflictNodes2 << " cause naming conflict after conflict resolution protocol was executed" << endl ;
630 return kTRUE ;
631 }
632
633 // Perform any auxiliary imports at this point
634 for (const auto node : *cloneSet2) {
635 if (node->importWorkspaceHook(*this)) {
636 coutE(ObjectHandling) << "RooWorkSpace::import(" << GetName() << ") ERROR object named " << node->GetName()
637 << " has an error in importing in one or more of its auxiliary objects, aborting" << endl ;
638 return kTRUE ;
639 }
640 }
641
642 RooArgSet recycledNodes ;
643 RooArgSet nodesToBeDeleted ;
644 for (const auto node : *cloneSet2) {
645 if (_autoClass) {
646 if (!_classes.autoImportClass(node->IsA())) {
647 coutW(ObjectHandling) << "RooWorkspace::import(" << GetName() << ") WARNING: problems import class code of object "
648 << node->IsA()->GetName() << "::" << node->GetName() << ", reading of workspace will require external definition of class" << endl ;
649 }
650 }
651
652 // Point expensiveObjectCache to copy in this workspace
653 RooExpensiveObjectCache& oldCache = node->expensiveObjectCache() ;
654 node->setExpensiveObjectCache(_eocache) ;
655 _eocache.importCacheObjects(oldCache,node->GetName(),kTRUE) ;
656
657 // Check if node is already in workspace (can only happen for variables or identical instances, unless RecycleConflictNodes is specified)
658 RooAbsArg* wsnode = _allOwnedNodes.find(node->GetName()) ;
659
660 if (wsnode) {
661 // Do not import node, add not to list of nodes that require reconnection
662 if (!silence && useExistingNodes) {
663 coutI(ObjectHandling) << "RooWorkspace::import(" << GetName() << ") using existing copy of " << node->IsA()->GetName()
664 << "::" << node->GetName() << " for import of " << cloneTop2->IsA()->GetName() << "::"
665 << cloneTop2->GetName() << endl ;
666 }
667 recycledNodes.add(*_allOwnedNodes.find(node->GetName())) ;
668
669 // Delete clone of incoming node
670 nodesToBeDeleted.addOwned(*node) ;
671
672 //cout << "WV: recycling existing node " << existingNode << " = " << existingNode->GetName() << " for imported node " << node << endl ;
673
674 } else {
675 // Import node
676 if (!silence) {
677 coutI(ObjectHandling) << "RooWorkspace::import(" << GetName() << ") importing " << node->IsA()->GetName() << "::"
678 << node->GetName() << endl ;
679 }
680 _allOwnedNodes.addOwned(*node) ;
681 if (_openTrans) {
682 _sandboxNodes.add(*node) ;
683 } else {
684 if (_dir && node->IsA() != RooConstVar::Class()) {
685 _dir->InternalAppend(node) ;
686 }
687 if (_doExport && node->IsA() != RooConstVar::Class()) {
688 exportObj(node) ;
689 }
690 }
691 }
692 }
693
694 // Release working copy
695 // no need to do a safe list erase since it was generated from a snapshot
696 // just take ownership and delte elements by hand
697 cloneSet->releaseOwnership();
698 for (auto cloneNode : *cloneSet){
699 delete cloneNode;
700 }
701 delete cloneSet ;
702
703 // Reconnect any nodes that need to be
704 if (recycledNodes.getSize()>0) {
705 for (const auto node : *cloneSet2) {
706 node->redirectServers(recycledNodes) ;
707 }
708 }
709
710 cloneSet2->releaseOwnership() ;
711 delete cloneSet2 ;
712
713 return kFALSE ;
714}
715
716
717
718////////////////////////////////////////////////////////////////////////////////
719/// Import a dataset (RooDataSet or RooDataHist) into the work space. The workspace will contain a copy of the data.
720/// The dataset and its variables can be renamed upon insertion with the options below
721///
722/// <table>
723/// <tr><th> Accepted arguments
724/// <tr><td> `Rename(const char* suffix)` <td> Rename dataset upon insertion
725/// <tr><td> `RenameVariable(const char* inputName, const char* outputName)` <td> Change names of observables in dataset upon insertion
726/// <tr><td> `Silence` <td> Be quiet, except in case of errors
727/// \note From python, use `Import()`, since `import` is a reserved keyword.
729 const RooCmdArg& arg1, const RooCmdArg& arg2, const RooCmdArg& arg3,
730 const RooCmdArg& arg4, const RooCmdArg& arg5, const RooCmdArg& arg6,
731 const RooCmdArg& arg7, const RooCmdArg& arg8, const RooCmdArg& arg9)
732
733{
734
735 RooLinkedList args ;
736 args.Add((TObject*)&arg1) ;
737 args.Add((TObject*)&arg2) ;
738 args.Add((TObject*)&arg3) ;
739 args.Add((TObject*)&arg4) ;
740 args.Add((TObject*)&arg5) ;
741 args.Add((TObject*)&arg6) ;
742 args.Add((TObject*)&arg7) ;
743 args.Add((TObject*)&arg8) ;
744 args.Add((TObject*)&arg9) ;
745
746 // Select the pdf-specific commands
747 RooCmdConfig pc(Form("RooWorkspace::import(%s)",GetName())) ;
748
749 pc.defineString("dsetName","Rename",0,"") ;
750 pc.defineString("varChangeIn","RenameVar",0,"",kTRUE) ;
751 pc.defineString("varChangeOut","RenameVar",1,"",kTRUE) ;
752 pc.defineInt("embedded","Embedded",0,0) ;
753 pc.defineInt("silence","Silence",0,0) ;
754
755 // Process and check varargs
756 pc.process(args) ;
757 if (!pc.ok(kTRUE)) {
758 return kTRUE ;
759 }
760
761 // Decode renaming logic into suffix string and boolean for conflictOnly mode
762 const char* dsetName = pc.getString("dsetName") ;
763 const char* varChangeIn = pc.getString("varChangeIn") ;
764 const char* varChangeOut = pc.getString("varChangeOut") ;
765 Bool_t embedded = pc.getInt("embedded") ;
766 Int_t silence = pc.getInt("silence") ;
767
768 if (!silence)
769 coutI(ObjectHandling) << "RooWorkspace::import(" << GetName() << ") importing dataset " << inData.GetName() << endl ;
770
771 // Transform emtpy string into null pointer
772 if (dsetName && strlen(dsetName)==0) {
773 dsetName=0 ;
774 }
775
776 RooLinkedList& dataList = embedded ? _embeddedDataList : _dataList ;
777 if (dataList.GetSize() > 50 && dataList.getHashTableSize() == 0) {
778 // When the workspaces get larger, traversing the linked list becomes a bottleneck:
779 dataList.setHashTableSize(200);
780 }
781
782 // Check that no dataset with target name already exists
783 if (dsetName && dataList.FindObject(dsetName)) {
784 coutE(ObjectHandling) << "RooWorkspace::import(" << GetName() << ") ERROR dataset with name " << dsetName << " already exists in workspace, import aborted" << endl ;
785 return kTRUE ;
786 }
787 if (!dsetName && dataList.FindObject(inData.GetName())) {
788 coutE(ObjectHandling) << "RooWorkspace::import(" << GetName() << ") ERROR dataset with name " << inData.GetName() << " already exists in workspace, import aborted" << endl ;
789 return kTRUE ;
790 }
791
792 // Rename dataset if required
793 RooAbsData* clone ;
794 if (dsetName) {
795 if (!silence)
796 coutI(ObjectHandling) << "RooWorkSpace::import(" << GetName() << ") changing name of dataset from " << inData.GetName() << " to " << dsetName << endl ;
797 clone = (RooAbsData*) inData.Clone(dsetName) ;
798 } else {
799 clone = (RooAbsData*) inData.Clone(inData.GetName()) ;
800 }
801
802
803 // Process any change in variable names
804 if (strlen(varChangeIn)>0) {
805 // Parse comma separated lists of variable name changes
806 const std::vector<std::string> tokIn = RooHelpers::tokenise(varChangeIn, ",");
807 const std::vector<std::string> tokOut = RooHelpers::tokenise(varChangeOut, ",");
808 for (unsigned int i=0; i < tokIn.size(); ++i) {
809 if (!silence)
810 coutI(ObjectHandling) << "RooWorkSpace::import(" << GetName() << ") changing name of dataset observable " << tokIn[i] << " to " << tokOut[i] << endl ;
811 clone->changeObservableName(tokIn[i].c_str(), tokOut[i].c_str());
812 }
813 }
814
815 // Now import the dataset observables, unless dataset is embedded
816 RooAbsArg* carg ;
817 if (!embedded) {
818 TIterator* iter = clone->get()->createIterator() ;
819 while((carg=(RooAbsArg*)iter->Next())) {
820 if (!arg(carg->GetName())) {
821 import(*carg) ;
822 }
823 }
824 delete iter ;
825 }
826
827 dataList.Add(clone) ;
828 if (_dir) {
829 _dir->InternalAppend(clone) ;
830 }
831 if (_doExport) {
832 exportObj(clone) ;
833 }
834
835 // Set expensive object cache of dataset internal buffers to that of workspace
836 RooFIter iter2 = clone->get()->fwdIterator() ;
837 while ((carg=iter2.next())) {
839 }
840
841
842 return kFALSE ;
843}
844
845
846
847
848////////////////////////////////////////////////////////////////////////////////
849/// Define a named RooArgSet with given constituents. If importMissing is true, any constituents
850/// of aset that are not in the workspace will be imported, otherwise an error is returned
851/// for missing components
852
853Bool_t RooWorkspace::defineSet(const char* name, const RooArgSet& aset, Bool_t importMissing)
854{
855 // Check if set was previously defined, if so print warning
856 map<string,RooArgSet>::iterator i = _namedSets.find(name) ;
857 if (i!=_namedSets.end()) {
858 coutW(InputArguments) << "RooWorkspace::defineSet(" << GetName() << ") WARNING redefining previously defined named set " << name << endl ;
859 }
860
861 RooArgSet wsargs ;
862
863 // Check all constituents of provided set
864 TIterator* iter = aset.createIterator() ;
865 RooAbsArg* sarg ;
866 while((sarg=(RooAbsArg*)iter->Next())) {
867 // If missing, either import or report error
868 if (!arg(sarg->GetName())) {
869 if (importMissing) {
870 import(*sarg) ;
871 } else {
872 coutE(InputArguments) << "RooWorkspace::defineSet(" << GetName() << ") ERROR set constituent \"" << sarg->GetName()
873 << "\" is not in workspace and importMissing option is disabled" << endl ;
874 return kTRUE ;
875 }
876 }
877 wsargs.add(*arg(sarg->GetName())) ;
878 }
879 delete iter ;
880
881 // Install named set
882 _namedSets[name].removeAll() ;
883 _namedSets[name].add(wsargs) ;
884
885 return kFALSE ;
886}
887
888//_____________________________________________________________________________
890{
891 // Define a named RooArgSet with given constituents. If importMissing is true, any constituents
892 // of aset that are not in the workspace will be imported, otherwise an error is returned
893 // for missing components
894
895 // Check if set was previously defined, if so print warning
896 map<string, RooArgSet>::iterator i = _namedSets.find(name);
897 if (i != _namedSets.end()) {
898 coutW(InputArguments) << "RooWorkspace::defineSet(" << GetName()
899 << ") WARNING redefining previously defined named set " << name << endl;
900 }
901
902 // Install named set
903 _namedSets[name].removeAll();
904 _namedSets[name].add(aset);
905
906 return kFALSE;
907}
908
909////////////////////////////////////////////////////////////////////////////////
910/// Define a named set in the work space through a comma separated list of
911/// names of objects already in the workspace
912
913Bool_t RooWorkspace::defineSet(const char* name, const char* contentList)
914{
915 // Check if set was previously defined, if so print warning
916 map<string,RooArgSet>::iterator i = _namedSets.find(name) ;
917 if (i!=_namedSets.end()) {
918 coutW(InputArguments) << "RooWorkspace::defineSet(" << GetName() << ") WARNING redefining previously defined named set " << name << endl ;
919 }
920
921 RooArgSet wsargs ;
922
923 // Check all constituents of provided set
924 for (const std::string& token : RooHelpers::tokenise(contentList, ",")) {
925 // If missing, either import or report error
926 if (!arg(token.c_str())) {
927 coutE(InputArguments) << "RooWorkspace::defineSet(" << GetName() << ") ERROR proposed set constituent \"" << token
928 << "\" is not in workspace" << endl ;
929 return kTRUE ;
930 }
931 wsargs.add(*arg(token.c_str())) ;
932 }
933
934 // Install named set
935 _namedSets[name].removeAll() ;
936 _namedSets[name].add(wsargs) ;
937
938 return kFALSE ;
939}
940
941
942
943
944////////////////////////////////////////////////////////////////////////////////
945/// Define a named set in the work space through a comma separated list of
946/// names of objects already in the workspace
947
948Bool_t RooWorkspace::extendSet(const char* name, const char* newContents)
949{
950 RooArgSet wsargs ;
951
952 // Check all constituents of provided set
953 for (const std::string& token : RooHelpers::tokenise(newContents, ",")) {
954 // If missing, either import or report error
955 if (!arg(token.c_str())) {
956 coutE(InputArguments) << "RooWorkspace::defineSet(" << GetName() << ") ERROR proposed set constituent \"" << token
957 << "\" is not in workspace" << endl ;
958 return kTRUE ;
959 }
960 wsargs.add(*arg(token.c_str())) ;
961 }
962
963 // Extend named set
964 _namedSets[name].add(wsargs,kTRUE) ;
965
966 return kFALSE ;
967}
968
969
970
971////////////////////////////////////////////////////////////////////////////////
972/// Return pointer to previously defined named set with given nmame
973/// If no such set is found a null pointer is returned
974
976{
977 map<string,RooArgSet>::iterator i = _namedSets.find(name) ;
978 return (i!=_namedSets.end()) ? &(i->second) : 0 ;
979}
980
981
982
983
984////////////////////////////////////////////////////////////////////////////////
985/// Rename set to a new name
986
987Bool_t RooWorkspace::renameSet(const char* name, const char* newName)
988{
989 // First check if set exists
990 if (!set(name)) {
991 coutE(InputArguments) << "RooWorkspace::renameSet(" << GetName() << ") ERROR a set with name " << name
992 << " does not exist" << endl ;
993 return kTRUE ;
994 }
995
996 // Check if no set exists with new name
997 if (set(newName)) {
998 coutE(InputArguments) << "RooWorkspace::renameSet(" << GetName() << ") ERROR a set with name " << newName
999 << " already exists" << endl ;
1000 return kTRUE ;
1001 }
1002
1003 // Copy entry under 'name' to 'newName'
1004 _namedSets[newName].add(_namedSets[name]) ;
1005
1006 // Remove entry under old name
1007 _namedSets.erase(name) ;
1008
1009 return kFALSE ;
1010}
1011
1012
1013
1014
1015////////////////////////////////////////////////////////////////////////////////
1016/// Remove a named set from the workspace
1017
1019{
1020 // First check if set exists
1021 if (!set(name)) {
1022 coutE(InputArguments) << "RooWorkspace::removeSet(" << GetName() << ") ERROR a set with name " << name
1023 << " does not exist" << endl ;
1024 return kTRUE ;
1025 }
1026
1027 // Remove set with given name
1028 _namedSets.erase(name) ;
1029
1030 return kFALSE ;
1031}
1032
1033
1034
1035
1036////////////////////////////////////////////////////////////////////////////////
1037/// Open an import transaction operations. Returns kTRUE if successful, kFALSE
1038/// if there is already an ongoing transaction
1039
1041{
1042 // Check that there was no ongoing transaction
1043 if (_openTrans) {
1044 return kFALSE ;
1045 }
1046
1047 // Open transaction
1048 _openTrans = kTRUE ;
1049 return kTRUE ;
1050}
1051
1052
1053
1054
1055////////////////////////////////////////////////////////////////////////////////
1056/// Cancel an ongoing import transaction. All objects imported since startTransaction()
1057/// will be removed and the transaction will be terminated. Return kTRUE if cancel operation
1058/// succeeds, return kFALSE if there was no open transaction
1059
1061{
1062 // Check that there is an ongoing transaction
1063 if (!_openTrans) {
1064 return kFALSE ;
1065 }
1066
1067 // Delete all objects in the sandbox
1069 RooAbsArg* tmpArg ;
1070 while((tmpArg=(RooAbsArg*)iter->Next())) {
1071 _allOwnedNodes.remove(*tmpArg) ;
1072 }
1073 delete iter ;
1075
1076 // Mark transaction as finished
1077 _openTrans = kFALSE ;
1078
1079 return kTRUE ;
1080}
1081
1083{
1084 // Commit an ongoing import transaction. Returns kTRUE if commit succeeded,
1085 // return kFALSE if there was no ongoing transaction
1086
1087 // Check that there is an ongoing transaction
1088 if (!_openTrans) {
1089 return kFALSE ;
1090 }
1091
1092 // Publish sandbox nodes in directory and/or CINT if requested
1094 RooAbsArg* sarg ;
1095 while((sarg=(RooAbsArg*)iter->Next())) {
1096 if (_dir && sarg->IsA() != RooConstVar::Class()) {
1097 _dir->InternalAppend(sarg) ;
1098 }
1099 if (_doExport && sarg->IsA() != RooConstVar::Class()) {
1100 exportObj(sarg) ;
1101 }
1102 }
1103 delete iter ;
1104
1105 // Remove all committed objects from the sandbox
1107
1108 // Mark transaction as finished
1109 _openTrans = kFALSE ;
1110
1111 return kTRUE ;
1112}
1113
1114
1115
1116
1117////////////////////////////////////////////////////////////////////////////////
1118
1120{
1121 return _classes.autoImportClass(theClass,doReplace) ;
1122}
1123
1124
1125
1126////////////////////////////////////////////////////////////////////////////////
1127/// Inport code of all classes in the workspace that have a class name
1128/// that matches pattern 'pat' and which are not found to be part of
1129/// the standard ROOT distribution. If doReplace is true any existing
1130/// class code saved in the workspace is replaced
1131
1133{
1134 Bool_t ret(kTRUE) ;
1135
1136 TRegexp re(pat,kTRUE) ;
1137 TIterator* iter = componentIterator() ;
1138 RooAbsArg* carg ;
1139 while((carg=(RooAbsArg*)iter->Next())) {
1140 TString className = carg->IsA()->GetName() ;
1141 if (className.Index(re)>=0 && !_classes.autoImportClass(carg->IsA(),doReplace)) {
1142 coutW(ObjectHandling) << "RooWorkspace::import(" << GetName() << ") WARNING: problems import class code of object "
1143 << carg->IsA()->GetName() << "::" << carg->GetName() << ", reading of workspace will require external definition of class" << endl ;
1144 ret = kFALSE ;
1145 }
1146 }
1147 delete iter ;
1148
1149 return ret ;
1150}
1151
1152
1153
1154
1155
1156////////////////////////////////////////////////////////////////////////////////
1157/// Save snapshot of values and attributes (including "Constant") of given parameters.
1158/// \param[in] name Name of the snapshot.
1159/// \param[in] paramNames Comma-separated list of parameter names to be snapshot.
1160Bool_t RooWorkspace::saveSnapshot(const char* name, const char* paramNames)
1161{
1162 return saveSnapshot(name,argSet(paramNames),kFALSE) ;
1163}
1164
1165
1166
1167
1168
1169////////////////////////////////////////////////////////////////////////////////
1170/// Save snapshot of values and attributes (including "Constant") of parameters 'params'.
1171/// If importValues is FALSE, the present values from the object in the workspace are
1172/// saved. If importValues is TRUE, the values of the objects passed in the 'params'
1173/// argument are saved
1174
1175Bool_t RooWorkspace::saveSnapshot(const char* name, const RooArgSet& params, Bool_t importValues)
1176{
1177 RooArgSet* actualParams = (RooArgSet*) _allOwnedNodes.selectCommon(params) ;
1178 RooArgSet* snapshot = (RooArgSet*) actualParams->snapshot() ;
1179 delete actualParams ;
1180
1181 snapshot->setName(name) ;
1182
1183 if (importValues) {
1184 *snapshot = params ;
1185 }
1186
1188 if (oldSnap) {
1189 coutI(ObjectHandling) << "RooWorkspace::saveSnaphot(" << GetName() << ") replacing previous snapshot with name " << name << endl ;
1190 _snapshots.Remove(oldSnap) ;
1191 delete oldSnap ;
1192 }
1193
1194 _snapshots.Add(snapshot) ;
1195
1196 return kTRUE ;
1197}
1198
1199
1200
1201
1202////////////////////////////////////////////////////////////////////////////////
1203/// Load the values and attributes of the parameters in the snapshot saved with
1204/// the given name
1205
1207{
1208 RooArgSet* snap = (RooArgSet*) _snapshots.find(name) ;
1209 if (!snap) {
1210 coutE(ObjectHandling) << "RooWorkspace::loadSnapshot(" << GetName() << ") no snapshot with name " << name << " is available" << endl ;
1211 return kFALSE ;
1212 }
1213
1214 RooArgSet* actualParams = (RooArgSet*) _allOwnedNodes.selectCommon(*snap) ;
1215 *actualParams = *snap ;
1216 delete actualParams ;
1217
1218 return kTRUE ;
1219}
1220
1221
1222////////////////////////////////////////////////////////////////////////////////
1223/// Return the RooArgSet containing a snapshot of variables contained in the workspace
1224///
1225/// Note that the variables of the objects in the snapshots are **copies** of the
1226/// variables in the workspace. To load the values of a snapshot in the workspace
1227/// variables, use loadSnapshot() instead.
1228
1230{
1231 RooArgSet* snap = (RooArgSet*) _snapshots.find(name) ;
1232 if (!snap) {
1233 coutE(ObjectHandling) << "RooWorkspace::loadSnapshot(" << GetName() << ") no snapshot with name " << name << " is available" << endl ;
1234 return 0 ;
1235 }
1236
1237 return snap ;
1238}
1239
1240
1241
1242// //_____________________________________________________________________________
1243// RooAbsPdf* RooWorkspace::joinPdf(const char* jointPdfName, const char* indexName, const char* inputMapping)
1244// {
1245// // Join given list of p.d.f.s into a simultaneous p.d.f with given name. If the named index category
1246// // does not exist, it is created.
1247// //
1248// // Example : joinPdf("simPdf","expIndex","A=pdfA,B=pdfB") ;
1249// //
1250// // will return a RooSimultaneous named 'simPdf' with index category 'expIndex' with
1251// // state names A and B. Pdf 'pdfA' will be associated with state A and pdf 'pdfB'
1252// // will be associated with state B
1253// //
1254// return 0 ;
1255// }
1256
1257// //_____________________________________________________________________________
1258// RooAbsData* RooWorkspace::joinData(const char* jointDataName, const char* indexName, const char* inputMapping)
1259// {
1260// // Join given list of dataset into a joint dataset for use with a simultaneous pdf
1261// // (as e.g. created by joingPdf"
1262// //
1263// // Example : joinData("simData","expIndex","A=dataA,B=dataB") ;
1264// //
1265// // will return a RooDataSet named 'simData' that consist of the entries of both
1266// // dataA and dataB. An extra category column 'expIndex' is added that labels
1267// // each entry with state 'A' and 'B' to indicate the originating dataset
1268// return 0 ;
1269// }
1270
1271
1272////////////////////////////////////////////////////////////////////////////////
1273/// Retrieve p.d.f (RooAbsPdf) with given name. A null pointer is returned if not found
1274
1276{
1277 return dynamic_cast<RooAbsPdf*>(_allOwnedNodes.find(name)) ;
1278}
1279
1280
1281////////////////////////////////////////////////////////////////////////////////
1282/// Retrieve function (RooAbsReal) with given name. Note that all RooAbsPdfs are also RooAbsReals. A null pointer is returned if not found.
1283
1285{
1286 return dynamic_cast<RooAbsReal*>(_allOwnedNodes.find(name)) ;
1287}
1288
1289
1290////////////////////////////////////////////////////////////////////////////////
1291/// Retrieve real-valued variable (RooRealVar) with given name. A null pointer is returned if not found
1292
1294{
1295 return dynamic_cast<RooRealVar*>(_allOwnedNodes.find(name)) ;
1296}
1297
1298
1299////////////////////////////////////////////////////////////////////////////////
1300/// Retrieve discrete variable (RooCategory) with given name. A null pointer is returned if not found
1301
1303{
1304 return dynamic_cast<RooCategory*>(_allOwnedNodes.find(name)) ;
1305}
1306
1307
1308////////////////////////////////////////////////////////////////////////////////
1309/// Retrieve discrete function (RooAbsCategory) with given name. A null pointer is returned if not found
1310
1312{
1313 return dynamic_cast<RooAbsCategory*>(_allOwnedNodes.find(name)) ;
1314}
1315
1316
1317
1318////////////////////////////////////////////////////////////////////////////////
1319/// Return RooAbsArg with given name. A null pointer is returned if none is found.
1320
1322{
1323 return _allOwnedNodes.find(name) ;
1324}
1325
1326
1327
1328////////////////////////////////////////////////////////////////////////////////
1329/// Return set of RooAbsArgs matching to given list of names
1330
1331RooArgSet RooWorkspace::argSet(const char* nameList) const
1332{
1333 RooArgSet ret ;
1334
1335 for (const std::string& token : RooHelpers::tokenise(nameList, ",")) {
1336 RooAbsArg* oneArg = arg(token.c_str()) ;
1337 if (oneArg) {
1338 ret.add(*oneArg) ;
1339 } else {
1340 coutE(InputArguments) << " RooWorkspace::argSet(" << GetName() << ") no RooAbsArg named \"" << token << "\" in workspace" << endl ;
1341 }
1342 }
1343 return ret ;
1344}
1345
1346
1347
1348////////////////////////////////////////////////////////////////////////////////
1349/// Return fundamental (i.e. non-derived) RooAbsArg with given name. Fundamental types
1350/// are e.g. RooRealVar, RooCategory. A null pointer is returned if none is found.
1351
1353{
1354 RooAbsArg* tmp = arg(name) ;
1355 if (!tmp) {
1356 return 0 ;
1357 }
1358 return tmp->isFundamental() ? tmp : 0 ;
1359}
1360
1361
1362
1363////////////////////////////////////////////////////////////////////////////////
1364/// Retrieve dataset (binned or unbinned) with given name. A null pointer is returned if not found
1365
1367{
1369}
1370
1371
1372////////////////////////////////////////////////////////////////////////////////
1373/// Retrieve dataset (binned or unbinned) with given name. A null pointer is returned if not found
1374
1376{
1378}
1379
1380
1381
1382
1383////////////////////////////////////////////////////////////////////////////////
1384/// Return set with all variable objects
1385
1387{
1388 RooArgSet ret ;
1389
1390 // Split list of components in pdfs, functions and variables
1392 RooAbsArg* parg ;
1393 while((parg=(RooAbsArg*)iter->Next())) {
1394 if (parg->IsA()->InheritsFrom(RooRealVar::Class())) {
1395 ret.add(*parg) ;
1396 }
1397 }
1398 delete iter ;
1399
1400 return ret ;
1401}
1402
1403
1404////////////////////////////////////////////////////////////////////////////////
1405/// Return set with all category objects
1406
1408{
1409 RooArgSet ret ;
1410
1411 // Split list of components in pdfs, functions and variables
1413 RooAbsArg* parg ;
1414 while((parg=(RooAbsArg*)iter->Next())) {
1415 if (parg->IsA()->InheritsFrom(RooCategory::Class())) {
1416 ret.add(*parg) ;
1417 }
1418 }
1419 delete iter ;
1420
1421 return ret ;
1422}
1423
1424
1425
1426////////////////////////////////////////////////////////////////////////////////
1427/// Return set with all function objects
1428
1430{
1431 RooArgSet ret ;
1432
1433 // Split list of components in pdfs, functions and variables
1435 RooAbsArg* parg ;
1436 while((parg=(RooAbsArg*)iter->Next())) {
1437 if (parg->IsA()->InheritsFrom(RooAbsReal::Class()) &&
1438 !parg->IsA()->InheritsFrom(RooAbsPdf::Class()) &&
1439 !parg->IsA()->InheritsFrom(RooConstVar::Class()) &&
1440 !parg->IsA()->InheritsFrom(RooRealVar::Class())) {
1441 ret.add(*parg) ;
1442 }
1443 }
1444
1445 return ret ;
1446}
1447
1448
1449////////////////////////////////////////////////////////////////////////////////
1450/// Return set with all category function objects
1451
1453{
1454 RooArgSet ret ;
1455
1456 // Split list of components in pdfs, functions and variables
1458 RooAbsArg* parg ;
1459 while((parg=(RooAbsArg*)iter->Next())) {
1460 if (parg->IsA()->InheritsFrom(RooAbsCategory::Class()) &&
1461 !parg->IsA()->InheritsFrom(RooCategory::Class())) {
1462 ret.add(*parg) ;
1463 }
1464 }
1465 return ret ;
1466}
1467
1468
1469
1470////////////////////////////////////////////////////////////////////////////////
1471/// Return set with all resolution model objects
1472
1474{
1475 RooArgSet ret ;
1476
1477 // Split list of components in pdfs, functions and variables
1479 RooAbsArg* parg ;
1480 while((parg=(RooAbsArg*)iter->Next())) {
1481 if (parg->IsA()->InheritsFrom(RooResolutionModel::Class())) {
1482 if (!((RooResolutionModel*)parg)->isConvolved()) {
1483 ret.add(*parg) ;
1484 }
1485 }
1486 }
1487 return ret ;
1488}
1489
1490
1491////////////////////////////////////////////////////////////////////////////////
1492/// Return set with all probability density function objects
1493
1495{
1496 RooArgSet ret ;
1497
1498 // Split list of components in pdfs, functions and variables
1500 RooAbsArg* parg ;
1501 while((parg=(RooAbsArg*)iter->Next())) {
1502 if (parg->IsA()->InheritsFrom(RooAbsPdf::Class()) &&
1503 !parg->IsA()->InheritsFrom(RooResolutionModel::Class())) {
1504 ret.add(*parg) ;
1505 }
1506 }
1507 return ret ;
1508}
1509
1510
1511
1512////////////////////////////////////////////////////////////////////////////////
1513/// Return list of all dataset in the workspace
1514
1515list<RooAbsData*> RooWorkspace::allData() const
1516{
1517 list<RooAbsData*> ret ;
1518 TIterator* iter = _dataList.MakeIterator() ;
1519 RooAbsData* dat ;
1520 while((dat=(RooAbsData*)iter->Next())) {
1521 ret.push_back(dat) ;
1522 }
1523 delete iter ;
1524 return ret ;
1525}
1526
1527
1528////////////////////////////////////////////////////////////////////////////////
1529/// Return list of all dataset in the workspace
1530
1531list<RooAbsData*> RooWorkspace::allEmbeddedData() const
1532{
1533 list<RooAbsData*> ret ;
1535 RooAbsData* dat ;
1536 while((dat=(RooAbsData*)iter->Next())) {
1537 ret.push_back(dat) ;
1538 }
1539 delete iter ;
1540 return ret ;
1541}
1542
1543
1544
1545////////////////////////////////////////////////////////////////////////////////
1546/// Return list of all generic objects in the workspace
1547
1549{
1550 list<TObject*> ret ;
1552 TObject* gobj ;
1553 while((gobj=(RooAbsData*)iter->Next())) {
1554
1555 // If found object is wrapper, return payload
1556 if (gobj->IsA()==RooTObjWrap::Class()) {
1557 ret.push_back(((RooTObjWrap*)gobj)->obj()) ;
1558 } else {
1559 ret.push_back(gobj) ;
1560 }
1561 }
1562 delete iter ;
1563 return ret ;
1564}
1565
1566
1567
1568
1569////////////////////////////////////////////////////////////////////////////////
1570/// Import code of class 'tc' into the repository. If code is already in repository it is only imported
1571/// again if doReplace is false. The names and location of the source files is determined from the information
1572/// in TClass. If no location is found in the TClass information, the files are searched in the workspace
1573/// search path, defined by addClassDeclImportDir() and addClassImplImportDir() for declaration and implementation
1574/// files respectively. If files cannot be found, abort with error status, otherwise update the internal
1575/// class-to-file map and import the contents of the files, if they are not imported yet.
1576
1578{
1579
1580 oocxcoutD(_wspace,ObjectHandling) << "RooWorkspace::CodeRepo(" << _wspace->GetName() << ") request to import code of class " << tc->GetName() << endl ;
1581
1582 // *** PHASE 1 *** Check if file needs to be imported, or is in ROOT distribution, and check if it can be persisted
1583
1584 // Check if we already have the class (i.e. it is in the classToFile map)
1585 if (!doReplace && _c2fmap.find(tc->GetName())!=_c2fmap.end()) {
1586 oocxcoutD(_wspace,ObjectHandling) << "RooWorkspace::CodeRepo(" << _wspace->GetName() << ") code of class " << tc->GetName() << " already imported, skipping" << endl ;
1587 return kTRUE ;
1588 }
1589
1590 // Check if class is listed in a ROOTMAP file - if so we can skip it because it is in the root distribtion
1591 const char* mapEntry = gInterpreter->GetClassSharedLibs(tc->GetName()) ;
1592 if (mapEntry && strlen(mapEntry)>0) {
1593 oocxcoutD(_wspace,ObjectHandling) << "RooWorkspace::CodeRepo(" << _wspace->GetName() << ") code of class " << tc->GetName() << " is in ROOT distribution, skipping " << endl ;
1594 return kTRUE ;
1595 }
1596
1597 // Retrieve file names through ROOT TClass interface
1598 string implfile = tc->GetImplFileName() ;
1599 string declfile = tc->GetDeclFileName() ;
1600
1601 // Check that file names are not empty
1602 if (implfile.empty() || declfile.empty()) {
1603 oocoutE(_wspace,ObjectHandling) << "RooWorkspace::CodeRepo(" << _wspace->GetName() << ") ERROR: cannot retrieve code file names for class "
1604 << tc->GetName() << " through ROOT TClass interface, unable to import code" << endl ;
1605 return kFALSE ;
1606 }
1607
1608 // Check if header filename is found in ROOT distribution, if so, do not import class
1609 TString rootsys = gSystem->Getenv("ROOTSYS") ;
1610 if (TString(implfile.c_str()).Index(rootsys)>=0) {
1611 oocxcoutD(_wspace,ObjectHandling) << "RooWorkspace::CodeRepo(" << _wspace->GetName() << ") code of class " << tc->GetName() << " is in ROOT distribution, skipping " << endl ;
1612 return kTRUE ;
1613 }
1614
1615 // Require that class meets technical criteria to be persistable (i.e it has a default ctor)
1616 // (We also need a default ctor of abstract classes, but cannot check that through is interface
1617 // as TClass::HasDefaultCtor only returns true for callable default ctors)
1618 if (!(tc->Property() & kIsAbstract) && !tc->HasDefaultConstructor()) {
1619 oocoutW(_wspace,ObjectHandling) << "RooWorkspace::autoImportClass(" << _wspace->GetName() << ") WARNING cannot import class "
1620 << tc->GetName() << " : it cannot be persisted because it doesn't have a default constructor. Please fix " << endl ;
1621 return kFALSE ;
1622 }
1623
1624
1625 // *** PHASE 2 *** Check if declaration and implementation files can be located
1626
1627 char *declpath = nullptr, *implpath = nullptr;
1628
1629 // Check if header file can be found in specified location
1630 // If not, scan through list of 'class declaration' paths in RooWorkspace
1631 if (gSystem->AccessPathName(declfile.c_str())) {
1632
1633 // Check list of additional declaration paths
1634 list<string>::iterator diter = RooWorkspace::_classDeclDirList.begin() ;
1635
1636 while(diter!= RooWorkspace::_classDeclDirList.end()) {
1637
1638 declpath = gSystem->ConcatFileName(diter->c_str(),declfile.c_str()) ;
1639 if (!gSystem->AccessPathName(declpath)) {
1640 // found declaration file
1641 break ;
1642 }
1643 // cleanup and continue ;
1644 delete [] declpath;
1645 declpath = nullptr;
1646
1647 ++diter ;
1648 }
1649
1650 // Header file cannot be found anywhere, warn user and abort operation
1651 if (!declpath) {
1652 oocoutW(_wspace,ObjectHandling) << "RooWorkspace::autoImportClass(" << _wspace->GetName() << ") WARNING Cannot access code of class "
1653 << tc->GetName() << " because header file " << declfile << " is not found in current directory nor in $ROOTSYS" ;
1654 if (_classDeclDirList.size()>0) {
1655 ooccoutW(_wspace,ObjectHandling) << ", nor in the search path " ;
1656 diter = RooWorkspace::_classDeclDirList.begin() ;
1657
1658 while(diter!= RooWorkspace::_classDeclDirList.end()) {
1659
1660 if (diter!=RooWorkspace::_classDeclDirList.begin()) {
1662 }
1663 ooccoutW(_wspace,ObjectHandling) << diter->c_str() ;
1664 ++diter ;
1665 }
1666 }
1667 ooccoutW(_wspace,ObjectHandling) << ". To fix this problem, add the required directory to the search "
1668 << "path using RooWorkspace::addClassDeclImportDir(const char* dir)" << endl ;
1669
1670 return kFALSE ;
1671 }
1672 }
1673
1674
1675 // Check if implementation file can be found in specified location
1676 // If not, scan through list of 'class implementation' paths in RooWorkspace
1677 if (gSystem->AccessPathName(implfile.c_str())) {
1678
1679 // Check list of additional declaration paths
1680 list<string>::iterator iiter = RooWorkspace::_classImplDirList.begin() ;
1681
1682 while(iiter!= RooWorkspace::_classImplDirList.end()) {
1683
1684 implpath = gSystem->ConcatFileName(iiter->c_str(),implfile.c_str()) ;
1685 if (!gSystem->AccessPathName(implpath)) {
1686 // found implementation file
1687 break ;
1688 }
1689 // cleanup and continue ;
1690 delete [] implpath;
1691 implpath = nullptr;
1692
1693 ++iiter ;
1694 }
1695
1696 // Implementation file cannot be found anywhere, warn user and abort operation
1697 if (!implpath) {
1698 oocoutW(_wspace,ObjectHandling) << "RooWorkspace::autoImportClass(" << _wspace->GetName() << ") WARNING Cannot access code of class "
1699 << tc->GetName() << " because implementation file " << implfile << " is not found in current directory nor in $ROOTSYS" ;
1700 if (_classDeclDirList.size()>0) {
1701 ooccoutW(_wspace,ObjectHandling) << ", nor in the search path " ;
1702 iiter = RooWorkspace::_classImplDirList.begin() ;
1703
1704 while(iiter!= RooWorkspace::_classImplDirList.end()) {
1705
1706 if (iiter!=RooWorkspace::_classImplDirList.begin()) {
1708 }
1709 ooccoutW(_wspace,ObjectHandling) << iiter->c_str() ;
1710 ++iiter ;
1711 }
1712 }
1713 ooccoutW(_wspace,ObjectHandling) << ". To fix this problem add the required directory to the search "
1714 << "path using RooWorkspace::addClassImplImportDir(const char* dir)" << endl;
1715 delete [] declpath;
1716 return kFALSE;
1717 }
1718 }
1719
1720 char buf[64000];
1721
1722 // *** Phase 3 *** Prepare to import code from files into STL string buffer
1723 //
1724 // Code storage is organized in two linked maps
1725 //
1726 // _fmap contains stl strings with code, indexed on declaration file name
1727 //
1728 // _c2fmap contains list of declaration file names and list of base classes
1729 // and is indexed on class name
1730 //
1731 // Phase 3 is skipped if fmap already contains an entry with given filebasename
1732
1733 string declfilename = declpath?gSystem->BaseName(declpath):gSystem->BaseName(declfile.c_str()) ;
1734
1735 // Split in base and extension
1736 int dotpos2 = strrchr(declfilename.c_str(),'.') - declfilename.c_str() ;
1737 string declfilebase = declfilename.substr(0,dotpos2) ;
1738 string declfileext = declfilename.substr(dotpos2+1) ;
1739
1740 list<string> extraHeaders ;
1741
1742 // If file has not beed stored yet, enter stl strings with implementation and declaration in file map
1743 if (_fmap.find(declfilebase) == _fmap.end()) {
1744
1745 // Open declaration file
1746 fstream fdecl(declpath?declpath:declfile.c_str()) ;
1747
1748 // Abort import if declaration file cannot be opened
1749 if (!fdecl) {
1750 oocoutE(_wspace,ObjectHandling) << "RooWorkspace::autoImportClass(" << _wspace->GetName()
1751 << ") ERROR opening declaration file " << declfile << endl ;
1752 delete[] implpath;
1753 delete[] declpath;
1754 return kFALSE ;
1755 }
1756
1757 oocoutI(_wspace,ObjectHandling) << "RooWorkspace::autoImportClass(" << _wspace->GetName()
1758 << ") importing code of class " << tc->GetName()
1759 << " from " << (implpath?implpath:implfile.c_str())
1760 << " and " << (declpath?declpath:declfile.c_str()) << endl ;
1761
1762
1763 // Read entire file into an stl string
1764 string decl ;
1765 while(fdecl.getline(buf,1023)) {
1766
1767 // Look for include state of self
1768 Bool_t processedInclude = kFALSE ;
1769 char* extincfile = 0 ;
1770
1771 // Look for include of declaration file corresponding to this implementation file
1772 if (strstr(buf,"#include")) {
1773 // Process #include statements here
1774 char tmp[64000];
1775 strlcpy(tmp, buf, 64000);
1776 Bool_t stdinclude = strchr(buf, '<');
1777 strtok(tmp, " <\"");
1778 char *incfile = strtok(0, " <>\"");
1779
1780 if (!stdinclude) {
1781 // check if it lives in $ROOTSYS/include
1782 TString hpath = gSystem->Getenv("ROOTSYS");
1783 hpath += "/include/";
1784 hpath += incfile;
1785 if (gSystem->AccessPathName(hpath.Data())) {
1786 oocoutI(_wspace, ObjectHandling) << "RooWorkspace::autoImportClass(" << _wspace->GetName()
1787 << ") scheduling include file " << incfile << " for import" << endl;
1788 extraHeaders.push_back(incfile);
1789 extincfile = incfile;
1790 processedInclude = kTRUE;
1791 }
1792 }
1793 }
1794
1795 if (processedInclude) {
1796 decl += "// external include file below retrieved from workspace code storage\n" ;
1797 decl += Form("#include \"%s\"\n",extincfile) ;
1798 } else {
1799 decl += buf ;
1800 decl += '\n' ;
1801 }
1802 }
1803
1804 // Open implementation file
1805 fstream fimpl(implpath?implpath:implfile.c_str()) ;
1806
1807 // Abort import if implementation file cannot be opened
1808 if (!fimpl) {
1809 oocoutE(_wspace,ObjectHandling) << "RooWorkspace::autoImportClass(" << _wspace->GetName()
1810 << ") ERROR opening implementation file " << implfile << endl ;
1811 delete[] implpath;
1812 delete[] declpath;
1813 return kFALSE ;
1814 }
1815
1816
1817 // Import entire implentation file into stl string
1818 string impl ;
1819 while(fimpl.getline(buf,1023)) {
1820 // Process #include statements here
1821
1822 // Look for include state of self
1823 Bool_t foundSelfInclude=kFALSE ;
1824 Bool_t processedInclude = kFALSE ;
1825 char* extincfile = 0 ;
1826
1827 // Look for include of declaration file corresponding to this implementation file
1828 if (strstr(buf,"#include")) {
1829 // Process #include statements here
1830 char tmp[64000];
1831 strlcpy(tmp, buf, 64000);
1832 Bool_t stdinclude = strchr(buf, '<');
1833 strtok(tmp, " <\"");
1834 char *incfile = strtok(0, " <>\"");
1835
1836 if (strstr(incfile, declfilename.c_str())) {
1837 foundSelfInclude = kTRUE;
1838 }
1839
1840 if (!stdinclude && !foundSelfInclude) {
1841 // check if it lives in $ROOTSYS/include
1842 TString hpath = gSystem->Getenv("ROOTSYS");
1843 hpath += "/include/";
1844 hpath += incfile;
1845
1846 if (gSystem->AccessPathName(hpath.Data())) {
1847 oocoutI(_wspace, ObjectHandling) << "RooWorkspace::autoImportClass(" << _wspace->GetName()
1848 << ") scheduling include file " << incfile << " for import" << endl;
1849 extraHeaders.push_back(incfile);
1850 extincfile = incfile;
1851 processedInclude = kTRUE;
1852 }
1853 }
1854 }
1855
1856 // Explicitly rewrite include of own declaration file to string
1857 // any directory prefixes, copy all other lines verbatim in stl string
1858 if (foundSelfInclude) {
1859 // If include of self is found, substitute original include
1860 // which may have directory structure with a plain include
1861 impl += "// class declaration include file below retrieved from workspace code storage\n" ;
1862 impl += Form("#include \"%s.%s\"\n",declfilebase.c_str(),declfileext.c_str()) ;
1863 } else if (processedInclude) {
1864 impl += "// external include file below retrieved from workspace code storage\n" ;
1865 impl += Form("#include \"%s\"\n",extincfile) ;
1866 } else {
1867 impl += buf ;
1868 impl += '\n' ;
1869 }
1870 }
1871
1872 // Create entry in file map
1873 _fmap[declfilebase]._hfile = decl ;
1874 _fmap[declfilebase]._cxxfile = impl ;
1875 _fmap[declfilebase]._hext = declfileext ;
1876
1877 // Process extra includes now
1878 for (list<string>::iterator ehiter = extraHeaders.begin() ; ehiter != extraHeaders.end() ; ++ehiter ) {
1879 if (_ehmap.find(*ehiter) == _ehmap.end()) {
1880
1881 ExtraHeader eh ;
1882 eh._hname = ehiter->c_str() ;
1883 fstream fehdr(ehiter->c_str()) ;
1884 string ehimpl ;
1885 char buf2[1024] ;
1886 while(fehdr.getline(buf2,1023)) {
1887
1888 // Look for include of declaration file corresponding to this implementation file
1889 if (strstr(buf2,"#include")) {
1890 // Process #include statements here
1891 char tmp[64000];
1892 strlcpy(tmp, buf2, 64000);
1893 Bool_t stdinclude = strchr(buf, '<');
1894 strtok(tmp, " <\"");
1895 char *incfile = strtok(0, " <>\"");
1896
1897 if (!stdinclude) {
1898 // check if it lives in $ROOTSYS/include
1899 TString hpath = gSystem->Getenv("ROOTSYS");
1900 hpath += "/include/";
1901 hpath += incfile;
1902 if (gSystem->AccessPathName(hpath.Data())) {
1903 oocoutI(_wspace, ObjectHandling) << "RooWorkspace::autoImportClass(" << _wspace->GetName()
1904 << ") scheduling recursive include file " << incfile << " for import"
1905 << endl;
1906 extraHeaders.push_back(incfile);
1907 }
1908 }
1909 }
1910
1911 ehimpl += buf2;
1912 ehimpl += '\n';
1913 }
1914 eh._hfile = ehimpl.c_str();
1915
1916 _ehmap[ehiter->c_str()] = eh;
1917 }
1918 }
1919
1920 } else {
1921
1922 // Inform that existing file entry is being recycled because it already contained class code
1923 oocoutI(_wspace,ObjectHandling) << "RooWorkspace::autoImportClass(" << _wspace->GetName()
1924 << ") code of class " << tc->GetName()
1925 << " was already imported from " << (implpath?implpath:implfile.c_str())
1926 << " and " << (declpath?declpath:declfile.c_str()) << endl ;
1927
1928 }
1929
1930
1931 // *** PHASE 4 *** Import stl strings with code into workspace
1932 //
1933 // If multiple classes are declared in a single code unit, there will be
1934 // multiple _c2fmap entries all pointing to the same _fmap entry.
1935
1936 // Make list of all immediate base classes of this class
1937 TString baseNameList ;
1938 TList* bl = tc->GetListOfBases() ;
1939 TIterator* iter = bl->MakeIterator() ;
1940 TBaseClass* base ;
1941 list<TClass*> bases ;
1942 while((base=(TBaseClass*)iter->Next())) {
1943 if (baseNameList.Length()>0) {
1944 baseNameList += "," ;
1945 }
1946 baseNameList += base->GetClassPointer()->GetName() ;
1947 bases.push_back(base->GetClassPointer()) ;
1948 }
1949
1950 // Map class name to above _fmap entries, along with list of base classes
1951 // in _c2fmap
1952 _c2fmap[tc->GetName()]._baseName = baseNameList ;
1953 _c2fmap[tc->GetName()]._fileBase = declfilebase ;
1954
1955 // Recursive store all base classes.
1956 list<TClass*>::iterator biter = bases.begin() ;
1957 while(biter!=bases.end()) {
1958 autoImportClass(*biter,doReplace) ;
1959 ++biter ;
1960 }
1961
1962 // Cleanup
1963 delete[] implpath;
1964 delete[] declpath;
1965
1966 return kTRUE ;
1967}
1968
1969
1970////////////////////////////////////////////////////////////////////////////////
1971/// Create transient TDirectory representation of this workspace. This directory
1972/// will appear as a subdirectory of the directory that contains the workspace
1973/// and will have the name of the workspace suffixed with "Dir". The TDirectory
1974/// interface is read-only. Any attempt to insert objects into the workspace
1975/// directory representation will result in an error message. Note that some
1976/// ROOT object like TH1 automatically insert themselves into the current directory
1977/// when constructed. This will give error messages when done in a workspace
1978/// directory.
1979
1981{
1982 if (_dir) return kTRUE ;
1983
1984 TString title= Form("TDirectory representation of RooWorkspace %s",GetName()) ;
1985 _dir = new WSDir(GetName(),title.Data(),this) ;
1986
1987 TIterator* iter = componentIterator() ;
1988 RooAbsArg* darg ;
1989 while((darg=(RooAbsArg*)iter->Next())) {
1990 if (darg->IsA() != RooConstVar::Class()) {
1991 _dir->InternalAppend(darg) ;
1992 }
1993 }
1994
1995 return kTRUE ;
1996}
1997
1998
1999
2000////////////////////////////////////////////////////////////////////////////////
2001/// Import a clone of a generic TObject into workspace generic object container. Imported
2002/// object can be retrieved by name through the obj() method. The object is cloned upon
2003/// importation and the input argument does not need to live beyond the import call
2004///
2005/// Returns kTRUE if an error has occurred.
2006
2008{
2009 // First check if object with given name already exists
2010 TObject* oldObj = _genObjects.FindObject(object.GetName()) ;
2011 if (oldObj && !replaceExisting) {
2012 coutE(InputArguments) << "RooWorkspace::import(" << GetName() << ") generic object with name "
2013 << object.GetName() << " is already in workspace and replaceExisting flag is set to false" << endl ;
2014 return kTRUE ;
2015 }
2016
2017 // Grab the current state of the directory Auto-Add
2018 ROOT::DirAutoAdd_t func = object.IsA()->GetDirectoryAutoAdd();
2019 object.IsA()->SetDirectoryAutoAdd(0);
2021
2022 if (oldObj) {
2023 _genObjects.Replace(oldObj,object.Clone()) ;
2024 delete oldObj ;
2025 } else {
2026 _genObjects.Add(object.Clone()) ;
2027 }
2028
2029 // Reset the state of the directory Auto-Add
2030 object.IsA()->SetDirectoryAutoAdd(func);
2032
2033 return kFALSE ;
2034}
2035
2036
2037
2038
2039////////////////////////////////////////////////////////////////////////////////
2040/// Import a clone of a generic TObject into workspace generic object container.
2041/// The imported object will be stored under the given alias name rather than its
2042/// own name. Imported object can be retrieved its alias name through the obj() method.
2043/// The object is cloned upon importation and the input argument does not need to live beyond the import call
2044/// This method is mostly useful for importing objects that do not have a settable name such as TMatrix
2045///
2046/// Returns kTRUE if an error has occurred.
2047
2048Bool_t RooWorkspace::import(TObject& object, const char* aliasName, Bool_t replaceExisting)
2049{
2050 // First check if object with given name already exists
2051 TObject* oldObj = _genObjects.FindObject(object.GetName()) ;
2052 if (oldObj && !replaceExisting) {
2053 coutE(InputArguments) << "RooWorkspace::import(" << GetName() << ") generic object with name "
2054 << object.GetName() << " is already in workspace and replaceExisting flag is set to false" << endl ;
2055 return kTRUE ;
2056 }
2057
2059 RooTObjWrap* wrapper = new RooTObjWrap(object.Clone()) ;
2061 wrapper->setOwning(kTRUE) ;
2062 wrapper->SetName(aliasName) ;
2063 wrapper->SetTitle(aliasName) ;
2064
2065 if (oldObj) {
2066 _genObjects.Replace(oldObj,wrapper) ;
2067 delete oldObj ;
2068 } else {
2069 _genObjects.Add(wrapper) ;
2070 }
2071 return kFALSE ;
2072}
2073
2074
2075
2076
2077////////////////////////////////////////////////////////////////////////////////
2078/// Insert RooStudyManager module
2079
2081{
2082 RooAbsStudy* clone = (RooAbsStudy*) study.Clone() ;
2083 _studyMods.Add(clone) ;
2084 return kFALSE ;
2085}
2086
2087
2088
2089
2090////////////////////////////////////////////////////////////////////////////////
2091/// Remove all RooStudyManager modules
2092
2094{
2095 _studyMods.Delete() ;
2096}
2097
2098
2099
2100
2101////////////////////////////////////////////////////////////////////////////////
2102/// Return any type of object (RooAbsArg, RooAbsData or generic object) with given name)
2103
2104TObject* RooWorkspace::obj(const char* name) const
2105{
2106 // Try RooAbsArg first
2107 TObject* ret = arg(name) ;
2108 if (ret) return ret ;
2109
2110 // Then try RooAbsData
2111 ret = data(name) ;
2112 if (ret) return ret ;
2113
2114 // Finally try generic object store
2115 return genobj(name) ;
2116}
2117
2118
2119
2120////////////////////////////////////////////////////////////////////////////////
2121/// Return generic object with given name
2122
2124{
2125 // Find object by name
2127
2128 // Exit here if not found
2129 if (!gobj) return 0 ;
2130
2131 // If found object is wrapper, return payload
2132 if (gobj->IsA()==RooTObjWrap::Class()) return ((RooTObjWrap*)gobj)->obj() ;
2133
2134 return gobj ;
2135}
2136
2137
2138
2139////////////////////////////////////////////////////////////////////////////////
2140
2141Bool_t RooWorkspace::cd(const char* path)
2142{
2143 makeDir() ;
2144 return _dir->cd(path) ;
2145}
2146
2147
2148
2149////////////////////////////////////////////////////////////////////////////////
2150/// Save this current workspace into given file
2151
2152Bool_t RooWorkspace::writeToFile(const char* fileName, Bool_t recreate)
2153{
2154 TFile f(fileName,recreate?"RECREATE":"UPDATE") ;
2155 Write() ;
2156 return kFALSE ;
2157}
2158
2159
2160
2161////////////////////////////////////////////////////////////////////////////////
2162/// Return instance to factory tool
2163
2165{
2166 if (_factory) {
2167 return *_factory;
2168 }
2169 cxcoutD(ObjectHandling) << "INFO: Creating RooFactoryWSTool associated with this workspace" << endl ;
2170 _factory = make_unique<RooFactoryWSTool>(*this);
2171 return *_factory;
2172}
2173
2174
2175
2176
2177////////////////////////////////////////////////////////////////////////////////
2178/// Short-hand function for `factory()->process(expr);`
2179///
2180/// \copydoc RooFactoryWSTool::process(const char*)
2182{
2183 return factory().process(expr) ;
2184}
2185
2186
2187
2188
2189////////////////////////////////////////////////////////////////////////////////
2190/// Print contents of the workspace
2191
2193{
2194 Bool_t treeMode(kFALSE) ;
2196 if (TString(opts).Contains("t")) {
2197 treeMode=kTRUE ;
2198 }
2199 if (TString(opts).Contains("v")) {
2200 verbose = kTRUE;
2201 }
2202
2203 cout << endl << "RooWorkspace(" << GetName() << ") " << GetTitle() << " contents" << endl << endl ;
2204
2205 RooAbsArg* parg ;
2206
2207 RooArgSet pdfSet ;
2208 RooArgSet funcSet ;
2209 RooArgSet varSet ;
2210 RooArgSet catfuncSet ;
2211 RooArgSet convResoSet ;
2212 RooArgSet resoSet ;
2213
2214
2215 // Split list of components in pdfs, functions and variables
2217 while((parg=(RooAbsArg*)iter->Next())) {
2218
2219 //---------------
2220
2221 if (treeMode) {
2222
2223 // In tree mode, only add nodes with no clients to the print lists
2224
2225 if (parg->IsA()->InheritsFrom(RooAbsPdf::Class())) {
2226 if (!parg->hasClients()) {
2227 pdfSet.add(*parg) ;
2228 }
2229 }
2230
2231 if (parg->IsA()->InheritsFrom(RooAbsReal::Class()) &&
2232 !parg->IsA()->InheritsFrom(RooAbsPdf::Class()) &&
2233 !parg->IsA()->InheritsFrom(RooConstVar::Class()) &&
2234 !parg->IsA()->InheritsFrom(RooRealVar::Class())) {
2235 if (!parg->hasClients()) {
2236 funcSet.add(*parg) ;
2237 }
2238 }
2239
2240
2241 if (parg->IsA()->InheritsFrom(RooAbsCategory::Class()) &&
2242 !parg->IsA()->InheritsFrom(RooCategory::Class())) {
2243 if (!parg->hasClients()) {
2244 catfuncSet.add(*parg) ;
2245 }
2246 }
2247
2248 } else {
2249
2250 if (parg->IsA()->InheritsFrom(RooResolutionModel::Class())) {
2251 if (((RooResolutionModel*)parg)->isConvolved()) {
2252 convResoSet.add(*parg) ;
2253 } else {
2254 resoSet.add(*parg) ;
2255 }
2256 }
2257
2258 if (parg->IsA()->InheritsFrom(RooAbsPdf::Class()) &&
2259 !parg->IsA()->InheritsFrom(RooResolutionModel::Class())) {
2260 pdfSet.add(*parg) ;
2261 }
2262
2263 if (parg->IsA()->InheritsFrom(RooAbsReal::Class()) &&
2264 !parg->IsA()->InheritsFrom(RooAbsPdf::Class()) &&
2265 !parg->IsA()->InheritsFrom(RooConstVar::Class()) &&
2266 !parg->IsA()->InheritsFrom(RooRealVar::Class())) {
2267 funcSet.add(*parg) ;
2268 }
2269
2270 if (parg->IsA()->InheritsFrom(RooAbsCategory::Class()) &&
2271 !parg->IsA()->InheritsFrom(RooCategory::Class())) {
2272 catfuncSet.add(*parg) ;
2273 }
2274 }
2275
2276 if (parg->IsA()->InheritsFrom(RooRealVar::Class())) {
2277 varSet.add(*parg) ;
2278 }
2279
2280 if (parg->IsA()->InheritsFrom(RooCategory::Class())) {
2281 varSet.add(*parg) ;
2282 }
2283
2284 }
2285 delete iter ;
2286
2287
2290
2291 if (varSet.getSize()>0) {
2292 varSet.sort() ;
2293 cout << "variables" << endl ;
2294 cout << "---------" << endl ;
2295 cout << varSet << endl ;
2296 cout << endl ;
2297 }
2298
2299 if (pdfSet.getSize()>0) {
2300 cout << "p.d.f.s" << endl ;
2301 cout << "-------" << endl ;
2302 pdfSet.sort() ;
2303 iter = pdfSet.createIterator() ;
2304 while((parg=(RooAbsArg*)iter->Next())) {
2305 if (treeMode) {
2306 parg->printComponentTree() ;
2307 } else {
2308 parg->Print() ;
2309 }
2310 }
2311 delete iter ;
2312 cout << endl ;
2313 }
2314
2315 if (!treeMode) {
2316 if (resoSet.getSize()>0) {
2317 cout << "analytical resolution models" << endl ;
2318 cout << "----------------------------" << endl ;
2319 resoSet.sort() ;
2320 iter = resoSet.createIterator() ;
2321 while((parg=(RooAbsArg*)iter->Next())) {
2322 parg->Print() ;
2323 }
2324 delete iter ;
2325 // iter = convResoSet.createIterator() ;
2326 // while((parg=(RooAbsArg*)iter->Next())) {
2327 // parg->Print() ;
2328 // }
2329 // delete iter ;
2330 cout << endl ;
2331 }
2332 }
2333
2334 if (funcSet.getSize()>0) {
2335 cout << "functions" << endl ;
2336 cout << "--------" << endl ;
2337 funcSet.sort() ;
2338 iter = funcSet.createIterator() ;
2339 while((parg=(RooAbsArg*)iter->Next())) {
2340 if (treeMode) {
2341 parg->printComponentTree() ;
2342 } else {
2343 parg->Print() ;
2344 }
2345 }
2346 delete iter ;
2347 cout << endl ;
2348 }
2349
2350 if (catfuncSet.getSize()>0) {
2351 cout << "category functions" << endl ;
2352 cout << "------------------" << endl ;
2353 catfuncSet.sort() ;
2354 iter = catfuncSet.createIterator() ;
2355 while((parg=(RooAbsArg*)iter->Next())) {
2356 if (treeMode) {
2357 parg->printComponentTree() ;
2358 } else {
2359 parg->Print() ;
2360 }
2361 }
2362 delete iter ;
2363 cout << endl ;
2364 }
2365
2366 if (_dataList.GetSize()>0) {
2367 cout << "datasets" << endl ;
2368 cout << "--------" << endl ;
2369 iter = _dataList.MakeIterator() ;
2370 RooAbsData* data2 ;
2371 while((data2=(RooAbsData*)iter->Next())) {
2372 cout << data2->IsA()->GetName() << "::" << data2->GetName() << *data2->get() << endl ;
2373 }
2374 delete iter ;
2375 cout << endl ;
2376 }
2377
2378 if (_embeddedDataList.GetSize()>0) {
2379 cout << "embedded datasets (in pdfs and functions)" << endl ;
2380 cout << "-----------------------------------------" << endl ;
2382 RooAbsData* data2 ;
2383 while((data2=(RooAbsData*)iter->Next())) {
2384 cout << data2->IsA()->GetName() << "::" << data2->GetName() << *data2->get() << endl ;
2385 }
2386 delete iter ;
2387 cout << endl ;
2388 }
2389
2390 if (_snapshots.GetSize()>0) {
2391 cout << "parameter snapshots" << endl ;
2392 cout << "-------------------" << endl ;
2393 iter = _snapshots.MakeIterator() ;
2394 RooArgSet* snap ;
2395 while((snap=(RooArgSet*)iter->Next())) {
2396 cout << snap->GetName() << " = (" ;
2397 TIterator* aiter = snap->createIterator() ;
2398 RooAbsArg* a ;
2399 Bool_t first(kTRUE) ;
2400 while((a=(RooAbsArg*)aiter->Next())) {
2401 if (first) { first=kFALSE ; } else { cout << "," ; }
2402 cout << a->GetName() << "=" ;
2403 a->printValue(cout) ;
2404 if (a->isConstant()) {
2405 cout << "[C]" ;
2406 }
2407 }
2408 cout << ")" << endl ;
2409 delete aiter ;
2410 }
2411 delete iter ;
2412 cout << endl ;
2413 }
2414
2415
2416 if (_namedSets.size()>0) {
2417 cout << "named sets" << endl ;
2418 cout << "----------" << endl ;
2419 for (map<string,RooArgSet>::const_iterator it = _namedSets.begin() ; it != _namedSets.end() ; ++it) {
2420 if (verbose || !TString(it->first.c_str()).BeginsWith("CACHE_")) {
2421 cout << it->first << ":" << it->second << endl;
2422 }
2423 }
2424
2425 cout << endl ;
2426 }
2427
2428
2429 if (_genObjects.GetSize()>0) {
2430 cout << "generic objects" << endl ;
2431 cout << "---------------" << endl ;
2432 iter = _genObjects.MakeIterator() ;
2433 TObject* gobj ;
2434 while((gobj=(TObject*)iter->Next())) {
2435 if (gobj->IsA()==RooTObjWrap::Class()) {
2436 cout << ((RooTObjWrap*)gobj)->obj()->IsA()->GetName() << "::" << gobj->GetName() << endl ;
2437 } else {
2438 cout << gobj->IsA()->GetName() << "::" << gobj->GetName() << endl ;
2439 }
2440 }
2441 delete iter ;
2442 cout << endl ;
2443
2444 }
2445
2446 if (_studyMods.GetSize()>0) {
2447 cout << "study modules" << endl ;
2448 cout << "-------------" << endl ;
2449 iter = _studyMods.MakeIterator() ;
2450 TObject* smobj ;
2451 while((smobj=(TObject*)iter->Next())) {
2452 cout << smobj->IsA()->GetName() << "::" << smobj->GetName() << endl ;
2453 }
2454 delete iter ;
2455 cout << endl ;
2456
2457 }
2458
2459 if (_classes.listOfClassNames().size()>0) {
2460 cout << "embedded class code" << endl ;
2461 cout << "-------------------" << endl ;
2462 cout << _classes.listOfClassNames() << endl ;
2463 cout << endl ;
2464 }
2465
2466 if (_eocache.size()>0) {
2467 cout << "embedded precalculated expensive components" << endl ;
2468 cout << "-------------------------------------------" << endl ;
2469 _eocache.print() ;
2470 }
2471
2473
2474 return ;
2475}
2476
2477
2478////////////////////////////////////////////////////////////////////////////////
2479/// Custom streamer for the workspace. Stream contents of workspace
2480/// and code repository. When reading, read code repository first
2481/// and compile missing classes before proceeding with streaming
2482/// of workspace contents to avoid errors.
2483
2484void RooWorkspace::CodeRepo::Streamer(TBuffer &R__b)
2485{
2486 typedef ::RooWorkspace::CodeRepo thisClass;
2487
2488 // Stream an object of class RooWorkspace::CodeRepo.
2489 if (R__b.IsReading()) {
2490
2491 UInt_t R__s, R__c;
2492 Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
2493
2494 // Stream contents of ClassFiles map
2495 Int_t count(0) ;
2496 R__b >> count ;
2497 while(count--) {
2498 TString name ;
2499 name.Streamer(R__b) ;
2500 _fmap[name]._hext.Streamer(R__b) ;
2501 _fmap[name]._hfile.Streamer(R__b) ;
2502 _fmap[name]._cxxfile.Streamer(R__b) ;
2503 }
2504
2505 // Stream contents of ClassRelInfo map
2506 count=0 ;
2507 R__b >> count ;
2508 while(count--) {
2509 TString name ;
2510 name.Streamer(R__b) ;
2511 _c2fmap[name]._baseName.Streamer(R__b) ;
2512 _c2fmap[name]._fileBase.Streamer(R__b) ;
2513 }
2514
2515 if (R__v==2) {
2516
2517 count=0 ;
2518 R__b >> count ;
2519 while(count--) {
2520 TString name ;
2521 name.Streamer(R__b) ;
2522 _ehmap[name]._hname.Streamer(R__b) ;
2523 _ehmap[name]._hfile.Streamer(R__b) ;
2524 }
2525 }
2526
2527 R__b.CheckByteCount(R__s, R__c, thisClass::IsA());
2528
2529 // Instantiate any classes that are not defined in current session
2530 _compiledOK = !compileClasses() ;
2531
2532 } else {
2533
2534 UInt_t R__c;
2535 R__c = R__b.WriteVersion(thisClass::IsA(), kTRUE);
2536
2537 // Stream contents of ClassFiles map
2538 UInt_t count = _fmap.size() ;
2539 R__b << count ;
2540 map<TString,ClassFiles>::iterator iter = _fmap.begin() ;
2541 while(iter!=_fmap.end()) {
2542 TString key_copy(iter->first) ;
2543 key_copy.Streamer(R__b) ;
2544 iter->second._hext.Streamer(R__b) ;
2545 iter->second._hfile.Streamer(R__b);
2546 iter->second._cxxfile.Streamer(R__b);
2547
2548 ++iter ;
2549 }
2550
2551 // Stream contents of ClassRelInfo map
2552 count = _c2fmap.size() ;
2553 R__b << count ;
2554 map<TString,ClassRelInfo>::iterator iter2 = _c2fmap.begin() ;
2555 while(iter2!=_c2fmap.end()) {
2556 TString key_copy(iter2->first) ;
2557 key_copy.Streamer(R__b) ;
2558 iter2->second._baseName.Streamer(R__b) ;
2559 iter2->second._fileBase.Streamer(R__b);
2560 ++iter2 ;
2561 }
2562
2563 // Stream contents of ExtraHeader map
2564 count = _ehmap.size() ;
2565 R__b << count ;
2566 map<TString,ExtraHeader>::iterator iter3 = _ehmap.begin() ;
2567 while(iter3!=_ehmap.end()) {
2568 TString key_copy(iter3->first) ;
2569 key_copy.Streamer(R__b) ;
2570 iter3->second._hname.Streamer(R__b) ;
2571 iter3->second._hfile.Streamer(R__b);
2572 ++iter3 ;
2573 }
2574
2575 R__b.SetByteCount(R__c, kTRUE);
2576
2577 }
2578}
2579
2580
2581////////////////////////////////////////////////////////////////////////////////
2582/// Stream an object of class RooWorkspace. This is a standard ROOT streamer for the
2583/// I/O part. This custom function exists to detach all external client links
2584/// from the payload prior to writing the payload so that these client links
2585/// are not persisted. (Client links occur if external function objects use
2586/// objects contained in the workspace as input)
2587/// After the actual writing, these client links are restored.
2588
2589void RooWorkspace::Streamer(TBuffer &R__b)
2590{
2591 if (R__b.IsReading()) {
2592
2594
2595 // Perform any pass-2 schema evolution here
2597 RooAbsArg* node ;
2598 while((node=fiter.next())) {
2599 node->ioStreamerPass2() ;
2600 }
2602
2603 // Make expensive object cache of all objects point to intermal copy.
2604 // Somehow this doesn't work OK automatically
2606 while((node=(RooAbsArg*)iter->Next())) {
2608 node->setWorkspace(*this);
2609 if (node->IsA()->InheritsFrom(RooAbsOptTestStatistic::Class())) {
2611 if (tmp->isSealed() && tmp->sealNotice() && strlen(tmp->sealNotice()) > 0) {
2612 cout << "RooWorkspace::Streamer(" << GetName() << ") " << node->IsA()->GetName() << "::" << node->GetName()
2613 << " : " << tmp->sealNotice() << endl;
2614 }
2615 }
2616 }
2617 delete iter ;
2618
2619
2620 } else {
2621
2622 // Make lists of external clients of WS objects, and remove those links temporarily
2623
2624 map<RooAbsArg*,vector<RooAbsArg *> > extClients, extValueClients, extShapeClients ;
2625
2627 RooAbsArg* tmparg ;
2628 while((tmparg=(RooAbsArg*)iter->Next())) {
2629
2630 // Loop over client list of this arg
2631 std::vector<RooAbsArg *> clientsTmp{tmparg->_clientList.begin(), tmparg->_clientList.end()};
2632 for (auto client : clientsTmp) {
2633 if (!_allOwnedNodes.containsInstance(*client)) {
2634
2635 const auto refCount = tmparg->_clientList.refCount(client);
2636 auto& bufferVec = extClients[tmparg];
2637
2638 bufferVec.insert(bufferVec.end(), refCount, client);
2639 tmparg->_clientList.Remove(client, true);
2640 }
2641 }
2642
2643 // Loop over value client list of this arg
2644 clientsTmp.assign(tmparg->_clientListValue.begin(), tmparg->_clientListValue.end());
2645 for (auto vclient : clientsTmp) {
2646 if (!_allOwnedNodes.containsInstance(*vclient)) {
2647 cxcoutD(ObjectHandling) << "RooWorkspace::Streamer(" << GetName() << ") element " << tmparg->GetName()
2648 << " has external value client link to " << vclient << " (" << vclient->GetName() << ") with ref count " << tmparg->_clientListValue.refCount(vclient) << endl ;
2649
2650 const auto refCount = tmparg->_clientListValue.refCount(vclient);
2651 auto& bufferVec = extValueClients[tmparg];
2652
2653 bufferVec.insert(bufferVec.end(), refCount, vclient);
2654 tmparg->_clientListValue.Remove(vclient, true);
2655 }
2656 }
2657
2658 // Loop over shape client list of this arg
2659 clientsTmp.assign(tmparg->_clientListShape.begin(), tmparg->_clientListShape.end());
2660 for (auto sclient : clientsTmp) {
2661 if (!_allOwnedNodes.containsInstance(*sclient)) {
2662 cxcoutD(ObjectHandling) << "RooWorkspace::Streamer(" << GetName() << ") element " << tmparg->GetName()
2663 << " has external shape client link to " << sclient << " (" << sclient->GetName() << ") with ref count " << tmparg->_clientListShape.refCount(sclient) << endl ;
2664
2665 const auto refCount = tmparg->_clientListShape.refCount(sclient);
2666 auto& bufferVec = extShapeClients[tmparg];
2667
2668 bufferVec.insert(bufferVec.end(), refCount, sclient);
2669 tmparg->_clientListShape.Remove(sclient, true);
2670 }
2671 }
2672
2673 }
2674 delete iter ;
2675
2677
2678 // Reinstate clients here
2679
2680
2681 for (auto iterx : extClients) {
2682 for (auto client : iterx.second) {
2683 iterx.first->_clientList.Add(client);
2684 }
2685 }
2686
2687 for (auto iterx : extValueClients) {
2688 for (auto client : iterx.second) {
2689 iterx.first->_clientListValue.Add(client);
2690 }
2691 }
2692
2693 for (auto iterx : extShapeClients) {
2694 for (auto client : iterx.second) {
2695 iterx.first->_clientListShape.Add(client);
2696 }
2697 }
2698
2699 }
2700}
2701
2702
2703
2704
2705////////////////////////////////////////////////////////////////////////////////
2706/// Return STL string with last of class names contained in the code repository
2707
2709{
2710 string ret ;
2711 map<TString,ClassRelInfo>::const_iterator iter = _c2fmap.begin() ;
2712 while(iter!=_c2fmap.end()) {
2713 if (ret.size()>0) {
2714 ret += ", " ;
2715 }
2716 ret += iter->first ;
2717 ++iter ;
2718 }
2719
2720 return ret ;
2721}
2722
2723namespace {
2724UInt_t crc32(const char* data, ULong_t sz, UInt_t crc)
2725{
2726 // update CRC32 with new data
2727
2728 // use precomputed table, rather than computing it on the fly
2729 static const UInt_t crctab[256] = { 0x00000000,
2730 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
2731 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6,
2732 0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
2733 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac,
2734 0x5bd4b01b, 0x569796c2, 0x52568b75, 0x6a1936c8, 0x6ed82b7f,
2735 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a,
2736 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
2737 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58,
2738 0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033,
2739 0xa4ad16ea, 0xa06c0b5d, 0xd4326d90, 0xd0f37027, 0xddb056fe,
2740 0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
2741 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4,
2742 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
2743 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5,
2744 0x2ac12072, 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
2745 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, 0x7897ab07,
2746 0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c,
2747 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1,
2748 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
2749 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b,
2750 0xbb60adfc, 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698,
2751 0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d,
2752 0x94ea7b2a, 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
2753 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, 0xc6bcf05f,
2754 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
2755 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80,
2756 0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
2757 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a,
2758 0x58c1663d, 0x558240e4, 0x51435d53, 0x251d3b9e, 0x21dc2629,
2759 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c,
2760 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
2761 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e,
2762 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65,
2763 0xeba91bbc, 0xef68060b, 0xd727bbb6, 0xd3e6a601, 0xdea580d8,
2764 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
2765 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2,
2766 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
2767 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74,
2768 0x857130c3, 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
2769 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, 0x7b827d21,
2770 0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a,
2771 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, 0x18197087,
2772 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
2773 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d,
2774 0x2056cd3a, 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce,
2775 0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb,
2776 0xdbee767c, 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
2777 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, 0x89b8fd09,
2778 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
2779 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf,
2780 0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
2781 };
2782
2783 crc = ~crc;
2784 while (sz--) crc = (crc << 8) ^ UInt_t(*data++) ^ crctab[crc >> 24];
2785
2786 return ~crc;
2787}
2788
2789UInt_t crc32(const char* data)
2790{
2791 // Calculate crc32 checksum on given string
2792 unsigned long sz = strlen(data);
2793 switch (strlen(data)) {
2794 case 0:
2795 return 0;
2796 case 1:
2797 return data[0];
2798 case 2:
2799 return (data[0] << 8) | data[1];
2800 case 3:
2801 return (data[0] << 16) | (data[1] << 8) | data[2];
2802 case 4:
2803 return (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
2804 default:
2805 return crc32(data + 4, sz - 4, (data[0] << 24) | (data[1] << 16) |
2806 (data[2] << 8) | data[3]);
2807 }
2808}
2809
2810}
2811
2812////////////////////////////////////////////////////////////////////////////////
2813/// For all classes in the workspace for which no class definition is
2814/// found in the ROOT class table extract source code stored in code
2815/// repository into temporary directory set by
2816/// setClassFileExportDir(), compile classes and link them with
2817/// current ROOT session. If a compilation error occurs print
2818/// instructions for user how to fix errors and recover workspace and
2819/// abort import procedure.
2820
2822{
2823 Bool_t haveDir=kFALSE ;
2824
2825 // Retrieve name of directory in which to export code files
2826 string dirName = Form(_classFileExportDir.c_str(),_wspace->uuid().AsString(),_wspace->GetName()) ;
2827
2828 Bool_t writeExtraHeaders(kFALSE) ;
2829
2830 // Process all class entries in repository
2831 map<TString,ClassRelInfo>::iterator iter = _c2fmap.begin() ;
2832 while(iter!=_c2fmap.end()) {
2833
2834 oocxcoutD(_wspace,ObjectHandling) << "RooWorkspace::CodeRepo::compileClasses() now processing class " << iter->first.Data() << endl ;
2835
2836 // If class is already known, don't load
2837 if (gClassTable->GetDict(iter->first.Data())) {
2838 oocoutI(_wspace,ObjectHandling) << "RooWorkspace::CodeRepo::compileClasses() Embedded class "
2839 << iter->first << " already in ROOT class table, skipping" << endl ;
2840 ++iter ;
2841 continue ;
2842 }
2843
2844 // Check that export directory exists
2845 if (!haveDir) {
2846
2847 // If not, make local directory to extract files
2848 if (!gSystem->AccessPathName(dirName.c_str())) {
2849 oocoutI(_wspace,ObjectHandling) << "RooWorkspace::CodeRepo::compileClasses() reusing code export directory " << dirName.c_str()
2850 << " to extract coded embedded in workspace" << endl ;
2851 } else {
2852 if (gSystem->MakeDirectory(dirName.c_str())==0) {
2853 oocoutI(_wspace,ObjectHandling) << "RooWorkspace::CodeRepo::compileClasses() creating code export directory " << dirName.c_str()
2854 << " to extract coded embedded in workspace" << endl ;
2855 } else {
2856 oocoutE(_wspace,ObjectHandling) << "RooWorkspace::CodeRepo::compileClasses() ERROR creating code export directory " << dirName.c_str()
2857 << " to extract coded embedded in workspace" << endl ;
2858 return kFALSE ;
2859 }
2860 }
2861 haveDir=kTRUE ;
2862
2863 }
2864
2865 // First write any extra header files
2866 if (!writeExtraHeaders) {
2867 writeExtraHeaders = kTRUE ;
2868
2869 map<TString,ExtraHeader>::iterator eiter = _ehmap.begin() ;
2870 while(eiter!=_ehmap.end()) {
2871
2872 // Check if identical declaration file (header) is already written
2873 Bool_t needEHWrite=kTRUE ;
2874 string fdname = Form("%s/%s",dirName.c_str(),eiter->second._hname.Data()) ;
2875 ifstream ifdecl(fdname.c_str()) ;
2876 if (ifdecl) {
2877 TString contents ;
2878 char buf[64000];
2879 while (ifdecl.getline(buf, 64000)) {
2880 contents += buf;
2881 contents += "\n";
2882 }
2883 UInt_t crcFile = crc32(contents.Data());
2884 UInt_t crcWS = crc32(eiter->second._hfile.Data());
2885 needEHWrite = (crcFile != crcWS);
2886 }
2887
2888 // Write declaration file if required
2889 if (needEHWrite) {
2890 oocoutI(_wspace, ObjectHandling) << "RooWorkspace::CodeRepo::compileClasses() Extracting extra header file "
2891 << fdname << endl;
2892
2893 // Extra headers may contain non-existing path - create first to be sure
2894 gSystem->MakeDirectory(gSystem->GetDirName(fdname.c_str()));
2895
2896 ofstream fdecl(fdname.c_str());
2897 if (!fdecl) {
2898 oocoutE(_wspace, ObjectHandling) << "RooWorkspace::CodeRepo::compileClasses() ERROR opening file " << fdname
2899 << " for writing" << endl;
2900 return kFALSE;
2901 }
2902 fdecl << eiter->second._hfile.Data();
2903 fdecl.close();
2904 }
2905 ++eiter;
2906 }
2907 }
2908
2909
2910 // Navigate from class to file
2911 ClassFiles& cfinfo = _fmap[iter->second._fileBase] ;
2912
2913 oocxcoutD(_wspace,ObjectHandling) << "RooWorkspace::CodeRepo::compileClasses() now processing file with base " << iter->second._fileBase << endl ;
2914
2915 // If file is already processed, skip to next class
2916 if (cfinfo._extracted) {
2917 oocxcoutD(_wspace,ObjectHandling) << "RooWorkspace::CodeRepo::compileClasses() file with base name " << iter->second._fileBase
2918 << " has already been extracted, skipping to next class" << endl ;
2919 continue ;
2920 }
2921
2922 // Check if identical declaration file (header) is already written
2923 Bool_t needDeclWrite=kTRUE ;
2924 string fdname = Form("%s/%s.%s",dirName.c_str(),iter->second._fileBase.Data(),cfinfo._hext.Data()) ;
2925 ifstream ifdecl(fdname.c_str()) ;
2926 if (ifdecl) {
2927 TString contents ;
2928 char buf[64000];
2929 while (ifdecl.getline(buf, 64000)) {
2930 contents += buf;
2931 contents += "\n";
2932 }
2933 UInt_t crcFile = crc32(contents.Data()) ;
2934 UInt_t crcWS = crc32(cfinfo._hfile.Data()) ;
2935 needDeclWrite = (crcFile!=crcWS) ;
2936 }
2937
2938 // Write declaration file if required
2939 if (needDeclWrite) {
2940 oocoutI(_wspace,ObjectHandling) << "RooWorkspace::CodeRepo::compileClasses() Extracting declaration code of class " << iter->first << ", file " << fdname << endl ;
2941 ofstream fdecl(fdname.c_str()) ;
2942 if (!fdecl) {
2943 oocoutE(_wspace,ObjectHandling) << "RooWorkspace::CodeRepo::compileClasses() ERROR opening file "
2944 << fdname << " for writing" << endl ;
2945 return kFALSE ;
2946 }
2947 fdecl << cfinfo._hfile ;
2948 fdecl.close() ;
2949 }
2950
2951 // Check if identical implementation file is already written
2952 Bool_t needImplWrite=kTRUE ;
2953 string finame = Form("%s/%s.cxx",dirName.c_str(),iter->second._fileBase.Data()) ;
2954 ifstream ifimpl(finame.c_str()) ;
2955 if (ifimpl) {
2956 TString contents ;
2957 char buf[64000];
2958 while (ifimpl.getline(buf, 64000)) {
2959 contents += buf;
2960 contents += "\n";
2961 }
2962 UInt_t crcFile = crc32(contents.Data()) ;
2963 UInt_t crcWS = crc32(cfinfo._cxxfile.Data()) ;
2964 needImplWrite = (crcFile!=crcWS) ;
2965 }
2966
2967 // Write implementation file if required
2968 if (needImplWrite) {
2969 oocoutI(_wspace,ObjectHandling) << "RooWorkspace::CodeRepo::compileClasses() Extracting implementation code of class " << iter->first << ", file " << finame << endl ;
2970 ofstream fimpl(finame.c_str()) ;
2971 if (!fimpl) {
2972 oocoutE(_wspace,ObjectHandling) << "RooWorkspace::CodeRepo::compileClasses() ERROR opening file"
2973 << finame << " for writing" << endl ;
2974 return kFALSE ;
2975 }
2976 fimpl << cfinfo._cxxfile ;
2977 fimpl.close() ;
2978 }
2979
2980 // Mark this file as extracted
2981 cfinfo._extracted = kTRUE ;
2982 oocxcoutD(_wspace,ObjectHandling) << "RooWorkspace::CodeRepo::compileClasses() marking code unit " << iter->second._fileBase << " as extracted" << endl ;
2983
2984 // Compile class
2985 oocoutI(_wspace,ObjectHandling) << "RooWorkspace::CodeRepo::compileClasses() Compiling code unit " << iter->second._fileBase.Data() << " to define class " << iter->first << endl ;
2986 Bool_t ok = gSystem->CompileMacro(finame.c_str(),"k") ;
2987
2988 if (!ok) {
2989 oocoutE(_wspace,ObjectHandling) << "RooWorkspace::CodeRepo::compileClasses() ERROR compiling class " << iter->first.Data() << ", to fix this you can do the following: " << endl
2990 << " 1) Fix extracted source code files in directory " << dirName.c_str() << "/" << endl
2991 << " 2) In clean ROOT session compiled fixed classes by hand using '.x " << dirName.c_str() << "/ClassName.cxx+'" << endl
2992 << " 3) Reopen file with RooWorkspace with broken source code in UPDATE mode. Access RooWorkspace to force loading of class" << endl
2993 << " Broken instances in workspace will _not_ be compiled, instead precompiled fixed instances will be used." << endl
2994 << " 4) Reimport fixed code in workspace using 'RooWorkspace::importClassCode(\"*\",kTRUE)' method, Write() updated workspace to file and close file" << endl
2995 << " 5) Reopen file in clean ROOT session to confirm that problems are fixed" << endl ;
2996 return kFALSE ;
2997 }
2998
2999 ++iter ;
3000 }
3001
3002 return kTRUE ;
3003}
3004
3005
3006
3007////////////////////////////////////////////////////////////////////////////////
3008/// Internal access to TDirectory append method
3009
3011{
3013}
3014
3015
3016////////////////////////////////////////////////////////////////////////////////
3017/// Overload TDirectory interface method to prohibit insertion of objects in read-only directory workspace representation
3018
3020{
3021 if (dynamic_cast<RooAbsArg*>(obj) || dynamic_cast<RooAbsData*>(obj)) {
3022 coutE(ObjectHandling) << "RooWorkspace::WSDir::Add(" << GetName() << ") ERROR: Directory is read-only representation of a RooWorkspace, use RooWorkspace::import() to add objects" << endl ;
3023 } else {
3024 InternalAppend(obj) ;
3025 }
3026}
3027
3028
3029////////////////////////////////////////////////////////////////////////////////
3030/// Overload TDirectory interface method to prohibit insertion of objects in read-only directory workspace representation
3031
3033{
3034 if (dynamic_cast<RooAbsArg*>(obj) || dynamic_cast<RooAbsData*>(obj)) {
3035 coutE(ObjectHandling) << "RooWorkspace::WSDir::Add(" << GetName() << ") ERROR: Directory is read-only representation of a RooWorkspace, use RooWorkspace::import() to add objects" << endl ;
3036 } else {
3037 InternalAppend(obj) ;
3038 }
3039}
3040
3041
3042
3043////////////////////////////////////////////////////////////////////////////////
3044/// Activate export of workspace symbols to CINT in a namespace with given name. If no name
3045/// is given the namespace will have the same name as the workspace
3046
3047void RooWorkspace::exportToCint(const char* nsname)
3048{
3049 // If export is already active, do nothing
3050 if (_doExport) {
3051 coutE(ObjectHandling) << "RooWorkspace::exportToCint(" << GetName() << ") WARNING: repeated calls to exportToCint() have no effect" << endl ;
3052 return ;
3053 }
3054
3055 // Set flag so that future import to workspace are automatically exported to CINT
3056 _doExport = kTRUE ;
3057
3058 // If no name is provided choose name of workspace
3059 if (!nsname) nsname = GetName() ;
3060 _exportNSName = nsname ;
3061
3062 coutI(ObjectHandling) << "RooWorkspace::exportToCint(" << GetName()
3063 << ") INFO: references to all objects in this workspace will be created in CINT in 'namespace " << _exportNSName << "'" << endl ;
3064
3065 // Export present contents of workspace to CINT
3067 TObject* wobj ;
3068 while((wobj=iter->Next())) {
3069 exportObj(wobj) ;
3070 }
3071 delete iter ;
3072 iter = _dataList.MakeIterator() ;
3073 while((wobj=iter->Next())) {
3074 exportObj(wobj) ;
3075 }
3076 delete iter ;
3077}
3078
3079
3080////////////////////////////////////////////////////////////////////////////////
3081/// Export reference to given workspace object to CINT
3082
3084{
3085 // Do nothing if export flag is not set
3086 if (!_doExport) return ;
3087
3088 // Do not export RooConstVars
3089 if (wobj->IsA() == RooConstVar::Class()) {
3090 return ;
3091 }
3092
3093
3094 // Determine if object name is a valid C++ identifier name
3095
3096 // Do not export objects that have names that are not valid C++ identifiers
3097 if (!isValidCPPID(wobj->GetName())) {
3098 cxcoutD(ObjectHandling) << "RooWorkspace::exportObj(" << GetName() << ") INFO: Workspace object name " << wobj->GetName() << " is not a valid C++ identifier and is not exported to CINT" << endl ;
3099 return ;
3100 }
3101
3102 // Declare correctly typed reference to object in CINT in the namespace associated with this workspace
3103 string cintExpr = Form("namespace %s { %s& %s = *(%s *)0x%lx ; }",_exportNSName.c_str(),wobj->IsA()->GetName(),wobj->GetName(),wobj->IsA()->GetName(),(ULong_t)wobj) ;
3104 gROOT->ProcessLine(cintExpr.c_str()) ;
3105}
3106
3107
3108
3109////////////////////////////////////////////////////////////////////////////////
3110/// Return true if given name is a valid C++ identifier name
3111
3113{
3114 string oname(name) ;
3115 if (isdigit(oname[0])) {
3116 return kFALSE ;
3117 } else {
3118 for (UInt_t i=0 ; i<oname.size() ; i++) {
3119 char c = oname[i] ;
3120 if (!isalnum(c) && (c!='_')) {
3121 return kFALSE ;
3122 }
3123 }
3124 }
3125 return kTRUE ;
3126}
3127
3128////////////////////////////////////////////////////////////////////////////////
3129/// Delete exported reference in CINT namespace
3130
3132{
3133 char buf[64000];
3135 TObject *wobj;
3136 while ((wobj = iter->Next())) {
3137 if (isValidCPPID(wobj->GetName())) {
3138 strlcpy(buf, Form("%s::%s", _exportNSName.c_str(), wobj->GetName()), 64000);
3139 gInterpreter->DeleteVariable(buf);
3140 }
3141 }
3142 delete iter ;
3143}
3144
3145////////////////////////////////////////////////////////////////////////////////
3146/// If one of the TObject we have a referenced to is deleted, remove the
3147/// reference.
3148
3150{
3151 _dataList.RecursiveRemove(removedObj);
3152 if (removedObj == _dir) _dir = nullptr;
3153
3154 _allOwnedNodes.RecursiveRemove(removedObj); // RooArgSet
3155
3156 _dataList.RecursiveRemove(removedObj);
3158 _views.RecursiveRemove(removedObj);
3159 _snapshots.RecursiveRemove(removedObj);
3160 _genObjects.RecursiveRemove(removedObj);
3161 _studyMods.RecursiveRemove(removedObj);
3162
3163 for(auto c : _namedSets) {
3164 c.second.RecursiveRemove(removedObj);
3165 }
3166
3167 _eocache.RecursiveRemove(removedObj); // RooExpensiveObjectCache
3168}
void Class()
Definition: Class.C:29
#define f(i)
Definition: RSha256.hxx:104
#define c(i)
Definition: RSha256.hxx:101
#define coutI(a)
Definition: RooMsgService.h:30
#define cxcoutD(a)
Definition: RooMsgService.h:81
#define oocoutW(o, a)
Definition: RooMsgService.h:47
#define oocxcoutD(o, a)
Definition: RooMsgService.h:83
#define coutW(a)
Definition: RooMsgService.h:32
#define oocoutE(o, a)
Definition: RooMsgService.h:48
#define oocoutI(o, a)
Definition: RooMsgService.h:45
#define coutE(a)
Definition: RooMsgService.h:33
#define ooccoutW(o, a)
Definition: RooMsgService.h:55
short Version_t
Definition: RtypesCore.h:63
unsigned int UInt_t
Definition: RtypesCore.h:44
const Bool_t kFALSE
Definition: RtypesCore.h:90
unsigned long ULong_t
Definition: RtypesCore.h:53
bool Bool_t
Definition: RtypesCore.h:61
const Bool_t kTRUE
Definition: RtypesCore.h:89
const char Option_t
Definition: RtypesCore.h:64
#define ClassImp(name)
Definition: Rtypes.h:361
R__EXTERN TClassTable * gClassTable
Definition: TClassTable.h:94
@ kIsAbstract
Definition: TDictionary.h:71
char name[80]
Definition: TGX11.cxx:109
#define gInterpreter
Definition: TInterpreter.h:556
#define gROOT
Definition: TROOT.h:406
char * Form(const char *fmt,...)
R__EXTERN TSystem * gSystem
Definition: TSystem.h:556
RooAbsArg is the common abstract base class for objects that represent a value (of arbitrary type) an...
Definition: RooAbsArg.h:73
void setStringAttribute(const Text_t *key, const Text_t *value)
Associate string 'value' to this object under key 'key'.
Definition: RooAbsArg.cxx:289
static void ioStreamerPass2Finalize()
Method called by workspace container to finalize schema evolution issues that cannot be handled in a ...
Definition: RooAbsArg.cxx:2299
void setWorkspace(RooWorkspace &ws)
Definition: RooAbsArg.h:482
void printComponentTree(const char *indent="", const char *namePat=0, Int_t nLevel=999)
Print tree structure of expression tree on given ostream, only branch nodes are printed.
Definition: RooAbsArg.cxx:1805
virtual void setExpensiveObjectCache(RooExpensiveObjectCache &cache)
Definition: RooAbsArg.h:521
virtual Bool_t isFundamental() const
Is this object a fundamental type that can be added to a dataset? Fundamental-type subclasses overrid...
Definition: RooAbsArg.h:243
RefCountList_t _clientListValue
Definition: RooAbsArg.h:583
virtual void Print(Option_t *options=0) const
Print the object to the defaultPrintStream().
Definition: RooAbsArg.h:302
const Text_t * getStringAttribute(const Text_t *key) const
Get string attribute mapped under key 'key'.
Definition: RooAbsArg.cxx:302
void setAttribute(const Text_t *name, Bool_t value=kTRUE)
Set (default) or clear a named boolean attribute of this object.
Definition: RooAbsArg.cxx:257
Bool_t hasClients() const
Definition: RooAbsArg.h:117
RooArgSet * getVariables(Bool_t stripDisconnected=kTRUE) const
Return RooArgSet with all variables (tree leaf nodes of expresssion tree)
Definition: RooAbsArg.cxx:1909
virtual void ioStreamerPass2()
Method called by workspace container to finalize schema evolution issues that cannot be handled in a ...
Definition: RooAbsArg.cxx:2271
RefCountList_t _clientListShape
Definition: RooAbsArg.h:582
Bool_t getAttribute(const Text_t *name) const
Check if a named attribute is set. By default, all attributes are unset.
Definition: RooAbsArg.cxx:280
RefCountList_t _clientList
Definition: RooAbsArg.h:581
void branchNodeServerList(RooAbsCollection *list, const RooAbsArg *arg=0, Bool_t recurseNonDerived=kFALSE) const
Fill supplied list with all branch nodes of the arg tree starting with ourself as top node.
Definition: RooAbsArg.cxx:486
void SetName(const char *name)
Set the name of the TNamed.
Definition: RooAbsArg.cxx:2216
RooAbsCategory is the base class for objects that represent a discrete value with a finite number of ...
virtual void removeAll()
Remove all arguments from our set, deleting them if we own them.
Bool_t containsInstance(const RooAbsArg &var) const
Check if this exact instance is in this collection.
RooAbsCollection * selectCommon(const RooAbsCollection &refColl) const
Create a subset of the current collection, consisting only of those elements that are contained as we...
Int_t getSize() const
void sort(Bool_t reverse=false)
Sort collection using std::sort and name comparison.
RooFIter fwdIterator() const
One-time forward iterator.
void useHashMapForFind(bool flag) const
Install an internal hash map for fast finding of elements by name.
const char * GetName() const
Returns name of object.
void setName(const char *name)
virtual void RecursiveRemove(TObject *obj)
If one of the TObject we have a referenced to is deleted, remove the reference.
virtual Bool_t remove(const RooAbsArg &var, Bool_t silent=kFALSE, Bool_t matchByNameOnly=kFALSE)
Remove the specified argument from our list.
TIterator * createIterator(Bool_t dir=kIterForward) const
TIterator-style iteration over contained elements.
RooAbsArg * find(const char *name) const
Find object with given name in list.
RooAbsData is the common abstract base class for binned and unbinned datasets.
Definition: RooAbsData.h:44
virtual const RooArgSet * get() const
Definition: RooAbsData.h:87
virtual Bool_t changeObservableName(const char *from, const char *to)
Definition: RooAbsData.cxx:286
RooAbsOptTestStatistic is the abstract base class for test statistics objects that evaluate a functio...
const char * sealNotice() const
RooAbsReal is the common abstract base class for objects that represent a real value and implements f...
Definition: RooAbsReal.h:60
RooAbsStudy is an abstract base class for RooStudyManager modules.
Definition: RooAbsStudy.h:33
TObject * Clone(const char *newname="") const
Make a clone of an object using the Streamer facility.
Definition: RooAbsStudy.h:40
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Definition: RooArgSet.h:28
RooArgSet * snapshot(bool deepCopy=true) const
Use RooAbsCollection::snapshot(), but return as RooArgSet.
Definition: RooArgSet.h:126
virtual Bool_t addOwned(const RooAbsCollection &col, Bool_t silent=kFALSE)
Add a collection of arguments to this collection by calling addOwned() for each element in the source...
Definition: RooArgSet.h:92
virtual Bool_t add(const RooAbsCollection &col, Bool_t silent=kFALSE)
Add a collection of arguments to this collection by calling add() for each element in the source coll...
Definition: RooArgSet.h:88
RooCategory is an object to represent discrete states.
Definition: RooCategory.h:23
RooCmdArg is a named container for two doubles, two integers two object points and three string point...
Definition: RooCmdArg.h:28
Class RooCmdConfig is a configurable parser for RooCmdArg named arguments.
Definition: RooCmdConfig.h:27
RooExpensiveObjectCache is a singleton class that serves as repository for objects that are expensive...
void importCacheObjects(RooExpensiveObjectCache &other, const char *ownerName, Bool_t verbose=kFALSE)
A one-time forward iterator working on RooLinkedList or RooAbsCollection.
RooAbsArg * next()
Return next element or nullptr if at end.
RooFactoryWSTool is a class similar to TTree::MakeClass() that generates skeleton code for RooAbsPdf ...
RooAbsArg * process(const char *expr)
Create a RooFit object from the given expression.
RooLinkedList is an collection class for internal use, storing a collection of RooAbsArg pointers in ...
Definition: RooLinkedList.h:35
Int_t GetSize() const
Definition: RooLinkedList.h:60
TObject * FindObject(const char *name) const
Return pointer to obejct with given name.
Int_t getHashTableSize() const
Definition: RooLinkedList.h:50
TIterator * MakeIterator(Bool_t forward=kTRUE) const
Create a TIterator for this list.
void Delete(Option_t *o=0)
Remove all elements in collection and delete all elements NB: Collection does not own elements,...
TObject * find(const char *name) const
Return pointer to object with given name in collection.
virtual void RecursiveRemove(TObject *obj)
If one of the TObject we have a referenced to is deleted, remove the reference.
virtual void Add(TObject *arg)
Definition: RooLinkedList.h:62
void setHashTableSize(Int_t size)
Change the threshold for hash-table use to given size.
Bool_t Replace(const TObject *oldArg, const TObject *newArg)
Replace object 'oldArg' in collection with new object 'newArg'.
virtual Bool_t Remove(TObject *arg)
Remove object from collection.
static RooMsgService & instance()
Return reference to singleton instance.
void setGlobalKillBelow(RooFit::MsgLevel level)
RooFit::MsgLevel globalKillBelow() const
static Bool_t setAddDirectoryStatus(Bool_t flag)
Definition: RooPlot.cxx:78
RooRealVar represents a variable that can be changed from the outside.
Definition: RooRealVar.h:35
RooResolutionModel is the base class for PDFs that represent a resolution model that can be convolute...
std::size_t refCount(typename Container_t::const_iterator item) const
Return ref count of item that iterator points to.
void Remove(const T *obj, bool force=false)
Decrease ref count of given object.
Container_t::const_iterator begin() const
Iterator over contained objects.
Container_t::const_iterator end() const
End of contained objects.
RooInt is a minimal implementation of a TNamed holding a TObject.
Definition: RooTObjWrap.h:23
void setOwning(Bool_t flag)
Definition: RooTObjWrap.h:31
An interface to set and retrieve a workspace.
virtual void ReplaceWS(RooWorkspace *ws)=0
Set the workspace irrespective of what the previous workspace is.
Bool_t autoImportClass(TClass *tc, Bool_t doReplace=kFALSE)
Import code of class 'tc' into the repository.
std::map< TString, ExtraHeader > _ehmap
Definition: RooWorkspace.h:215
RooWorkspace * _wspace
Definition: RooWorkspace.h:212
std::string listOfClassNames() const
Return STL string with last of class names contained in the code repository.
std::map< TString, ClassRelInfo > _c2fmap
Definition: RooWorkspace.h:213
Bool_t compileClasses()
For all classes in the workspace for which no class definition is found in the ROOT class table extra...
std::map< TString, ClassFiles > _fmap
Definition: RooWorkspace.h:214
virtual void Append(TObject *, Bool_t)
Overload TDirectory interface method to prohibit insertion of objects in read-only directory workspac...
void InternalAppend(TObject *obj)
Internal access to TDirectory append method.
virtual void Add(TObject *, Bool_t)
Overload TDirectory interface method to prohibit insertion of objects in read-only directory workspac...
The RooWorkspace is a persistable container for RooFit projects.
Definition: RooWorkspace.h:43
Bool_t makeDir()
Create transient TDirectory representation of this workspace.
RooExpensiveObjectCache _eocache
Transient ROOT directory representation of workspace.
Definition: RooWorkspace.h:276
RooLinkedList _genObjects
Definition: RooWorkspace.h:270
void exportToCint(const char *namespaceName=0)
Activate export of workspace symbols to CINT in a namespace with given name.
std::string _exportNSName
Export contents of workspace to CINT?
Definition: RooWorkspace.h:281
static std::list< std::string > _classDeclDirList
Definition: RooWorkspace.h:255
const RooArgSet * getSnapshot(const char *name) const
Return the RooArgSet containing a snapshot of variables contained in the workspace.
Bool_t extendSet(const char *name, const char *newContents)
Define a named set in the work space through a comma separated list of names of objects already in th...
static void addClassDeclImportDir(const char *dir)
Add dir to search path for class declaration (header) files.
Bool_t defineSetInternal(const char *name, const RooArgSet &aset)
void unExport()
Delete exported reference in CINT namespace.
RooLinkedList _dataList
Definition: RooWorkspace.h:266
RooAbsData * data(const char *name) const
Retrieve dataset (binned or unbinned) with given name. A null pointer is returned if not found.
RooAbsData * embeddedData(const char *name) const
Retrieve dataset (binned or unbinned) with given name. A null pointer is returned if not found.
WSDir * _dir
Definition: RooWorkspace.h:274
static void addClassImplImportDir(const char *dir)
Add dir to search path for class implementation (.cxx) files.
TObject * genobj(const char *name) const
Return generic object with given name.
std::map< std::string, RooArgSet > _namedSets
Definition: RooWorkspace.h:272
Bool_t _openTrans
Name of CINT namespace to which contents are exported.
Definition: RooWorkspace.h:283
std::list< RooAbsData * > allData() const
Return list of all dataset in the workspace.
void clearStudies()
Remove all RooStudyManager modules.
RooAbsArg * fundArg(const char *name) const
Return fundamental (i.e.
RooArgSet argSet(const char *nameList) const
Return set of RooAbsArgs matching to given list of names.
std::unique_ptr< RooFactoryWSTool > _factory
Definition: RooWorkspace.h:278
RooArgSet allVars() const
Return set with all variable objects.
virtual void RecursiveRemove(TObject *obj)
If one of the TObject we have a referenced to is deleted, remove the reference.
RooArgSet allCats() const
Return set with all category objects.
Bool_t commitTransaction()
RooLinkedList _views
Definition: RooWorkspace.h:268
Bool_t startTransaction()
Open an import transaction operations.
RooAbsReal * function(const char *name) const
Retrieve function (RooAbsReal) with given name. Note that all RooAbsPdfs are also RooAbsReals....
RooArgSet allResolutionModels() const
Return set with all resolution model objects.
RooLinkedList _snapshots
Definition: RooWorkspace.h:269
Bool_t importClassCode(const char *pat="*", Bool_t doReplace=kFALSE)
Inport code of all classes in the workspace that have a class name that matches pattern 'pat' and whi...
RooCategory * cat(const char *name) const
Retrieve discrete variable (RooCategory) with given name. A null pointer is returned if not found.
Bool_t renameSet(const char *name, const char *newName)
Rename set to a new name.
RooAbsArg * arg(const char *name) const
Return RooAbsArg with given name. A null pointer is returned if none is found.
std::list< RooAbsData * > allEmbeddedData() const
Return list of all dataset in the workspace.
void Print(Option_t *opts=0) const
Print contents of the workspace.
RooArgSet allPdfs() const
Return set with all probability density function objects.
Bool_t addStudy(RooAbsStudy &study)
Insert RooStudyManager module.
Bool_t writeToFile(const char *fileName, Bool_t recreate=kTRUE)
Save this current workspace into given file.
std::list< TObject * > allGenericObjects() const
Return list of all generic objects in the workspace.
static void setClassFileExportDir(const char *dir=0)
Specify the name of the directory in which embedded source code is unpacked and compiled.
Bool_t _doExport
Factory tool associated with workspace.
Definition: RooWorkspace.h:280
Bool_t removeSet(const char *name)
Remove a named set from the workspace.
static void autoImportClassCode(Bool_t flag)
If flag is true, source code of classes not the the ROOT distribution is automatically imported if on...
RooAbsCategory * catfunc(const char *name) const
Retrieve discrete function (RooAbsCategory) with given name. A null pointer is returned if not found.
RooLinkedList _studyMods
Definition: RooWorkspace.h:271
RooArgSet allCatFunctions() const
Return set with all category function objects.
static std::string _classFileExportDir
Definition: RooWorkspace.h:257
static std::list< std::string > _classImplDirList
Definition: RooWorkspace.h:256
~RooWorkspace()
Workspace destructor.
Bool_t defineSet(const char *name, const RooArgSet &aset, Bool_t importMissing=kFALSE)
Define a named RooArgSet with given constituents.
RooWorkspace()
Default constructor.
Bool_t cd(const char *path=0)
Bool_t saveSnapshot(const char *name, const char *paramNames)
Save snapshot of values and attributes (including "Constant") of given parameters.
Bool_t loadSnapshot(const char *name)
Load the values and attributes of the parameters in the snapshot saved with the given name.
CodeRepo _classes
Definition: RooWorkspace.h:263
RooRealVar * var(const char *name) const
Retrieve real-valued variable (RooRealVar) with given name. A null pointer is returned if not found.
Bool_t import(const RooAbsArg &arg, const RooCmdArg &arg1=RooCmdArg(), const RooCmdArg &arg2=RooCmdArg(), const RooCmdArg &arg3=RooCmdArg(), const RooCmdArg &arg4=RooCmdArg(), const RooCmdArg &arg5=RooCmdArg(), const RooCmdArg &arg6=RooCmdArg(), const RooCmdArg &arg7=RooCmdArg(), const RooCmdArg &arg8=RooCmdArg(), const RooCmdArg &arg9=RooCmdArg())
Import a RooAbsArg object, e.g.
RooArgSet allFunctions() const
Return set with all function objects.
RooFactoryWSTool & factory()
Return instance to factory tool.
RooExpensiveObjectCache & expensiveObjectCache()
Definition: RooWorkspace.h:165
Bool_t isValidCPPID(const char *name)
Return true if given name is a valid C++ identifier name.
RooArgSet _sandboxNodes
Is there a transaction open?
Definition: RooWorkspace.h:284
Bool_t cancelTransaction()
Cancel an ongoing import transaction.
void exportObj(TObject *obj)
Export reference to given workspace object to CINT.
static Bool_t _autoClass
Definition: RooWorkspace.h:261
RooLinkedList _embeddedDataList
Definition: RooWorkspace.h:267
RooArgSet _allOwnedNodes
Definition: RooWorkspace.h:265
const RooArgSet * set(const char *name)
Return pointer to previously defined named set with given nmame If no such set is found a null pointe...
TObject * obj(const char *name) const
Return any type of object (RooAbsArg, RooAbsData or generic object) with given name)
TIterator * componentIterator() const
Definition: RooWorkspace.h:113
RooAbsPdf * pdf(const char *name) const
Retrieve p.d.f (RooAbsPdf) with given name. A null pointer is returned if not found.
Each class (see TClass) has a linked list of its base class(es).
Definition: TBaseClass.h:33
TClass * GetClassPointer(Bool_t load=kTRUE)
Get pointer to the base class TClass.
Definition: TBaseClass.cxx:63
Buffer base class used for serializing objects.
Definition: TBuffer.h:42
virtual void SetByteCount(UInt_t cntpos, Bool_t packInVersion=kFALSE)=0
virtual Int_t ReadClassBuffer(const TClass *cl, void *pointer, const TClass *onfile_class=0)=0
virtual Version_t ReadVersion(UInt_t *start=0, UInt_t *bcnt=0, const TClass *cl=0)=0
virtual Int_t CheckByteCount(UInt_t startpos, UInt_t bcnt, const TClass *clss)=0
Bool_t IsReading() const
Definition: TBuffer.h:85
virtual UInt_t WriteVersion(const TClass *cl, Bool_t useBcnt=kFALSE)=0
virtual Int_t WriteClassBuffer(const TClass *cl, void *pointer)=0
static DictFuncPtr_t GetDict(const char *cname)
Given the class name returns the Dictionary() function of a class (uses hash of name).
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition: TClass.h:80
const char * GetImplFileName() const
Definition: TClass.h:453
TList * GetListOfBases()
Return list containing the TBaseClass(es) of a class.
Definition: TClass.cxx:3604
Long_t Property() const
Returns the properties of the TClass as a bit field stored as a Long_t value.
Definition: TClass.cxx:6010
Bool_t HasDefaultConstructor(Bool_t testio=kFALSE) const
const char * GetDeclFileName() const
Return name of the file containing the declaration of this class.
Definition: TClass.cxx:3431
Bool_t cd(const char *path=nullptr) override
Change current directory to "this" directory.
virtual void Append(TObject *obj, Bool_t replace=kFALSE)
Append object to this directory.
Definition: TDirectory.cxx:191
A ROOT file is a suite of consecutive data records (TKey instances) with a well defined format.
Definition: TFile.h:53
static TFile * Open(const char *name, Option_t *option="", const char *ftitle="", Int_t compress=ROOT::RCompressionSetting::EDefaults::kUseCompiledDefault, Int_t netopt=0)
Create / open a file.
Definition: TFile.cxx:3942
static void AddDirectory(Bool_t add=kTRUE)
Sets the flag controlling the automatic add of histograms in memory.
Definition: TH1.cxx:1226
Iterator abstract base class.
Definition: TIterator.h:30
virtual TObject * Next()=0
A doubly linked list.
Definition: TList.h:44
virtual TIterator * MakeIterator(Bool_t dir=kIterForward) const
Return a list iterator.
Definition: TList.cxx:721
The TNamed class is the base class for all named ROOT classes.
Definition: TNamed.h:29
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition: TNamed.cxx:164
virtual void SetName(const char *name)
Set the name of the TNamed.
Definition: TNamed.cxx:140
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:48
virtual TObject * Clone(const char *newname="") const
Make a clone of an object using the Streamer facility.
Definition: TNamed.cxx:74
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
Mother of all ROOT objects.
Definition: TObject.h:37
virtual Int_t Write(const char *name=0, Int_t option=0, Int_t bufsize=0)
Write this object to the current directory.
Definition: TObject.cxx:796
virtual const char * GetName() const
Returns name of object.
Definition: TObject.cxx:357
virtual void RecursiveRemove(TObject *obj)
Recursively remove this object from a list.
Definition: TObject.cxx:572
virtual TObject * Clone(const char *newname="") const
Make a clone of an object using the Streamer facility.
Definition: TObject.cxx:144
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition: TObject.cxx:443
Regular expression class.
Definition: TRegexp.h:31
Basic string class.
Definition: TString.h:131
Ssiz_t Length() const
Definition: TString.h:405
const char * Data() const
Definition: TString.h:364
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition: TString.h:610
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:634
virtual const char * Getenv(const char *env)
Get environment variable.
Definition: TSystem.cxx:1658
virtual char * ConcatFileName(const char *dir, const char *name)
Concatenate a directory and a file name. User must delete returned string.
Definition: TSystem.cxx:1066
virtual int MakeDirectory(const char *name)
Make a directory.
Definition: TSystem.cxx:823
virtual Bool_t AccessPathName(const char *path, EAccessMode mode=kFileExists)
Returns FALSE if one can access a file using the specified access mode.
Definition: TSystem.cxx:1291
virtual const char * BaseName(const char *pathname)
Base name of a file name. Base name of /user/root is root.
Definition: TSystem.cxx:930
virtual int CompileMacro(const char *filename, Option_t *opt="", const char *library_name="", const char *build_dir="", UInt_t dirmode=0)
This method compiles and loads a shared library containing the code from the file "filename".
Definition: TSystem.cxx:2831
virtual TString GetDirName(const char *pathname)
Return the directory name in pathname.
Definition: TSystem.cxx:1027
const Int_t n
Definition: legend1.C:16
void(* DirAutoAdd_t)(void *, TDirectory *)
Definition: Rtypes.h:111
MsgLevel
Verbosity level for RooMsgService::StreamConfig in RooMsgService.
Definition: RooGlobalFunc.h:65
@ InputArguments
Definition: RooGlobalFunc.h:68
@ ObjectHandling
Definition: RooGlobalFunc.h:68
std::vector< std::string > tokenise(const std::string &str, const std::string &delims, bool returnEmptyToken=true)
Tokenise the string by splitting at the characters in delims.
Definition: RooHelpers.cxx:62
static constexpr double pc
Definition: first.py:1
auto * a
Definition: textangle.C:12