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