Logo ROOT   6.18/05
Reference Guide
RooCustomizer.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 * DK, David Kirkby, UC Irvine, dkirkby@uci.edu *
8 * *
9 * Copyright (c) 2000-2005, Regents of the University of California *
10 * and Stanford University. All rights reserved. *
11 * *
12 * Redistribution and use in source and binary forms, *
13 * with or without modification, are permitted according to the terms *
14 * listed in LICENSE (http://roofit.sourceforge.net/license.txt) *
15 *****************************************************************************/
16
17//////////////////////////////////////////////////////////////////////////////
18/// \class RooCustomizer
19///
20/// RooCustomizer is a factory class to produce clones
21/// of a prototype composite PDF object with the same structure but
22/// different leaf servers (parameters or dependents).
23///
24/// RooCustomizer supports two kinds of modifications:
25///
26/// - replace(leaf_arg,repl_arg)
27/// replaces each occurence of leaf_arg with repl_arg in the composite pdf.
28///
29/// - split(split_arg)
30/// is used when building multiple clones of the same prototype. Each
31/// occurrence of split_arg is replaceed with a clone of split_arg
32/// named split_arg_[MCstate], where [MCstate] is the name of the
33/// 'master category state' that indexes the clones to be built.
34///
35///
36/// Example
37/// ------------------------------
38/// Splitting is particularly useful when building simultaneous fits to
39/// subsets of the data sample with different background properties.
40/// In such a case, the user builds a single prototype PDF representing
41/// the structure of the signal and background and splits the dataset
42/// into categories with different background properties. Using
43/// RooCustomizer a PDF for each subfit can be constructed from the
44/// prototype that has same structure and signal parameters, but
45/// different instances of the background parameters: e.g.
46/// ```
47/// ...
48/// RooExponential bg("bg","background",x,alpha) ;
49/// RooGaussian sig("sig","signal",x,mean,sigma) ;
50/// RooAddPdf pdf("pdf","pdf",sig,bg,sigfrac) ;
51///
52/// RooDataSet data("data","dataset",RooArgSet(x,runblock),...)
53///
54/// RooCategory runblock("runblock","run block") ;
55/// runblock.defineType("run1") ;
56/// runblock.defineType("run2") ;
57///
58/// RooArgSet splitLeafs;
59/// RooCustomizer cust(pdf,runblock,splitLeafs);
60/// cust.split(alpha,runblock);
61///
62/// RooAbsPdf* pdf_run1 = cust.build("run1") ;
63/// RooAbsPdf* pdf_run2 = cust.build("run2") ;
64///
65/// RooSimultaneous simpdf("simpdf","simpdf",RooArgSet(*pdf_run1,*pdf_run2))
66/// ```
67/// If the master category state is a super category, leafs may be split
68/// by any subset of that master category. E.g. if the master category
69/// is 'A x B', leafs may be split by A, B or AxB.
70///
71/// In addition to replacing leaf nodes, RooCustomizer clones all branch
72/// nodes that depend directly or indirectly on modified leaf nodes, so
73/// that the input pdf is untouched by each build operation.
74///
75/// The customizer owns all the branch nodes including the returned top
76/// level node, so the customizer should live as longs as the cloned
77/// composites are needed.
78///
79/// Any leaf nodes that are created by the customizer will be put into
80/// the leaf list that is passed into the customizers constructor (splitLeafs in
81/// the above example. The list owner is responsible for deleting these leaf
82/// nodes after the customizer is deleted.
83///
84///
85/// Advanced techniques
86/// -------------------------------------
87///
88/// By default the customizer clones the prototype leaf node when splitting a leaf,
89/// but the user can feed pre-defined split leafs in leaf list. These leafs
90/// must have the name <split_leaf>_<splitcat_label> to be picked up. The list
91/// of pre-supplied leafs may be partial, any missing split leafs will be auto
92/// generated.
93///
94/// Another common construction is to have two prototype PDFs, each to be customized
95/// by a separate customizer instance, that share parameters. To ensure that
96/// the customized clones also share their respective split leafs, i.e.
97/// ```
98/// PDF1(x,y;A) and PDF2(z,A) ---> PDF1_run1(x,y,A_run1) and PDF2_run1(x,y,A_run1)
99/// PDF1_run2(x,y,A_run2) and PDF2_run2(x,y,A_run2)
100/// ```
101/// feed the same split leaf list into both customizers. In that case the second customizer
102/// will pick up the split leafs instantiated by the first customizer and the link between
103/// the two PDFs is retained
104///
105///
106
107
108#include "RooFit.h"
109
110#include "TClass.h"
111#include "TStopwatch.h"
112
113#include "RooAbsCategoryLValue.h"
114#include "RooAbsCategory.h"
115#include "RooAbsArg.h"
116#include "RooAbsPdf.h"
117#include "RooArgSet.h"
118#include "RooArgList.h"
119#include "RooMsgService.h"
120
121#include "RooCustomizer.h"
122
123#include "Riostream.h"
124#include "RooWorkspace.h"
125#include "RooGlobalFunc.h"
126#include "RooConstVar.h"
127#include "RooRealConstant.h"
128
129
130#ifndef _WIN32
131#include <strings.h>
132#endif
133
134
135using namespace std;
136
138;
139
140
141static Int_t init();
142
143static Int_t dummy = init() ;
144
145static Int_t init()
146{
149 (void) dummy;
150 return 0 ;
151}
152
153
154////////////////////////////////////////////////////////////////////////////////
155/// Constructor with a prototype and masterCat index category.
156/// Customizers created by this constructor offer offer both the
157/// replaceArg() and splitArg() functionality. All nodes created in
158/// the customization process are added to the splitLeafs set.
159/// If the customizer is owning, the splitLeafs set will become
160/// owner of all created objects by the customizer
161///
162
163RooCustomizer::RooCustomizer(const RooAbsArg& pdf, const RooAbsCategoryLValue& masterCat, RooArgSet& splitLeafs, RooArgSet* splitLeafsAll) :
164 TNamed(pdf.GetName(),pdf.GetTitle()),
165 _sterile(kFALSE),
166 _owning(kTRUE),
167 _masterPdf((RooAbsArg*)&pdf),
168 _masterCat((RooAbsCategoryLValue*)&masterCat),
169 _masterBranchList("masterBranchList"),
170 _masterLeafList("masterLeafList"),
171 _internalCloneBranchList("cloneBranchList"),
172 _cloneNodeListAll(splitLeafsAll),
173 _cloneNodeListOwned(&splitLeafs)
174{
177
180
181 initialize() ;
182}
183
184
185
186////////////////////////////////////////////////////////////////////////////////
187/// Sterile Constructor. Customizers created by this constructor
188/// offer only the replace() method. The supplied 'name' is used as
189/// suffix for any cloned branch nodes
190
192 TNamed(pdf.GetName(),pdf.GetTitle()),
193 _sterile(kTRUE),
194 _owning(kFALSE),
195 _name(name),
196 _masterPdf((RooAbsArg*)&pdf),
197 _masterCat(0),
198 _masterBranchList("masterBranchList"),
199 _masterLeafList("masterLeafList"),
200 _internalCloneBranchList("cloneBranchList"),
201 _cloneNodeListAll(0),
202 _cloneNodeListOwned(0)
203{
206
209
210 initialize() ;
211}
212
213
214
215
216////////////////////////////////////////////////////////////////////////////////
217/// Initialize the customizer
218
220{
223
226}
227
228
229
230////////////////////////////////////////////////////////////////////////////////
231/// Destructor
232
234{
235 delete _masterLeafListIter ;
236 delete _masterBranchListIter ;
237
238}
239
240
241
242
243////////////////////////////////////////////////////////////////////////////////
244/// Split all arguments in 'set' into individualized clones for each
245/// defined state of 'splitCat'. The 'splitCats' category must be
246/// subset of or equal to the master category supplied in the
247/// customizer constructor.
248///
249/// Splitting is only available on customizers created with a master index category
250
251void RooCustomizer::splitArgs(const RooArgSet& set, const RooAbsCategory& splitCat)
252{
253 if (_sterile) {
254 coutE(InputArguments) << "RooCustomizer::splitArgs(" << _name
255 << ") ERROR cannot set spitting rules on this sterile customizer" << endl ;
256 return ;
257 }
258 TIterator* iter = set.createIterator() ;
259 RooAbsArg* arg ;
260 while((arg=(RooAbsArg*)iter->Next())){
261 splitArg(*arg,splitCat) ;
262 }
263 delete iter ;
264}
265
266
267
268////////////////////////////////////////////////////////////////////////////////
269/// Split all argument 'arg' into individualized clones for each
270/// defined state of 'splitCat'. The 'splitCats' category must be
271/// subset of or equal to the master category supplied in the
272/// customizer constructor.
273///
274/// Splitting is only available on customizers created with a master index category
275
276void RooCustomizer::splitArg(const RooAbsArg& arg, const RooAbsCategory& splitCat)
277{
278 if (_splitArgList.FindObject(arg.GetName())) {
279 coutE(InputArguments) << "RooCustomizer(" << GetName() << ") ERROR: multiple splitting rules defined for "
280 << arg.GetName() << " only using first rule" << endl ;
281 return ;
282 }
283
284 if (_sterile) {
285 coutE(InputArguments) << "RooCustomizer::splitArg(" << _name
286 << ") ERROR cannot set spitting rules on this sterile customizer" << endl ;
287 return ;
288 }
289
290 _splitArgList.Add((RooAbsArg*)&arg) ;
291 _splitCatList.Add((RooAbsCategory*)&splitCat) ;
292}
293
294
295
296////////////////////////////////////////////////////////////////////////////////
297/// Replace any occurence of arg 'orig' with arg 'subst'
298
299void RooCustomizer::replaceArg(const RooAbsArg& orig, const RooAbsArg& subst)
300{
301 if (_replaceArgList.FindObject(orig.GetName())) {
302 coutE(InputArguments) << "RooCustomizer(" << GetName() << ") ERROR: multiple replacement rules defined for "
303 << orig.GetName() << " only using first rule" << endl ;
304 return ;
305 }
306
307 _replaceArgList.Add((RooAbsArg*)&orig) ;
308 _replaceSubList.Add((RooAbsArg*)&subst) ;
309}
310
311
312
313////////////////////////////////////////////////////////////////////////////////
314/// Build a clone of the prototype executing all registered 'replace' rules
315/// If verbose is set a message is printed for each leaf or branch node
316/// modification. The returned head node owns all cloned branch nodes
317/// that were created in the cloning proces
318
320{
321 // Execute build
322 RooAbsArg* ret = doBuild(_name.Length()>0?_name.Data():0,verbose) ;
323
324 // Make root object own all cloned nodes
325
326 // First make list of all objects that were created
327 RooArgSet allOwned ;
329 allOwned.add(*_cloneNodeListOwned) ;
330 }
331 allOwned.add(*_cloneBranchList) ;
332
333 // Remove head node from list
334 allOwned.remove(*ret) ;
335
336 // If list with owned objects is not empty, assign
337 // head node as owner
338 if (allOwned.getSize()>0) {
339 ret->addOwnedComponents(allOwned) ;
340 }
341
342 return ret ;
343}
344
345
346
347////////////////////////////////////////////////////////////////////////////////
348/// Build a clone of the prototype executing all registered 'replace'
349/// rules and 'split' rules for the masterCat state named
350/// 'masterCatState'. If verbose is set a message is printed for
351/// each leaf or branch node modification. The returned composite arg
352/// is owned by the customizer. This function cannot be called on
353/// customizer build with the sterile constructor.
354
355RooAbsArg* RooCustomizer::build(const char* masterCatState, Bool_t verbose)
356{
357 if (_sterile) {
358 coutE(InputArguments) << "RooCustomizer::build(" << _name
359 << ") ERROR cannot use leaf spitting build() on this sterile customizer" << endl ;
360 return 0 ;
361 }
362
363 // Set masterCat to given state
364 if (_masterCat->setLabel(masterCatState)) {
365 coutE(InputArguments) << "RooCustomizer::build(" << _masterPdf->GetName() << "): ERROR label '" << masterCatState
366 << "' not defined for master splitting category " << _masterCat->GetName() << endl ;
367 return 0 ;
368 }
369
370 return doBuild(masterCatState,verbose) ;
371}
372
373
374
375////////////////////////////////////////////////////////////////////////////////
376/// Back-end implementation of the p.d.f building functionality
377
378RooAbsArg* RooCustomizer::doBuild(const char* masterCatState, Bool_t verbose)
379{
380 // Find nodes that must be split according to provided description, Clone nodes, change their names
381 RooArgSet masterNodesToBeSplit("masterNodesToBeSplit") ;
382 RooArgSet masterNodesToBeReplaced("masterNodesToBeReplaced") ;
383 RooArgSet masterReplacementNodes("masterReplacementNodes") ;
384 RooArgSet clonedMasterNodes("clonedMasterNodes") ;
385
386 masterNodesToBeSplit.setHashTableSize(1000) ;
387 masterNodesToBeReplaced.setHashTableSize(1000) ;
388 masterReplacementNodes.setHashTableSize(1000) ;
389 clonedMasterNodes.setHashTableSize(1000) ;
390
392 RooAbsArg* node ;
393
394 RooArgSet nodeList(_masterLeafList) ;
395 nodeList.setHashTableSize(1000) ;
396
397 nodeList.add(_masterBranchList) ;
398 TIterator* nIter = nodeList.createIterator() ;
399
400 // cout << "loop over " << nodeList.getSize() << " nodes" << endl ;
401 while((node=(RooAbsArg*)nIter->Next())) {
402 RooAbsArg* theSplitArg = !_sterile?(RooAbsArg*) _splitArgList.FindObject(node->GetName()):0 ;
403 if (theSplitArg) {
405 if (verbose) {
406 coutI(ObjectHandling) << "RooCustomizer::build(" << _masterPdf->GetName()
407 << "): tree node " << node->GetName() << " is split by category " << splitCat->GetName() << endl ;
408 }
409
410 TString newName(node->GetName()) ;
411 if (masterCatState) {
412 newName.Append("_") ;
413 newName.Append(splitCat->getLabel()) ;
414 }
415
416 // Check if this node instance already exists
417 RooAbsArg* specNode = _cloneNodeListAll ? _cloneNodeListAll->find(newName) : _cloneNodeListOwned->find(newName) ;
418 if (specNode) {
419
420 // Copy instance to one-time use list for this build
421 clonedMasterNodes.add(*specNode) ;
422 if (verbose) {
423 coutI(ObjectHandling) << "RooCustomizer::build(" << _masterPdf->GetName()
424 << ") Adding existing node specialization " << newName << " to clonedMasterNodes" << endl ;
425 }
426
427 // Affix attribute with old name to clone to support name changing server redirect
428 TString nameAttrib("ORIGNAME:") ;
429 nameAttrib.Append(node->GetName()) ;
430 specNode->setAttribute(nameAttrib) ;
431
432 if (!specNode->getStringAttribute("origName")) {
433 specNode->setStringAttribute("origName",node->GetName()) ;
434 }
435
436
437
438 } else {
439
440 if (node->isDerived()) {
441 coutW(ObjectHandling) << "RooCustomizer::build(" << _masterPdf->GetName()
442 << "): WARNING: branch node " << node->GetName() << " is split but has no pre-defined specializations" << endl ;
443 }
444
445 TString newTitle(node->GetTitle()) ;
446 newTitle.Append(" (") ;
447 newTitle.Append(splitCat->getLabel()) ;
448 newTitle.Append(")") ;
449
450 // Create a new clone
451 RooAbsArg* clone = (RooAbsArg*) node->Clone(newName.Data()) ;
452 clone->setStringAttribute("factory_tag",0) ;
453 clone->SetTitle(newTitle) ;
454
455 // Affix attribute with old name to clone to support name changing server redirect
456 TString nameAttrib("ORIGNAME:") ;
457 nameAttrib.Append(node->GetName()) ;
458 clone->setAttribute(nameAttrib) ;
459
460 if (!clone->getStringAttribute("origName")) {
461 clone->setStringAttribute("origName",node->GetName()) ;
462 }
463
464 // Add to one-time use list and life-time use list
465 clonedMasterNodes.add(*clone) ;
466 if (_owning) {
467 _cloneNodeListOwned->addOwned(*clone) ;
468 } else {
469 _cloneNodeListOwned->add(*clone) ;
470 }
471 if (_cloneNodeListAll) {
472 _cloneNodeListAll->add(*clone) ;
473 }
474 }
475 masterNodesToBeSplit.add(*node) ;
476 }
477
478 RooAbsArg* ReplaceArg = (RooAbsArg*) _replaceArgList.FindObject(node->GetName()) ;
479 if (ReplaceArg) {
480 RooAbsArg* substArg = (RooAbsArg*) _replaceSubList.At(_replaceArgList.IndexOf(ReplaceArg)) ;
481 if (verbose) {
482 coutI(ObjectHandling) << "RooCustomizer::build(" << _masterPdf->GetName()
483 << "): tree node " << node->GetName() << " will be replaced by " << substArg->GetName() << endl ;
484 }
485
486 // Affix attribute with old name to support name changing server redirect
487 TString nameAttrib("ORIGNAME:") ;
488 nameAttrib.Append(node->GetName()) ;
489 substArg->setAttribute(nameAttrib) ;
490
491 // Add to list
492 masterNodesToBeReplaced.add(*node) ;
493 masterReplacementNodes.add(*substArg) ;
494 }
495 }
496 delete nIter ;
497
498 // Find branches that are affected by splitting and must be cloned
499 RooArgSet masterBranchesToBeCloned("masterBranchesToBeCloned") ;
500 masterBranchesToBeCloned.setHashTableSize(1000) ;
502 RooAbsArg* branch ;
503 while((branch=(RooAbsArg*)_masterBranchListIter->Next())) {
504
505 // If branch is split itself, don't handle here
506 if (masterNodesToBeSplit.find(branch->GetName())) {
507 if (verbose) {
508 coutI(ObjectHandling) << "RooCustomizer::build(" << _masterPdf->GetName() << ") Branch node " << branch->GetName() << " is already split" << endl ;
509 }
510 continue ;
511 }
512 if (masterNodesToBeReplaced.find(branch->GetName())) {
513 if (verbose) {
514 coutI(ObjectHandling) << "RooCustomizer::build(" << _masterPdf->GetName() << ") Branch node " << branch->GetName() << " is already replaced" << endl ;
515 }
516 continue ;
517 }
518
519 if (branch->dependsOn(masterNodesToBeSplit)) {
520 if (verbose) {
521 coutI(ObjectHandling) << "RooCustomizer::build(" << _masterPdf->GetName() << ") Branch node "
522 << branch->IsA()->GetName() << "::" << branch->GetName() << " cloned: depends on a split parameter" << endl ;
523 }
524 masterBranchesToBeCloned.add(*branch) ;
525 } else if (branch->dependsOn(masterNodesToBeReplaced)) {
526 if (verbose) {
527 coutI(ObjectHandling) << "RooCustomizer::build(" << _masterPdf->GetName() << ") Branch node "
528 << branch->IsA()->GetName() << "::" << branch->GetName() << " cloned: depends on a replaced parameter" << endl ;
529 }
530 masterBranchesToBeCloned.add(*branch) ;
531 }
532 }
533
534 // Clone branches, changes their names
535 RooAbsArg* cloneTopPdf = 0;
536 RooArgSet clonedMasterBranches("clonedMasterBranches") ;
537 clonedMasterBranches.setHashTableSize(1000) ;
538 TIterator* iter = masterBranchesToBeCloned.createIterator() ;
539 while((branch=(RooAbsArg*)iter->Next())) {
540 TString newName(branch->GetName()) ;
541 if (masterCatState) {
542 newName.Append("_") ;
543 newName.Append(masterCatState) ;
544 }
545
546 // Affix attribute with old name to clone to support name changing server redirect
547 RooAbsArg* clone = (RooAbsArg*) branch->Clone(newName.Data()) ;
548 clone->setStringAttribute("factory_tag",0) ;
549 TString nameAttrib("ORIGNAME:") ;
550 nameAttrib.Append(branch->GetName()) ;
551 clone->setAttribute(nameAttrib) ;
552
553 if (!clone->getStringAttribute("origName")) {
554 clone->setStringAttribute("origName",branch->GetName()) ;
555 }
556
557 clonedMasterBranches.add(*clone) ;
558
559 // Save pointer to clone of top-level pdf
560 if (branch==_masterPdf) cloneTopPdf=(RooAbsArg*)clone ;
561 }
562 delete iter ;
563 if (_owning) {
564 _cloneBranchList->addOwned(clonedMasterBranches) ;
565 } else {
566 _cloneBranchList->add(clonedMasterBranches) ;
567 }
568
569 // Reconnect cloned branches to each other and to cloned nodess
570 iter = clonedMasterBranches.createIterator() ;
571 while((branch=(RooAbsArg*)iter->Next())) {
572 branch->redirectServers(clonedMasterBranches,kFALSE,kTRUE) ;
573 branch->redirectServers(clonedMasterNodes,kFALSE,kTRUE) ;
574 branch->redirectServers(masterReplacementNodes,kFALSE,kTRUE) ;
575 }
576 delete iter ;
577
578 return cloneTopPdf?cloneTopPdf:_masterPdf ;
579}
580
581
582////////////////////////////////////////////////////////////////////////////////
583/// Print name of customizer
584
585void RooCustomizer::printName(ostream& os) const
586{
587 os << GetName() ;
588}
589
590
591////////////////////////////////////////////////////////////////////////////////
592/// Print title of customizer
593
594void RooCustomizer::printTitle(ostream& os) const
595{
596 os << GetTitle() ;
597}
598
599
600////////////////////////////////////////////////////////////////////////////////
601/// Print class name of customizer
602
603void RooCustomizer::printClassName(ostream& os) const
604{
605 os << IsA()->GetName() ;
606}
607
608
609////////////////////////////////////////////////////////////////////////////////
610/// Print arguments of customizer, i.e. input p.d.f and input master category (if any)
611
612void RooCustomizer::printArgs(ostream& os) const
613{
614 os << "[ masterPdf=" << _masterPdf->GetName() ;
615 if (_masterCat) {
616 os << " masterCat=" << _masterCat->GetName() ;
617 }
618 os << " ]" ;
619}
620
621
622
623////////////////////////////////////////////////////////////////////////////////
624/// Print customizer configuration details
625
626void RooCustomizer::printMultiline(ostream& os, Int_t /*content*/, Bool_t /*verbose*/, TString indent) const
627{
628 os << indent << "RooCustomizer for " << _masterPdf->GetName() << (_sterile?" (sterile)":"") << endl ;
629
630 Int_t i, nsplit = _splitArgList.GetSize() ;
631 if (nsplit>0) {
632 os << indent << " Splitting rules:" << endl ;
633 for (i=0 ; i<nsplit ; i++) {
634 os << indent << " " << _splitArgList.At(i)->GetName() << " is split by " << _splitCatList.At(i)->GetName() << endl ;
635 }
636 }
637
638 Int_t nrepl = _replaceArgList.GetSize() ;
639 if (nrepl>0) {
640 os << indent << " Replacement rules:" << endl ;
641 for (i=0 ; i<nrepl ; i++) {
642 os << indent << " " << _replaceSubList.At(i)->GetName() << " replaces " << _replaceArgList.At(i)->GetName() << endl ;
643 }
644 }
645
646 return ;
647}
648
649
650
651////////////////////////////////////////////////////////////////////////////////
652/// Install the input RooArgSet as container in which all cloned branches
653/// will be stored
654
656{
657 _cloneBranchList = &cloneBranchSet ;
659}
660
661
662
663
664////////////////////////////////////////////////////////////////////////////////
665
666std::string RooCustomizer::CustIFace::create(RooFactoryWSTool& ft, const char* typeName, const char* instanceName, std::vector<std::string> args)
667{
668 // Check number of arguments
669 if (args.size()<2) {
670 throw string(Form("RooCustomizer::CustIFace::create() ERROR: expect at least 2 arguments for EDIT: the input object and at least one $Replace() rule")) ;
671 }
672
673 if (string(typeName)!="EDIT") {
674 throw string(Form("RooCustomizer::CustIFace::create() ERROR: unknown type requested: %s",typeName)) ;
675 }
676
677 // Check that first arg exists as RooAbsArg
678 RooAbsArg* arg = ft.ws().arg(args[0].c_str()) ;
679 if (!arg) {
680 throw string(Form("RooCustomizer::CustIFace::create() ERROR: input RooAbsArg %s does not exist",args[0].c_str())) ;
681 }
682
683 // If name of new object is same as original, execute in sterile mode (i.e no suffixes attached), and rename original nodes in workspace upon import
684 if (args[0]==instanceName) {
685 instanceName=0 ;
686 }
687
688 // Create a customizer
689 RooCustomizer cust(*arg,instanceName) ;
690
691 for (unsigned int i=1 ; i<args.size() ; i++) {
692 char buf[1024] ;
693 strlcpy(buf,args[i].c_str(),1024) ;
694 char* sep = strchr(buf,'=') ;
695 if (!sep) {
696 throw string(Form("RooCustomizer::CustIFace::create() ERROR: unknown argument: %s, expect form orig=subst",args[i].c_str())) ;
697 }
698 *sep = 0 ;
699 RooAbsArg* orig = ft.ws().arg(buf) ;
700 RooAbsArg* subst(0) ;
701 if (string(sep+1).find("$REMOVE")==0) {
702
703 // Create a removal dummy ;
705
706 // If removal instructed was annotated with target node, encode these in removal dummy
707 char* sep2 = strchr(sep+1,'(') ;
708 if (sep2) {
709 char buf2[1024] ;
710 strlcpy(buf2,sep2+1,1024) ;
711 char* saveptr ;
712 char* tok = R__STRTOK_R(buf2,",)",&saveptr) ;
713 while(tok) {
714 //cout << "$REMOVE is restricted to " << tok << endl ;
715 subst->setAttribute(Form("REMOVE_FROM_%s",tok)) ;
716 tok = R__STRTOK_R(0,",)",&saveptr) ;
717 }
718 } else {
719 // Otherwise mark as universal removal node
720 subst->setAttribute("REMOVE_ALL") ;
721 }
722
723 } else {
724 subst = ft.ws().arg(sep+1) ;
725 }
726// if (!orig) {
727// throw string(Form("RooCustomizer::CustIFace::create() ERROR: $Replace() input RooAbsArg %s does not exist",buf)) ;
728// }
729// if (!subst) {
730// throw string(Form("RooCustomizer::CustIFace::create() ERROR: $Replace() replacement RooAbsArg %s does not exist",sep+1)) ;
731// }
732 if (orig && subst) {
733 cust.replaceArg(*orig,*subst) ;
734 } else {
735 oocoutW((TObject*)0,ObjectHandling) << "RooCustomizer::CustIFace::create() WARNING: input or replacement of a replacement operation not found, operation ignored"<< endl ;
736 }
737 }
738
739 // Build the desired edited object
740 RooAbsArg* targ = cust.build(kFALSE) ;
741 if (!targ) {
742 throw string(Form("RooCustomizer::CustIFace::create() ERROR in customizer build, object %snot created",instanceName)) ;
743 }
744
745 // Import the object into the workspace
746 if (instanceName) {
747 // Set the desired name of the top level node
748 targ->SetName(instanceName) ;
750 } else {
752 }
753
754 return string(instanceName?instanceName:targ->GetName()) ;
755}
static Int_t dummy
static Int_t init()
#define coutI(a)
Definition: RooMsgService.h:31
#define oocoutW(o, a)
Definition: RooMsgService.h:46
#define coutW(a)
Definition: RooMsgService.h:33
#define coutE(a)
Definition: RooMsgService.h:34
int Int_t
Definition: RtypesCore.h:41
const Bool_t kFALSE
Definition: RtypesCore.h:88
bool Bool_t
Definition: RtypesCore.h:59
const Bool_t kTRUE
Definition: RtypesCore.h:87
#define ClassImp(name)
Definition: Rtypes.h:365
char * R__STRTOK_R(char *str, const char *delim, char **saveptr)
Definition: Rtypes.h:486
static void indent(ostringstream &buf, int indent_level)
char name[80]
Definition: TGX11.cxx:109
char * Form(const char *fmt,...)
typedef void((*Func_t)())
RooAbsArg is the common abstract base class for objects that represent a value (of arbitrary type) an...
Definition: RooAbsArg.h:70
Bool_t redirectServers(const RooAbsCollection &newServerList, Bool_t mustReplaceAll=kFALSE, Bool_t nameChange=kFALSE, Bool_t isRecursionStep=kFALSE)
Substitute our servers with those listed in newSet.
Definition: RooAbsArg.cxx:906
Bool_t dependsOn(const RooAbsCollection &serverList, const RooAbsArg *ignoreArg=0, Bool_t valueOnly=kFALSE) const
Test whether we depend on (ie, are served by) any object in the specified collection.
Definition: RooAbsArg.cxx:729
void setStringAttribute(const Text_t *key, const Text_t *value)
Associate string 'value' to this object under key 'key'.
Definition: RooAbsArg.cxx:288
void leafNodeServerList(RooAbsCollection *list, const RooAbsArg *arg=0, Bool_t recurseNonDerived=kFALSE) const
Fill supplied list with all leaf nodes of the arg tree, starting with ourself as top node.
Definition: RooAbsArg.cxx:474
virtual TObject * Clone(const char *newname=0) const
Make a clone of an object using the Streamer facility.
Definition: RooAbsArg.h:82
const Text_t * getStringAttribute(const Text_t *key) const
Get string attribute mapped under key 'key'.
Definition: RooAbsArg.cxx:301
void setAttribute(const Text_t *name, Bool_t value=kTRUE)
Set (default) or clear a named boolean attribute of this object.
Definition: RooAbsArg.cxx:256
virtual Bool_t isDerived() const
Does value or shape of this arg depend on any other arg?
Definition: RooAbsArg.h:90
Bool_t addOwnedComponents(const RooArgSet &comps)
Take ownership of the contents of 'comps'.
Definition: RooAbsArg.cxx:2232
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.
Definition: RooAbsArg.cxx:485
void SetName(const char *name)
Set the name of the TNamed.
Definition: RooAbsArg.cxx:2341
RooAbsCategoryLValue is the common abstract base class for objects that represent a discrete value th...
virtual Bool_t setLabel(const char *label, Bool_t printError=kTRUE)=0
RooAbsCategory is the common abstract base class for objects that represent a discrete value with a f...
virtual const char * getLabel() const
Return label string of current state.
void setHashTableSize(Int_t)
Int_t getSize() const
TIterator * createIterator(Bool_t dir=kIterForward) const R__SUGGEST_ALTERNATIVE("begin()
TIterator-style iteration over contained elements.
virtual Bool_t remove(const RooAbsArg &var, Bool_t silent=kFALSE, Bool_t matchByNameOnly=kFALSE)
Remove the specified argument from our list.
RooAbsArg * find(const char *name) const
Find object with given name in list.
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Definition: RooArgSet.h:28
virtual Bool_t addOwned(const RooAbsCollection &col, Bool_t silent=kFALSE)
Add a collection of arguments to this collection by calling addOwned() for each element in the source...
Definition: RooArgSet.h:92
virtual Bool_t add(const RooAbsCollection &col, Bool_t silent=kFALSE)
Add a collection of arguments to this collection by calling add() for each element in the source coll...
Definition: RooArgSet.h:88
std::string create(RooFactoryWSTool &ft, const char *typeName, const char *instanceName, std::vector< std::string > args)
RooCustomizer is a factory class to produce clones of a prototype composite PDF object with the same ...
Definition: RooCustomizer.h:32
TList _splitArgList
Definition: RooCustomizer.h:94
void splitArg(const RooAbsArg &arg, const RooAbsCategory &splitCat)
Split all argument 'arg' into individualized clones for each defined state of 'splitCat'.
void setCloneBranchSet(RooArgSet &cloneBranchSet)
Install the input RooArgSet as container in which all cloned branches will be stored.
RooArgSet * _cloneNodeListAll
void replaceArg(const RooAbsArg &orig, const RooAbsArg &subst)
Replace any occurence of arg 'orig' with arg 'subst'.
RooAbsArg * _masterPdf
TList _replaceSubList
Definition: RooCustomizer.h:98
const RooArgSet & cloneBranchList() const
Definition: RooCustomizer.h:52
RooArgSet * _cloneBranchList
virtual void printName(std::ostream &os) const
Print name of customizer.
TIterator * _masterLeafListIter
virtual void printTitle(std::ostream &os) const
Print title of customizer.
RooCustomizer(const RooAbsArg &pdf, const RooAbsCategoryLValue &masterCat, RooArgSet &splitLeafListOwned, RooArgSet *splitLeafListAll=0)
Constructor with a prototype and masterCat index category.
virtual void printMultiline(std::ostream &os, Int_t content, Bool_t verbose=kFALSE, TString indent="") const
Print customizer configuration details.
RooArgSet _masterBranchList
RooAbsArg * doBuild(const char *masterCatState, Bool_t verbose)
Back-end implementation of the p.d.f building functionality.
RooArgSet _masterLeafList
virtual void printClassName(std::ostream &os) const
Print class name of customizer.
virtual ~RooCustomizer()
Destructor.
RooArgSet _internalCloneBranchList
void initialize()
Initialize the customizer.
TIterator * _masterBranchListIter
RooAbsCategoryLValue * _masterCat
void splitArgs(const RooArgSet &argSet, const RooAbsCategory &splitCat)
Split all arguments in 'set' into individualized clones for each defined state of 'splitCat'.
RooAbsArg * build(const char *masterCatState, Bool_t verbose=kFALSE)
Build a clone of the prototype executing all registered 'replace' rules and 'split' rules for the mas...
TList _replaceArgList
Definition: RooCustomizer.h:97
TList _splitCatList
Definition: RooCustomizer.h:95
RooArgSet * _cloneNodeListOwned
virtual void printArgs(std::ostream &os) const
Print arguments of customizer, i.e. input p.d.f and input master category (if any)
RooFactoryWSTool is a clase like TTree::MakeClass() that generates skeleton code for RooAbsPdf and Ro...
RooWorkspace & ws()
static void registerSpecial(const char *typeName, RooFactoryWSTool::IFace *iface)
Register foreign special objects in factory.
static RooConstVar & removalDummy()
Create a dummy node used in node-removal operations.
RooAbsArg * arg(const char *name) const
Return RooAbsArg with given name. A null pointer is returned if none is found.
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.
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
Definition: TCollection.h:182
Iterator abstract base class.
Definition: TIterator.h:30
virtual void Reset()=0
virtual TObject * Next()=0
virtual void Add(TObject *obj)
Definition: TList.h:87
virtual TObject * FindObject(const char *name) const
Find an object in this list using its name.
Definition: TList.cxx:575
virtual TObject * At(Int_t idx) const
Returns the object at position idx. Returns 0 if idx is out of range.
Definition: TList.cxx:354
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 const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:48
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
Mother of all ROOT objects.
Definition: TObject.h:37
virtual const char * GetName() const
Returns name of object.
Definition: TObject.cxx:357
virtual Int_t IndexOf(const TObject *obj) const
Return index of object in collection.
Basic string class.
Definition: TString.h:131
Ssiz_t Length() const
Definition: TString.h:405
const char * Data() const
Definition: TString.h:364
TString & Append(const char *cs)
Definition: TString.h:559
std::string GetName(const std::string &scope_name)
Definition: Cppyy.cxx:146
RooCmdArg NoRecursion(Bool_t flag=kTRUE)
RooCmdArg RenameConflictNodes(const char *suffix, Bool_t renameOrigNodes=kFALSE)
@ InputArguments
Definition: RooGlobalFunc.h:58
@ ObjectHandling
Definition: RooGlobalFunc.h:58
RooCmdArg Silence(Bool_t flag=kTRUE)