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