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