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