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