Logo ROOT  
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  * - replaceArg(leaf_arg, repl_arg):
27  * Replaces each occurence of leaf_arg with repl_arg in the composite pdf.
28  *
29  * - splitArg(split_arg):
30  * Build multiple clones of the same prototype. Each
31  * occurrence of split_arg is replaced 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: Change the decay constant of an exponential for each run
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.splitArg(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  * ### Reuse nodes to customise a different PDF
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  * ### Customising with pre-defined leafs
106  * If leaf nodes are provided in the sets, the customiser will use them. This is a complete
107  * example that customises the `yield` parameter, and splits (automatically clones) the
108  * mean of the Gaussian. This is a short version of the tutorial rf514_RooCustomizer.C.
109  * ```
110  * RooRealVar E("Energy","Energy",0,3000);
111  *
112  * RooRealVar meanG("meanG","meanG", peak[1]);
113  * RooRealVar fwhm("fwhm", "fwhm", 5/(2*Sqrt(2*Log(2))));
114  * RooGaussian gauss("gauss", "gauss", E, meanG, fwhm);
115  *
116  * RooPolynomial linear("linear","linear",E,RooArgList());
117  *
118  * RooRealVar yieldSig("yieldSig", "yieldSig", 1, 0, 1.E4);
119  * RooRealVar yieldBkg("yieldBkg", "yieldBkg", 1, 0, 1.E4);
120  *
121  * RooAddPdf model("model","model",
122  * RooArgList(gauss,linear),
123  * RooArgList(yieldSig, yieldBkg));
124  *
125  * RooCategory sample("sample","sample");
126  * sample.defineType("BBG1m2T");
127  * sample.defineType("BBG2m2T");
128  *
129  *
130  * RooArgSet customisedLeafs;
131  * RooArgSet allLeafs;
132  *
133  * RooRealVar mass("M", "M", 1, 0, 12000);
134  * RooFormulaVar yield1("yieldSig_BBG1m2T","sigy1","M/3.360779",mass);
135  * RooFormulaVar yield2("yieldSig_BBG2m2T","sigy2","M/2",mass);
136  * allLeafs.add(yield1);
137  * allLeafs.add(yield2);
138  *
139  *
140  * RooCustomizer cust(model, sample, customisedLeafs, &allLeafs);
141  * cust.splitArg(yieldSig, sample);
142  * cust.splitArg(meanG, sample);
143  *
144  * auto pdf1 = cust.build("BBG1m2T");
145  * auto pdf2 = cust.build("BBG2m2T");
146  * ```
147 */
148 
149 
150 #include "RooCustomizer.h"
151 
152 #include "RooAbsCategoryLValue.h"
153 #include "RooAbsCategory.h"
154 #include "RooAbsArg.h"
155 #include "RooAbsPdf.h"
156 #include "RooArgSet.h"
157 #include "RooArgList.h"
158 #include "RooMsgService.h"
159 #include "RooHelpers.h"
160 
161 #include <iostream>
162 #include "strtok.h"
163 #include "strlcpy.h"
164 
165 #include "RooWorkspace.h"
166 #include "RooGlobalFunc.h"
167 #include "RooConstVar.h"
168 #include "RooRealConstant.h"
169 
170 
171 #ifndef _WIN32
172 #include <strings.h>
173 #endif
174 
175 
176 using namespace std;
177 
179 ;
180 
181 namespace {
182 
183 static Int_t init();
184 
185 Int_t dummy = init() ;
186 
187 static Int_t init()
188 {
190  RooFactoryWSTool::registerSpecial("EDIT",iface) ;
191  (void) dummy;
192  return 0 ;
193 }
194 
195 }
196 
197 ////////////////////////////////////////////////////////////////////////////////
198 /// Constructor with a prototype and masterCat index category.
199 /// Customizers created by this constructor offer both the
200 /// replaceArg() and splitArg() functionality.
201 /// \param[in] pdf Proto PDF to be customised.
202 /// \param[in] masterCat Category to be used for splitting.
203 /// \param[in,out] splitLeafs All nodes created in
204 /// the customisation process are added to this set.
205 /// The user can provide nodes that are *taken*
206 /// from the set if they have a name that matches `<parameterNameToBeReplaced>_<category>`.
207 /// \note The set needs to own its contents if they are user-provided.
208 /// Use *e.g.*
209 /// ```
210 /// RooArgSet customisedLeafs;
211 /// auto yield1 = new RooFormulaVar("yieldSig_BBG1m2T","sigy1","M/3.360779",mass);
212 /// customisedLeafs.addOwned(*yield1);
213 /// ```
214 /// \param[in,out] splitLeafsAll All leafs that are used when customising are collected here.
215 /// If this set already contains leaves, they will be used for customising if the names match
216 /// as above.
217 ///
218 
220  RooArgSet& splitLeafs, RooArgSet* splitLeafsAll) :
221  TNamed(pdf.GetName(),pdf.GetTitle()),
222  _sterile(kFALSE),
223  _owning(kTRUE),
224  _masterPdf((RooAbsArg*)&pdf),
225  _masterCat((RooAbsCategoryLValue*)&masterCat),
226  _masterBranchList("masterBranchList"),
227  _masterLeafList("masterLeafList"),
228  _internalCloneBranchList("cloneBranchList"),
229  _cloneNodeListAll(splitLeafsAll),
230  _cloneNodeListOwned(&splitLeafs)
231 {
233 
234  initialize() ;
235 }
236 
237 
238 
239 ////////////////////////////////////////////////////////////////////////////////
240 /// Sterile Constructor. Customizers created by this constructor
241 /// offer only the replace() method. The supplied 'name' is used as
242 /// suffix for any cloned branch nodes
243 
244 RooCustomizer::RooCustomizer(const RooAbsArg& pdf, const char* name) :
245  TNamed(pdf.GetName(),pdf.GetTitle()),
246  _sterile(kTRUE),
247  _owning(kFALSE),
248  _name(name),
249  _masterPdf((RooAbsArg*)&pdf),
250  _masterCat(0),
251  _masterBranchList("masterBranchList"),
252  _masterLeafList("masterLeafList"),
253  _internalCloneBranchList("cloneBranchList"),
254  _cloneNodeListAll(0),
255  _cloneNodeListOwned(0)
256 {
258 
259  initialize() ;
260 }
261 
262 
263 
264 
265 ////////////////////////////////////////////////////////////////////////////////
266 /// Initialize the customizer
267 
269 {
272 }
273 
274 
275 
276 ////////////////////////////////////////////////////////////////////////////////
277 /// Destructor
278 
280 {
281 
282 }
283 
284 
285 
286 
287 ////////////////////////////////////////////////////////////////////////////////
288 /// Split all arguments in 'set' into individualized clones for each
289 /// defined state of 'splitCat'. The 'splitCats' category must be
290 /// subset of or equal to the master category supplied in the
291 /// customizer constructor.
292 ///
293 /// Splitting is only available on customizers created with a master index category
294 
295 void RooCustomizer::splitArgs(const RooArgSet& set, const RooAbsCategory& splitCat)
296 {
297  if (_sterile) {
298  coutE(InputArguments) << "RooCustomizer::splitArgs(" << _name
299  << ") ERROR cannot set spitting rules on this sterile customizer" << endl ;
300  return ;
301  }
302 
303  for (auto arg : set) {
304  splitArg(*arg,splitCat) ;
305  }
306 }
307 
308 
309 
310 ////////////////////////////////////////////////////////////////////////////////
311 /// Split all argument 'arg' into individualized clones for each
312 /// defined state of 'splitCat'. The 'splitCats' category must be
313 /// subset of or equal to the master category supplied in the
314 /// customizer constructor.
315 ///
316 /// Splitting is only available on customizers created with a master index category
317 
318 void RooCustomizer::splitArg(const RooAbsArg& arg, const RooAbsCategory& splitCat)
319 {
320  if (_splitArgList.FindObject(arg.GetName())) {
321  coutE(InputArguments) << "RooCustomizer(" << GetName() << ") ERROR: multiple splitting rules defined for "
322  << arg.GetName() << " only using first rule" << endl ;
323  return ;
324  }
325 
326  if (_sterile) {
327  coutE(InputArguments) << "RooCustomizer::splitArg(" << _name
328  << ") ERROR cannot set spitting rules on this sterile customizer" << endl ;
329  return ;
330  }
331 
332  _splitArgList.Add((RooAbsArg*)&arg) ;
333  _splitCatList.Add((RooAbsCategory*)&splitCat) ;
334 }
335 
336 
337 
338 ////////////////////////////////////////////////////////////////////////////////
339 /// Replace any occurence of arg 'orig' with arg 'subst'
340 
341 void RooCustomizer::replaceArg(const RooAbsArg& orig, const RooAbsArg& subst)
342 {
343  if (_replaceArgList.FindObject(orig.GetName())) {
344  coutE(InputArguments) << "RooCustomizer(" << GetName() << ") ERROR: multiple replacement rules defined for "
345  << orig.GetName() << " only using first rule" << endl ;
346  return ;
347  }
348 
349  _replaceArgList.Add((RooAbsArg*)&orig) ;
350  _replaceSubList.Add((RooAbsArg*)&subst) ;
351 }
352 
353 
354 
355 ////////////////////////////////////////////////////////////////////////////////
356 /// Build a clone of the prototype executing all registered 'replace' rules.
357 /// If verbose is set, a message is printed for each leaf or branch node
358 /// modification. The returned head node owns all cloned branch nodes
359 /// that were created in the cloning process.
360 
362 {
363  // Execute build
364  RooAbsArg* ret = doBuild(_name.Length()>0?_name.Data():0,verbose) ;
365 
366  // Make root object own all cloned nodes
367 
368  // First make list of all objects that were created
369  RooArgSet allOwned ;
370  if (_cloneNodeListOwned) {
371  allOwned.add(*_cloneNodeListOwned) ;
372  }
373  allOwned.add(*_cloneBranchList) ;
374 
375  // Remove head node from list
376  allOwned.remove(*ret) ;
377 
378  // If list with owned objects is not empty, assign
379  // head node as owner
380  if (allOwned.getSize()>0) {
381  ret->addOwnedComponents(allOwned) ;
382  }
383 
384  return ret ;
385 }
386 
387 
388 
389 ////////////////////////////////////////////////////////////////////////////////
390 /// Build a clone of the prototype executing all registered 'replace'
391 /// rules and 'split' rules for the masterCat state named
392 /// 'masterCatState'. If verbose is set a message is printed for
393 /// each leaf or branch node modification. The returned composite arg
394 /// is owned by the customizer. This function cannot be called on
395 /// customizer build with the sterile constructor.
396 
397 RooAbsArg* RooCustomizer::build(const char* masterCatState, Bool_t verbose)
398 {
399  if (_sterile) {
400  coutE(InputArguments) << "RooCustomizer::build(" << _name
401  << ") ERROR cannot use leaf spitting build() on this sterile customizer" << endl ;
402  return 0 ;
403  }
404 
405  // Set masterCat to given state
406  if (_masterCat->setLabel(masterCatState)) {
407  coutE(InputArguments) << "RooCustomizer::build(" << _masterPdf->GetName() << "): ERROR label '" << masterCatState
408  << "' not defined for master splitting category " << _masterCat->GetName() << endl ;
409  return 0 ;
410  }
411 
412  return doBuild(masterCatState,verbose) ;
413 }
414 
415 
416 
417 ////////////////////////////////////////////////////////////////////////////////
418 /// Back-end implementation of the p.d.f building functionality
419 
420 RooAbsArg* RooCustomizer::doBuild(const char* masterCatState, Bool_t verbose)
421 {
422  // Find nodes that must be split according to provided description, Clone nodes, change their names
423  RooArgSet masterNodesToBeSplit("masterNodesToBeSplit") ;
424  RooArgSet masterNodesToBeReplaced("masterNodesToBeReplaced") ;
425  RooArgSet masterReplacementNodes("masterReplacementNodes") ;
426  RooArgSet clonedMasterNodes("clonedMasterNodes") ;
427 
428 
429  RooArgSet nodeList(_masterLeafList) ;
430  nodeList.add(_masterBranchList) ;
431 
432  // cout << "loop over " << nodeList.getSize() << " nodes" << endl ;
433  for (auto node : nodeList) {
434  RooAbsArg* theSplitArg = !_sterile?(RooAbsArg*) _splitArgList.FindObject(node->GetName()):0 ;
435  if (theSplitArg) {
436  RooAbsCategory* splitCat = (RooAbsCategory*) _splitCatList.At(_splitArgList.IndexOf(theSplitArg)) ;
437  if (verbose) {
438  coutI(ObjectHandling) << "RooCustomizer::build(" << _masterPdf->GetName()
439  << "): tree node " << node->GetName() << " is split by category " << splitCat->GetName() << endl ;
440  }
441 
442  TString newName(node->GetName()) ;
443  if (masterCatState) {
444  newName.Append("_") ;
445  newName.Append(splitCat->getCurrentLabel()) ;
446  }
447 
448  // Check if this node instance already exists
449  RooAbsArg* specNode = _cloneNodeListAll ? _cloneNodeListAll->find(newName) : _cloneNodeListOwned->find(newName) ;
450  if (specNode) {
451 
452  // Copy instance to one-time use list for this build
453  clonedMasterNodes.add(*specNode) ;
454  if (verbose) {
455  coutI(ObjectHandling) << "RooCustomizer::build(" << _masterPdf->GetName()
456  << ") Adding existing node specialization " << newName << " to clonedMasterNodes" << endl ;
457  }
458 
459  // Affix attribute with old name to clone to support name changing server redirect
460  TString nameAttrib("ORIGNAME:") ;
461  nameAttrib.Append(node->GetName()) ;
462  specNode->setAttribute(nameAttrib) ;
463 
464  if (!specNode->getStringAttribute("origName")) {
465  specNode->setStringAttribute("origName",node->GetName()) ;
466  }
467 
468 
469 
470  } else {
471 
472  if (node->isDerived()) {
473  coutW(ObjectHandling) << "RooCustomizer::build(" << _masterPdf->GetName()
474  << "): WARNING: branch node " << node->GetName() << " is split but has no pre-defined specializations" << endl ;
475  }
476 
477  TString newTitle(node->GetTitle()) ;
478  newTitle.Append(" (") ;
479  newTitle.Append(splitCat->getCurrentLabel()) ;
480  newTitle.Append(")") ;
481 
482  // Create a new clone
483  RooAbsArg* clone = (RooAbsArg*) node->Clone(newName.Data()) ;
484  clone->setStringAttribute("factory_tag",0) ;
485  clone->SetTitle(newTitle) ;
486 
487  // Affix attribute with old name to clone to support name changing server redirect
488  TString nameAttrib("ORIGNAME:") ;
489  nameAttrib.Append(node->GetName()) ;
490  clone->setAttribute(nameAttrib) ;
491 
492  if (!clone->getStringAttribute("origName")) {
493  clone->setStringAttribute("origName",node->GetName()) ;
494  }
495 
496  // Add to one-time use list and life-time use list
497  clonedMasterNodes.add(*clone) ;
498  if (_owning) {
499  _cloneNodeListOwned->addOwned(*clone) ;
500  } else {
501  _cloneNodeListOwned->add(*clone) ;
502  }
503  if (_cloneNodeListAll) {
504  _cloneNodeListAll->add(*clone) ;
505  }
506  }
507  masterNodesToBeSplit.add(*node) ;
508  }
509 
510  RooAbsArg* ReplaceArg = (RooAbsArg*) _replaceArgList.FindObject(node->GetName()) ;
511  if (ReplaceArg) {
512  RooAbsArg* substArg = (RooAbsArg*) _replaceSubList.At(_replaceArgList.IndexOf(ReplaceArg)) ;
513  if (verbose) {
514  coutI(ObjectHandling) << "RooCustomizer::build(" << _masterPdf->GetName()
515  << "): tree node " << node->GetName() << " will be replaced by " << substArg->GetName() << endl ;
516  }
517 
518  // Affix attribute with old name to support name changing server redirect
519  TString nameAttrib("ORIGNAME:") ;
520  nameAttrib.Append(node->GetName()) ;
521  substArg->setAttribute(nameAttrib) ;
522 
523  // Add to list
524  masterNodesToBeReplaced.add(*node) ;
525  masterReplacementNodes.add(*substArg) ;
526  }
527  }
528 
529  // Find branches that are affected by splitting and must be cloned
530  RooArgSet masterBranchesToBeCloned("masterBranchesToBeCloned") ;
531  for (auto branch : _masterBranchList) {
532 
533  // If branch is split itself, don't handle here
534  if (masterNodesToBeSplit.find(branch->GetName())) {
535  if (verbose) {
536  coutI(ObjectHandling) << "RooCustomizer::build(" << _masterPdf->GetName() << ") Branch node " << branch->GetName() << " is already split" << endl ;
537  }
538  continue ;
539  }
540  if (masterNodesToBeReplaced.find(branch->GetName())) {
541  if (verbose) {
542  coutI(ObjectHandling) << "RooCustomizer::build(" << _masterPdf->GetName() << ") Branch node " << branch->GetName() << " is already replaced" << endl ;
543  }
544  continue ;
545  }
546 
547  if (branch->dependsOn(masterNodesToBeSplit)) {
548  if (verbose) {
549  coutI(ObjectHandling) << "RooCustomizer::build(" << _masterPdf->GetName() << ") Branch node "
550  << branch->IsA()->GetName() << "::" << branch->GetName() << " cloned: depends on a split parameter" << endl ;
551  }
552  masterBranchesToBeCloned.add(*branch) ;
553  } else if (branch->dependsOn(masterNodesToBeReplaced)) {
554  if (verbose) {
555  coutI(ObjectHandling) << "RooCustomizer::build(" << _masterPdf->GetName() << ") Branch node "
556  << branch->IsA()->GetName() << "::" << branch->GetName() << " cloned: depends on a replaced parameter" << endl ;
557  }
558  masterBranchesToBeCloned.add(*branch) ;
559  }
560  }
561 
562  // Clone branches, changes their names
563  RooAbsArg* cloneTopPdf = 0;
564  RooArgSet clonedMasterBranches("clonedMasterBranches") ;
565 
566  for (auto branch : masterBranchesToBeCloned) {
567  TString newName(branch->GetName()) ;
568  if (masterCatState) {
569  newName.Append("_") ;
570  newName.Append(masterCatState) ;
571  }
572 
573  // Affix attribute with old name to clone to support name changing server redirect
574  RooAbsArg* clone = (RooAbsArg*) branch->Clone(newName.Data()) ;
575  clone->setStringAttribute("factory_tag",0) ;
576  TString nameAttrib("ORIGNAME:") ;
577  nameAttrib.Append(branch->GetName()) ;
578  clone->setAttribute(nameAttrib) ;
579 
580  if (!clone->getStringAttribute("origName")) {
581  clone->setStringAttribute("origName",branch->GetName()) ;
582  }
583 
584  clonedMasterBranches.add(*clone) ;
585 
586  // Save pointer to clone of top-level pdf
587  if (branch==_masterPdf) cloneTopPdf=(RooAbsArg*)clone ;
588  }
589 
590  if (_owning) {
591  _cloneBranchList->addOwned(clonedMasterBranches) ;
592  } else {
593  _cloneBranchList->add(clonedMasterBranches) ;
594  }
595 
596  // Reconnect cloned branches to each other and to cloned nodess
597  for (auto branch : clonedMasterBranches) {
598  branch->redirectServers(clonedMasterBranches,kFALSE,kTRUE) ;
599  branch->redirectServers(clonedMasterNodes,kFALSE,kTRUE) ;
600  branch->redirectServers(masterReplacementNodes,kFALSE,kTRUE) ;
601  }
602 
603  return cloneTopPdf ? cloneTopPdf : _masterPdf ;
604 }
605 
606 
607 ////////////////////////////////////////////////////////////////////////////////
608 /// Print name of customizer
609 
610 void RooCustomizer::printName(ostream& os) const
611 {
612  os << GetName() ;
613 }
614 
615 
616 ////////////////////////////////////////////////////////////////////////////////
617 /// Print title of customizer
618 
619 void RooCustomizer::printTitle(ostream& os) const
620 {
621  os << GetTitle() ;
622 }
623 
624 
625 ////////////////////////////////////////////////////////////////////////////////
626 /// Print class name of customizer
627 
628 void RooCustomizer::printClassName(ostream& os) const
629 {
630  os << IsA()->GetName() ;
631 }
632 
633 
634 ////////////////////////////////////////////////////////////////////////////////
635 /// Print arguments of customizer, i.e. input p.d.f and input master category (if any)
636 
637 void RooCustomizer::printArgs(ostream& os) const
638 {
639  os << "[ masterPdf=" << _masterPdf->GetName() ;
640  if (_masterCat) {
641  os << " masterCat=" << _masterCat->GetName() ;
642  }
643  os << " ]" ;
644 }
645 
646 
647 
648 ////////////////////////////////////////////////////////////////////////////////
649 /// Print customizer configuration details
650 
651 void RooCustomizer::printMultiline(ostream& os, Int_t /*content*/, Bool_t /*verbose*/, TString indent) const
652 {
653  os << indent << "RooCustomizer for " << _masterPdf->GetName() << (_sterile?" (sterile)":"") << endl ;
654 
655  Int_t i, nsplit = _splitArgList.GetSize() ;
656  if (nsplit>0) {
657  os << indent << " Splitting rules:" << endl ;
658  for (i=0 ; i<nsplit ; i++) {
659  os << indent << " " << _splitArgList.At(i)->GetName() << " is split by " << _splitCatList.At(i)->GetName() << endl ;
660  }
661  }
662 
663  Int_t nrepl = _replaceArgList.GetSize() ;
664  if (nrepl>0) {
665  os << indent << " Replacement rules:" << endl ;
666  for (i=0 ; i<nrepl ; i++) {
667  os << indent << " " << _replaceSubList.At(i)->GetName() << " replaces " << _replaceArgList.At(i)->GetName() << endl ;
668  }
669  }
670 
671  return ;
672 }
673 
674 
675 
676 ////////////////////////////////////////////////////////////////////////////////
677 /// Install the input RooArgSet as container in which all cloned branches
678 /// will be stored
679 
681 {
682  _cloneBranchList = &cloneBranchSet ;
684 }
685 
686 
687 
688 
689 ////////////////////////////////////////////////////////////////////////////////
690 
691 std::string RooCustomizer::CustIFace::create(RooFactoryWSTool& ft, const char* typeName, const char* instanceName, std::vector<std::string> args)
692 {
693  // Check number of arguments
694  if (args.size()<2) {
695  throw string(Form("RooCustomizer::CustIFace::create() ERROR: expect at least 2 arguments for EDIT: the input object and at least one $Replace() rule")) ;
696  }
697 
698  if (string(typeName)!="EDIT") {
699  throw string(Form("RooCustomizer::CustIFace::create() ERROR: unknown type requested: %s",typeName)) ;
700  }
701 
702  // Check that first arg exists as RooAbsArg
703  RooAbsArg* arg = ft.ws().arg(args[0].c_str()) ;
704  if (!arg) {
705  throw string(Form("RooCustomizer::CustIFace::create() ERROR: input RooAbsArg %s does not exist",args[0].c_str())) ;
706  }
707 
708  // 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
709  if (args[0]==instanceName) {
710  instanceName=0 ;
711  }
712 
713  // Create a customizer
714  RooCustomizer cust(*arg,instanceName) ;
715 
716  for (unsigned int i=1 ; i<args.size() ; i++) {
717  char buf[1024] ;
718  strlcpy(buf,args[i].c_str(),1024) ;
719  char* sep = strchr(buf,'=') ;
720  if (!sep) {
721  throw string(Form("RooCustomizer::CustIFace::create() ERROR: unknown argument: %s, expect form orig=subst",args[i].c_str())) ;
722  }
723  *sep = 0 ;
724  RooAbsArg* orig = ft.ws().arg(buf) ;
725  RooAbsArg* subst(0) ;
726  if (string(sep+1).find("$REMOVE")==0) {
727 
728  // Create a removal dummy ;
729  subst = &RooRealConstant::removalDummy() ;
730 
731  // If removal instructed was annotated with target node, encode these in removal dummy
732  char* sep2 = strchr(sep+1,'(') ;
733  if (sep2) {
734  char buf2[1024] ;
735  strlcpy(buf2,sep2+1,1024) ;
736  char* saveptr ;
737  char* tok = R__STRTOK_R(buf2,",)",&saveptr) ;
738  while(tok) {
739  //cout << "$REMOVE is restricted to " << tok << endl ;
740  subst->setAttribute(Form("REMOVE_FROM_%s",tok)) ;
741  tok = R__STRTOK_R(0,",)",&saveptr) ;
742  }
743  } else {
744  // Otherwise mark as universal removal node
745  subst->setAttribute("REMOVE_ALL") ;
746  }
747 
748  } else {
749  subst = ft.ws().arg(sep+1) ;
750  }
751 // if (!orig) {
752 // throw string(Form("RooCustomizer::CustIFace::create() ERROR: $Replace() input RooAbsArg %s does not exist",buf)) ;
753 // }
754 // if (!subst) {
755 // throw string(Form("RooCustomizer::CustIFace::create() ERROR: $Replace() replacement RooAbsArg %s does not exist",sep+1)) ;
756 // }
757  if (orig && subst) {
758  cust.replaceArg(*orig,*subst) ;
759  } else {
760  oocoutW((TObject*)0,ObjectHandling) << "RooCustomizer::CustIFace::create() WARNING: input or replacement of a replacement operation not found, operation ignored"<< endl ;
761  }
762  }
763 
764  // Build the desired edited object
765  RooAbsArg* targ = cust.build(kFALSE) ;
766  if (!targ) {
767  throw string(Form("RooCustomizer::CustIFace::create() ERROR in customizer build, object %snot created",instanceName)) ;
768  }
769 
770  // Import the object into the workspace
771  if (instanceName) {
772  // Set the desired name of the top level node
773  targ->SetName(instanceName) ;
774  // Now import everything. What we didn't touch gets recycled, everything else was cloned here:
776  } else {
778  }
779 
780  return string(instanceName?instanceName:targ->GetName()) ;
781 }
RooAbsArg::Clone
virtual TObject * Clone(const char *newname=0) const
Make a clone of an object using the Streamer facility.
Definition: RooAbsArg.h:84
RooFit::RenameConflictNodes
RooCmdArg RenameConflictNodes(const char *suffix, Bool_t renameOrigNodes=kFALSE)
Definition: RooGlobalFunc.cxx:350
RooCustomizer::_masterPdf
RooAbsArg * _masterPdf
Definition: RooCustomizer.h:104
RooCustomizer::CustIFace::create
std::string create(RooFactoryWSTool &ft, const char *typeName, const char *instanceName, std::vector< std::string > args)
Definition: RooCustomizer.cxx:691
RooWorkspace.h
RooHelpers.h
RooCustomizer::doBuild
RooAbsArg * doBuild(const char *masterCatState, Bool_t verbose)
Back-end implementation of the p.d.f building functionality.
Definition: RooCustomizer.cxx:420
kTRUE
const Bool_t kTRUE
Definition: RtypesCore.h:100
RooCustomizer::_masterLeafList
RooArgSet _masterLeafList
Definition: RooCustomizer.h:108
RooCustomizer::printClassName
virtual void printClassName(std::ostream &os) const
Print class name of customizer.
Definition: RooCustomizer.cxx:628
RooMsgService.h
RooCustomizer::setCloneBranchSet
void setCloneBranchSet(RooArgSet &cloneBranchSet)
Install the input RooArgSet as container in which all cloned branches will be stored.
Definition: RooCustomizer.cxx:680
RooCustomizer::splitArgs
void splitArgs(const RooArgSet &argSet, const RooAbsCategory &splitCat)
Split all arguments in 'set' into individualized clones for each defined state of 'splitCat'.
Definition: RooCustomizer.cxx:295
RooFit::NoRecursion
RooCmdArg NoRecursion(Bool_t flag=kTRUE)
Definition: RooGlobalFunc.cxx:358
RooCustomizer::_replaceArgList
TList _replaceArgList
Definition: RooCustomizer.h:100
RooAbsCategoryLValue::setLabel
virtual bool setLabel(const char *label, Bool_t printError=kTRUE)=0
Change category state by specifying a state name.
RooFit::InputArguments
@ InputArguments
Definition: RooGlobalFunc.h:61
RooCustomizer::_cloneNodeListOwned
RooArgSet * _cloneNodeListOwned
Definition: RooCustomizer.h:115
RooArgSet.h
RooCustomizer::printMultiline
virtual void printMultiline(std::ostream &os, Int_t content, Bool_t verbose=kFALSE, TString indent="") const
Print customizer configuration details.
Definition: RooCustomizer.cxx:651
TList::FindObject
virtual TObject * FindObject(const char *name) const
Find an object in this list using its name.
Definition: TList.cxx:578
TString::Data
const char * Data() const
Definition: TString.h:369
RooCustomizer::printName
virtual void printName(std::ostream &os) const
Print name of customizer.
Definition: RooCustomizer.cxx:610
ClassImp
#define ClassImp(name)
Definition: Rtypes.h:364
Form
char * Form(const char *fmt,...)
RooCustomizer::_cloneNodeListAll
RooArgSet * _cloneNodeListAll
Definition: RooCustomizer.h:114
TNamed::GetTitle
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:48
RooCustomizer
RooCustomizer is a factory class to produce clones of a prototype composite PDF object with the same ...
Definition: RooCustomizer.h:35
RooCustomizer::_cloneBranchList
RooArgSet * _cloneBranchList
Definition: RooCustomizer.h:111
coutE
#define coutE(a)
Definition: RooMsgService.h:33
coutW
#define coutW(a)
Definition: RooMsgService.h:32
RooAbsArg::SetName
void SetName(const char *name)
Set the name of the TNamed.
Definition: RooAbsArg.cxx:2325
RooAbsArg.h
RooAbsCollection::remove
virtual Bool_t remove(const RooAbsArg &var, Bool_t silent=kFALSE, Bool_t matchByNameOnly=kFALSE)
Remove the specified argument from our list.
Definition: RooAbsCollection.cxx:585
RooAbsCollection::find
RooAbsArg * find(const char *name) const
Find object with given name in list.
Definition: RooAbsCollection.cxx:810
TString::Length
Ssiz_t Length() const
Definition: TString.h:410
coutI
#define coutI(a)
Definition: RooMsgService.h:30
indent
static void indent(ostringstream &buf, int indent_level)
Definition: TClingCallFunc.cxx:87
RooCustomizer::CustIFace
Definition: RooCustomizer.h:80
RooFactoryWSTool::ws
RooWorkspace & ws()
Definition: RooFactoryWSTool.h:74
TString
Basic string class.
Definition: TString.h:136
RooCustomizer::printArgs
virtual void printArgs(std::ostream &os) const
Print arguments of customizer, i.e. input p.d.f and input master category (if any)
Definition: RooCustomizer.cxx:637
RooCustomizer::build
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...
Definition: RooCustomizer.cxx:397
RooAbsCategory::getCurrentLabel
virtual const char * getCurrentLabel() const
Return label string of current state.
Definition: RooAbsCategory.cxx:130
RooAbsArg::branchNodeServerList
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:520
RooAbsCollection::useHashMapForFind
void useHashMapForFind(bool flag) const
Install an internal hash map for fast finding of elements by name.
Definition: RooAbsCollection.cxx:1483
bool
RooCustomizer::replaceArg
void replaceArg(const RooAbsArg &orig, const RooAbsArg &subst)
Replace any occurence of arg 'orig' with arg 'subst'.
Definition: RooCustomizer.cxx:341
TSeqCollection::IndexOf
virtual Int_t IndexOf(const TObject *obj) const
Return index of object in collection.
Definition: TSeqCollection.cxx:30
RooFit::RecycleConflictNodes
RooCmdArg RecycleConflictNodes(Bool_t flag=kTRUE)
Definition: RooGlobalFunc.cxx:351
RooWorkspace::import
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.
Definition: RooWorkspace.cxx:361
RooAbsCategory
RooAbsCategory is the base class for objects that represent a discrete value with a finite number of ...
Definition: RooAbsCategory.h:37
RooCustomizer::cloneBranchList
const RooArgSet & cloneBranchList() const
Definition: RooCustomizer.h:55
TObject::GetName
virtual const char * GetName() const
Returns name of object.
Definition: TObject.cxx:359
RooCustomizer::_splitArgList
TList _splitArgList
Definition: RooCustomizer.h:97
TList::At
virtual TObject * At(Int_t idx) const
Returns the object at position idx. Returns 0 if idx is out of range.
Definition: TList.cxx:357
RooFactoryWSTool::registerSpecial
static void registerSpecial(const char *typeName, RooFactoryWSTool::IFace *iface)
Register foreign special objects in factory.
Definition: RooFactoryWSTool.cxx:1937
RooAbsArg::setStringAttribute
void setStringAttribute(const Text_t *key, const Text_t *value)
Associate string 'value' to this object under key 'key'.
Definition: RooAbsArg.cxx:323
RooCustomizer::RooCustomizer
RooCustomizer(const RooAbsArg &pdf, const RooAbsCategoryLValue &masterCat, RooArgSet &splitLeafListOwned, RooArgSet *splitLeafListAll=0)
Constructor with a prototype and masterCat index category.
Definition: RooCustomizer.cxx:219
RooCustomizer::initialize
void initialize()
Initialize the customizer.
Definition: RooCustomizer.cxx:268
RooFactoryWSTool
RooFactoryWSTool is a class similar to TTree::MakeClass() that generates skeleton code for RooAbsPdf ...
Definition: RooFactoryWSTool.h:47
RooCustomizer.h
RooAbsPdf.h
TNamed
The TNamed class is the base class for all named ROOT classes.
Definition: TNamed.h:29
kFALSE
const Bool_t kFALSE
Definition: RtypesCore.h:101
TString::Append
TString & Append(const char *cs)
Definition: TString.h:564
RooCustomizer::_replaceSubList
TList _replaceSubList
Definition: RooCustomizer.h:101
RooAbsCollection::add
virtual Bool_t add(const RooAbsArg &var, Bool_t silent=kFALSE)
Add the specified argument to list.
Definition: RooAbsCollection.cxx:455
RooAbsArg::getStringAttribute
const Text_t * getStringAttribute(const Text_t *key) const
Get string attribute mapped under key 'key'.
Definition: RooAbsArg.cxx:336
RooRealConstant::removalDummy
static RooConstVar & removalDummy()
Create a dummy node used in node-removal operations.
Definition: RooRealConstant.cxx:75
RooFit::ObjectHandling
@ ObjectHandling
Definition: RooGlobalFunc.h:61
oocoutW
#define oocoutW(o, a)
Definition: RooMsgService.h:47
TNamed::SetTitle
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition: TNamed.cxx:164
void
typedef void((*Func_t)())
RooAbsCollection::addOwned
virtual Bool_t addOwned(RooAbsArg &var, Bool_t silent=kFALSE)
Add the specified argument to list.
Definition: RooAbsCollection.cxx:403
RooConstVar.h
RooGlobalFunc.h
RooFactoryWSTool::IFace
Definition: RooFactoryWSTool.h:139
RooCustomizer::_masterBranchList
RooArgSet _masterBranchList
Definition: RooCustomizer.h:107
RooCustomizer::_internalCloneBranchList
RooArgSet _internalCloneBranchList
Definition: RooCustomizer.h:110
RooCustomizer::printTitle
virtual void printTitle(std::ostream &os) const
Print title of customizer.
Definition: RooCustomizer.cxx:619
RooAbsCategory.h
RooAbsArg::addOwnedComponents
Bool_t addOwnedComponents(const RooArgSet &comps)
Take ownership of the contents of 'comps'.
Definition: RooAbsArg.cxx:2216
RooAbsArg::leafNodeServerList
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:509
TCollection::GetSize
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
Definition: TCollection.h:182
RooAbsCategoryLValue.h
RooCustomizer::_sterile
Bool_t _sterile
Definition: RooCustomizer.h:93
TList::Add
virtual void Add(TObject *obj)
Definition: TList.h:87
TObject
Mother of all ROOT objects.
Definition: TObject.h:37
RooAbsArg::setAttribute
void setAttribute(const Text_t *name, Bool_t value=kTRUE)
Set (default) or clear a named boolean attribute of this object.
Definition: RooAbsArg.cxx:291
RooCustomizer::~RooCustomizer
virtual ~RooCustomizer()
Destructor.
Definition: RooCustomizer.cxx:279
RooCustomizer::splitArg
void splitArg(const RooAbsArg &arg, const RooAbsCategory &splitCat)
Split all argument 'arg' into individualized clones for each defined state of 'splitCat'.
Definition: RooCustomizer.cxx:318
RooWorkspace::arg
RooAbsArg * arg(const char *name) const
Return RooAbsArg with given name. A null pointer is returned if none is found.
Definition: RooWorkspace.cxx:1323
name
char name[80]
Definition: TGX11.cxx:110
RooCustomizer::_splitCatList
TList _splitCatList
Definition: RooCustomizer.h:98
RooCustomizer::_owning
Bool_t _owning
Definition: RooCustomizer.h:94
genreflex::verbose
bool verbose
Definition: rootcling_impl.cxx:133
RooAbsArg
RooAbsArg is the common abstract base class for objects that represent a value and a "shape" in RooFi...
Definition: RooAbsArg.h:72
RooCustomizer::_name
TString _name
Definition: RooCustomizer.h:95
TNamed::GetName
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
RooFit::Silence
RooCmdArg Silence(Bool_t flag=kTRUE)
Definition: RooGlobalFunc.cxx:301
RooAbsCategoryLValue
RooAbsCategoryLValue is the common abstract base class for objects that represent a discrete value th...
Definition: RooAbsCategoryLValue.h:25
ROOT::Math::detail::sep
@ sep
Definition: GenVectorIO.h:35
RooArgList.h
RooCustomizer::_masterCat
RooAbsCategoryLValue * _masterCat
Definition: RooCustomizer.h:105
RooAbsCollection::getSize
Int_t getSize() const
Definition: RooAbsCollection.h:231
RooRealConstant.h
RooArgSet
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Definition: RooArgSet.h:33
int