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