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