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