Logo ROOT   6.12/07
Reference Guide
RooFactoryWSTool.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 \file RooFactoryWSTool.cxx
19 \class RooFactoryWSTool
20 \ingroup Roofitcore
21 
22 RooFactoryWSTool is a clase like TTree::MakeClass() that generates
23 skeleton code for RooAbsPdf and RooAbsReal functions given
24 a list of input parameter names. The factory can also compile
25 the generated code on the fly, and on request also immediate
26 instantiate objects.
27 **/
28 
29 #include "RooFit.h"
30 
31 #include "RooFactoryWSTool.h"
32 #include "RooAbsReal.h"
33 #include "RooAbsCategory.h"
34 #include "RooArgList.h"
35 #include "RooRealVar.h"
36 #include "RooCategory.h"
37 #include "RooMsgService.h"
38 #include "RooWorkspace.h"
39 #include "TInterpreter.h"
40 #include "TClass.h"
41 #include "TClassTable.h"
42 #include "RooAbsPdf.h"
43 #include "RooGaussian.h"
44 #include <fstream>
45 #include <vector>
46 #include <string>
47 #include "RooGlobalFunc.h"
48 #include "RooDataSet.h"
49 #include "RooDataHist.h"
50 #include "RooCintUtils.h"
51 #include "RooAddPdf.h"
52 #include "RooProdPdf.h"
53 #include "RooSimultaneous.h"
54 #include "RooFFTConvPdf.h"
55 #include "RooNumConvPdf.h"
56 #include "RooResolutionModel.h"
57 #include "RooProduct.h"
58 #include "RooAddition.h"
59 #include "RooChi2Var.h"
60 #include "RooNLLVar.h"
61 #include "RooRealSumPdf.h"
62 #include "RooConstVar.h"
63 #include "RooDerivative.h"
64 #include "RooStringVar.h"
65 #include "TROOT.h"
66 
67 using namespace RooFit ;
68 using namespace std ;
69 
70 #define BUFFER_SIZE 64000
71 
73 ;
74 
76 map<string,RooFactoryWSTool::IFace*>* RooFactoryWSTool::_hooks=0 ;
77 
78 static Int_t init();
79 
80 static Int_t dummy = init() ;
81 
82 static Int_t init()
83 {
85 
86  // Operator p.d.f.s
88  RooFactoryWSTool::registerSpecial("RSUM",iface) ;
89  RooFactoryWSTool::registerSpecial("ASUM",iface) ;
90  RooFactoryWSTool::registerSpecial("PROD",iface) ;
91  RooFactoryWSTool::registerSpecial("SIMUL",iface) ;
92  RooFactoryWSTool::registerSpecial("EXPR",iface) ;
93  RooFactoryWSTool::registerSpecial("FCONV",iface) ;
94  RooFactoryWSTool::registerSpecial("NCONV",iface) ;
95 
96  // Operator functions
98  RooFactoryWSTool::registerSpecial("prod",iface) ;
99  RooFactoryWSTool::registerSpecial("expr",iface) ;
100  RooFactoryWSTool::registerSpecial("nconv",iface) ;
101 
102  // Test statistics
103  RooFactoryWSTool::registerSpecial("nll",iface) ;
104  RooFactoryWSTool::registerSpecial("chi2",iface) ;
105  RooFactoryWSTool::registerSpecial("profile",iface) ;
106 
107  // Integration and derivation
108  RooFactoryWSTool::registerSpecial("int",iface) ;
109  RooFactoryWSTool::registerSpecial("deriv",iface) ;
110  RooFactoryWSTool::registerSpecial("cdf",iface) ;
111  RooFactoryWSTool::registerSpecial("PROJ",iface) ;
112 
113  // Miscellaneous
114  RooFactoryWSTool::registerSpecial("dataobs",iface) ;
115  RooFactoryWSTool::registerSpecial("set",iface) ;
116 
117  (void) dummy;
118  return 0 ;
119 }
120 
121 
122 #ifndef _WIN32
123 #include <strings.h>
124 #else
125 
126 static char *strtok_r(char *s1, const char *s2, char **lasts)
127 {
128  char *ret;
129 
130  if (s1 == NULL)
131  s1 = *lasts;
132  while(*s1 && strchr(s2, *s1))
133  ++s1;
134  if(*s1 == '\0')
135  return NULL;
136  ret = s1;
137  while(*s1 && !strchr(s2, *s1))
138  ++s1;
139  if(*s1)
140  *s1++ = '\0';
141  *lasts = s1;
142  return ret;
143 }
144 
145 #endif
146 
147 
148 
149 ////////////////////////////////////////////////////////////////////////////////
150 
151 RooFactoryWSTool::RooFactoryWSTool(RooWorkspace& inws) : _ws(&inws), _errorCount(0), _autoClassPostFix("")
152 
153 {
154  // Default constructor
155 }
156 
157 
158 
159 ////////////////////////////////////////////////////////////////////////////////
160 /// Destructor
161 
163 {
164 }
165 
166 
167 
168 
169 ////////////////////////////////////////////////////////////////////////////////
170 /// Low-level factory interface for creating a RooRealVar with a given range and initial value
171 
173 {
174  // First check if variable already exists
175  if (_ws->var(name)) {
176  coutE(ObjectHandling) << "RooFactoryWSTool::createFactory() ERROR: variable with name '" << name << "' already exists" << endl ;
177  logError() ;
178  return 0 ;
179  }
180 
181  // Create variable
182  RooRealVar var(name,name,xmin,xmax) ;
183 
184  // Put in workspace
185  if (_ws->import(var,Silence())) logError() ;
186 
187  return _ws->var(name) ;
188 }
189 
190 
191 
192 ////////////////////////////////////////////////////////////////////////////////
193 /// Low-level factory interface for creating a RooCategory with a given list of state names. The State name list
194 /// can be of the form 'name1,name2,name3' or of the form 'name1=id1,name2=id2,name3=id3'
195 
196 RooCategory* RooFactoryWSTool::createCategory(const char* name, const char* stateNameList)
197 {
198  // Create variable
199  RooCategory cat(name,name) ;
200 
201  // Add listed state names
202  if (stateNameList) {
203  const size_t tmpSize = strlen(stateNameList)+1;
204  char *tmp = new char[tmpSize] ;
205  strlcpy(tmp,stateNameList,tmpSize) ;
206  char* save ;
207  char* tok = strtok_r(tmp,",",&save) ;
208  while(tok) {
209  char* sep = strchr(tok,'=') ;
210  if (sep) {
211  *sep = 0 ;
212  Int_t id = atoi(sep+1) ;
213  cat.defineType(tok,id) ;
214  *sep = '=' ;
215  } else {
216  cat.defineType(tok) ;
217  }
218  tok = strtok_r(0,",",&save) ;
219  }
220  delete[] tmp ;
221  }
222 
223  cat.setStringAttribute("factory_tag",Form("%s[%s]",name,stateNameList)) ;
224 
225  // Put in workspace
226  if (_ws->import(cat,Silence())) logError() ;
227 
228  return _ws->cat(name) ;
229 }
230 
231 
232 
233 ////////////////////////////////////////////////////////////////////////////////
234 /// Low-level factory interface for creating a RooAbsPdf of a given class with a given list of input variables
235 /// The variable list varList should be of the form "a,b,c" where the interpretation of the argument is
236 /// dependent on the p.d.f. Set and List arguments can be passed by substituting a single argument with
237 /// the form (a,b,c), i.e. one can set varList to "x,(a0,a1,a2)" to pass a RooAbsReal and a RooArgSet as arguments.
238 
239 RooAbsArg* RooFactoryWSTool::createArg(const char* className, const char* objName, const char* varList)
240 {
241  // Find class in ROOT class table
242  TClass* tc = resolveClassName(className) ;
243  if (!tc) {
244  coutE(ObjectHandling) << "RooFactoryWSTool::createArg() ERROR class " << className << " not found in factory alias table, nor in ROOT class table" << endl ;
245  logError() ;
246  return 0 ;
247  }
248 
249  className = tc->GetName() ;
250 
251  // Check that class inherits from RooAbsPdf
252  if (!tc->InheritsFrom(RooAbsArg::Class())) {
253  coutE(ObjectHandling) << "RooFactoryWSTool::createArg() ERROR class " << className << " does not inherit from RooAbsArg" << endl ;
254  logError() ;
255  return 0 ;
256  }
257 
258 
259  _args.clear() ;
260  char tmp[BUFFER_SIZE] ;
261  strlcpy(tmp,varList,BUFFER_SIZE) ;
262  char* p=tmp ;
263  char* tok=tmp ;
264  Int_t blevel(0) ;
265  Bool_t litmode(kFALSE) ;
266  while(*p) {
267 
268  // Keep track of opening and closing brackets
269  if (*p=='{' || *p=='(' || *p=='[') blevel++ ;
270  if (*p=='}' || *p==')' || *p==']') blevel-- ;
271 
272  // Keep track of string literals
273  if (*p=='"' || *p=='\'') litmode = !litmode ;
274 
275  // If we encounter a comma at zero bracket level
276  // finalize the current token as a completed argument
277  // and start the next token
278  if (!litmode && blevel==0 && ((*p)==',')) {
279  *p = 0 ;
280  _args.push_back(tok) ;
281  tok = p+1 ;
282  }
283 
284  p++ ;
285  }
286  _args.push_back(tok) ;
287 
288 
289  // Try CINT interface
290  pair<list<string>,unsigned int> ca = RooCintUtils::ctorArgs(className,_args.size()+2) ;
291  if (ca.first.size()==0) {
292  coutE(ObjectHandling) << "RooFactoryWSTool::createArg() ERROR no suitable constructor found for class " << className << endl ;
293  logError() ;
294  return 0 ;
295  }
296 
297 
298  // Check if number of provided args is in valid range (add two to accomodate name and title strings)
299  if (_args.size()+2<ca.second || _args.size()+2>ca.first.size()) {
300  if (ca.second==ca.first.size()) {
301  coutE(ObjectHandling) << "RooFactoryWSTool::createArg() ERROR number of arguments provided (" << _args.size() << ") for class is invalid, " << className
302  << " expects " << ca.first.size()-2 << endl ;
303  logError() ;
304  } else {
305  coutE(ObjectHandling) << "RooFactoryWSTool::createArg() ERROR number of arguments provided (" << _args.size() << ") for class is invalid " << className
306  << " expect number between " << ca.second-2 << " and " << ca.first.size()-2 << endl ;
307  logError() ;
308  }
309  return 0 ;
310  }
311 
312  // Now construct CINT constructor spec, start with mandatory name and title args
313  string cintExpr(Form("new %s(\"%s\",\"%s\"",className,objName,objName)) ;
314 
315  // Install argument in static data member to be accessed below through static CINT interface functions
316  _of = this ;
317 
318 
319  try {
320  Int_t i(0) ;
321  list<string>::iterator ti = ca.first.begin() ; ti++ ; ti++ ;
322  for (vector<string>::iterator ai = _args.begin() ; ai != _args.end() ; ai++,ti++,i++) {
323  if ((*ti)=="RooAbsReal&" || (*ti)=="const RooAbsReal&") {
325  cintExpr += Form(",RooFactoryWSTool::as_FUNC(%d)",i) ;
326  } else if ((*ti)=="RooAbsArg&" || (*ti)=="const RooAbsArg&") {
328  cintExpr += Form(",RooFactoryWSTool::as_ARG(%d)",i) ;
329  } else if ((*ti)=="RooRealVar&" || (*ti)=="const RooRealVar&") {
331  cintExpr += Form(",RooFactoryWSTool::as_VAR(%d)",i) ;
332  } else if ((*ti)=="RooAbsRealLValue&" || (*ti)=="const RooAbsRealLValue&") {
334  cintExpr += Form(",RooFactoryWSTool::as_VARLV(%d)",i) ;
335  } else if ((*ti)=="RooCategory&" || (*ti)=="const RooCategory&") {
337  cintExpr += Form(",RooFactoryWSTool::as_CAT(%d)",i) ;
338  } else if ((*ti)=="RooAbsCategory&" || (*ti)=="const RooAbsCategory&") {
340  cintExpr += Form(",RooFactoryWSTool::as_CATFUNC(%d)",i) ;
341  } else if ((*ti)=="RooAbsCategoryLValue&" || (*ti)=="const RooAbsCategoryLValue&") {
343  cintExpr += Form(",RooFactoryWSTool::as_CATLV(%d)",i) ;
344  } else if ((*ti)=="RooAbsPdf&" || (*ti)=="const RooAbsPdf&") {
346  cintExpr += Form(",RooFactoryWSTool::as_PDF(%d)",i) ;
347  } else if ((*ti)=="RooResolutionModel&" || (*ti)=="const RooResolutionModel&") {
349  cintExpr += Form(",RooFactoryWSTool::as_RMODEL(%d)",i) ;
350  } else if ((*ti)=="RooAbsData&" || (*ti)=="const RooAbsData&") {
352  cintExpr += Form(",RooFactoryWSTool::as_DATA(%d)",i) ;
353  } else if ((*ti)=="RooDataSet&" || (*ti)=="const RooDataSet&") {
355  cintExpr += Form(",RooFactoryWSTool::as_DSET(%d)",i) ;
356  } else if ((*ti)=="RooDataHist&" || (*ti)=="const RooDataHist&") {
358  cintExpr += Form(",RooFactoryWSTool::as_DHIST(%d)",i) ;
359  } else if ((*ti)=="const RooArgSet&") {
361  cintExpr += Form(",RooFactoryWSTool::as_SET(%d)",i) ;
362  } else if ((*ti)=="const RooArgList&") {
364  cintExpr += Form(",RooFactoryWSTool::as_LIST(%d)",i) ;
365  } else if ((*ti)=="const char*") {
367  cintExpr += Form(",RooFactoryWSTool::as_STRING(%d)",i) ;
368  } else if ((*ti)=="Int_t" || (*ti)=="int" || (*ti)=="Bool_t" || (*ti)=="bool") {
370  cintExpr += Form(",RooFactoryWSTool::as_INT(%d)",i) ;
371  } else if ((*ti)=="Double_t") {
373  cintExpr += Form(",RooFactoryWSTool::as_DOUBLE(%d)",i) ;
374  } else if (RooCintUtils::isEnum(ti->c_str())) {
375 
376  string qualvalue ;
377  if (_args[i].find(Form("%s::",className)) != string::npos) {
378  qualvalue = _args[i].c_str() ;
379  } else {
380  qualvalue = Form("%s::%s",className,_args[i].c_str()) ;
381  }
382  if (RooCintUtils::isValidEnumValue(ti->c_str(),qualvalue.c_str())) {
383  cintExpr += Form(",(%s)%s",ti->c_str(),qualvalue.c_str()) ;
384  } else {
385  throw string(Form("Supplied argument %s does not represent a valid state of enum %s",_args[i].c_str(),ti->c_str())) ;
386  }
387  } else {
388  // Check if generic object store has argument of given name and type
390 
391  // Strip argument type to bare type (i.e. const X& -> X)
392  string btype ;
393  if (ti->find("const ")==0) {
394  btype = ti->c_str()+6 ;
395  } else {
396  btype = *ti ;
397  }
398  if (btype.find("&")) {
399  btype.erase(btype.size()-1,btype.size()) ;
400  }
401 
402  // If btype if a typedef, substitute it by the true type name
403  btype = RooCintUtils::trueName(btype.c_str()) ;
404 
405  if (obj.InheritsFrom(btype.c_str())) {
406  cintExpr += Form(",(%s&)RooFactoryWSTool::as_OBJ(%d)",ti->c_str(),i) ;
407  } else {
408  throw string(Form("Required argument with name %s of type '%s' is not in the workspace",_args[i].c_str(),ti->c_str())) ;
409  }
410  }
411  }
412  cintExpr += ") ;" ;
413  } catch (string err) {
414  coutE(ObjectHandling) << "RooFactoryWSTool::createArg() ERROR constructing " << className << "::" << objName << ": " << err << endl ;
415  logError() ;
416  return 0 ;
417  }
418 
419  cxcoutD(ObjectHandling) << "RooFactoryWSTool::createArg() Construct expression is " << cintExpr << endl ;
420 
421  // Call CINT to perform constructor call. Catch any error thrown by argument conversion method
422  RooAbsArg* arg = (RooAbsArg*) gROOT->ProcessLineFast(cintExpr.c_str()) ;
423 
424  if (arg) {
425  if (string(className)=="RooGenericPdf") {
426  arg->setStringAttribute("factory_tag",Form("EXPR::%s(%s)",objName,varList)) ;
427  } else if (string(className)=="RooFormulaVar") {
428  arg->setStringAttribute("factory_tag",Form("expr::%s(%s)",objName,varList)) ;
429  } else {
430  arg->setStringAttribute("factory_tag",Form("%s::%s(%s)",className,objName,varList)) ;
431  }
432  if (_ws->import(*arg,Silence())) logError() ;
433  RooAbsArg* ret = _ws->arg(objName) ;
434  delete arg ;
435  return ret ;
436  } else {
437  coutE(ObjectHandling) << "RooFactoryWSTool::createArg() ERROR in CINT constructor call to create object" << endl ;
438  logError() ;
439  return 0 ;
440  }
441 }
442 
443 
444 
445 ////////////////////////////////////////////////////////////////////////////////
446 
447 vector<string> RooFactoryWSTool::ctorArgs(const char* /*className*/)
448 {
449  return vector<string>() ;
450 }
451 
452 
453 
454 
455 ////////////////////////////////////////////////////////////////////////////////
456 
457 RooAddPdf* RooFactoryWSTool::add(const char *objName, const char* specList, Bool_t recursiveCoefs)
458 {
459  // Spec list is of form a*A,b*B,c*C,D [ *d]
460 
461  RooArgList pdfList ;
462  RooArgList coefList ;
463  RooArgList pdfList2 ;
464 
465  try {
466 
467  char buf[BUFFER_SIZE] ;
468  strlcpy(buf,specList,BUFFER_SIZE) ;
469  char* save ;
470  char* tok = strtok_r(buf,",",&save) ;
471  while(tok) {
472  char* star=strchr(tok,'*') ;
473  if (star) {
474  *star=0 ;
475  pdfList.add(asPDF(star+1)) ;
476  coefList.add(asFUNC(tok)) ;
477  } else {
478  pdfList2.add(asPDF(tok)) ;
479  }
480  tok = strtok_r(0,",",&save) ;
481  }
482  pdfList.add(pdfList2) ;
483 
484  } catch (string err) {
485  coutE(ObjectHandling) << "RooFactoryWSTool::add(" << objName << ") ERROR creating RooAddPdf: " << err << endl ;
486  logError() ;
487  return 0 ;
488  }
489 
490  RooAddPdf* pdf = new RooAddPdf(objName,objName,pdfList,coefList,recursiveCoefs) ;
491  pdf->setStringAttribute("factory_tag",Form("SUM::%s(%s)",objName,specList)) ;
492  if (_ws->import(*pdf,Silence())) logError() ;
493  return (RooAddPdf*) _ws->pdf(objName) ;
494 }
495 
496 
497 ////////////////////////////////////////////////////////////////////////////////
498 
499 RooRealSumPdf* RooFactoryWSTool::amplAdd(const char *objName, const char* specList)
500 {
501  // Spec list is of form a*A,b*B,c*C,D [ *d]
502 
503  RooArgList amplList ;
504  RooArgList coefList ;
505  RooArgList amplList2 ;
506 
507  try {
508 
509  char buf[BUFFER_SIZE] ;
510  strlcpy(buf,specList,BUFFER_SIZE) ;
511  char* save ;
512  char* tok = strtok_r(buf,",",&save) ;
513  while(tok) {
514  char* star=strchr(tok,'*') ;
515  if (star) {
516  *star=0 ;
517  amplList.add(asFUNC(star+1)) ;
518  coefList.add(asFUNC(tok)) ;
519  } else {
520  amplList2.add(asFUNC(tok)) ;
521  }
522  tok = strtok_r(0,",",&save) ;
523  }
524  amplList.add(amplList2) ;
525 
526  } catch (string err) {
527  coutE(ObjectHandling) << "RooFactoryWSTool::add(" << objName << ") ERROR creating RooRealSumPdf: " << err << endl ;
528  logError() ;
529  return 0 ;
530  }
531 
532  RooRealSumPdf* pdf = new RooRealSumPdf(objName,objName,amplList,coefList,(amplList.getSize()==coefList.getSize())) ;
533  pdf->setStringAttribute("factory_tag",Form("ASUM::%s(%s)",objName,specList)) ;
534  if (_ws->import(*pdf,Silence())) logError() ;
535  return (RooRealSumPdf*) _ws->pdf(objName) ;
536 }
537 
538 
539 ////////////////////////////////////////////////////////////////////////////////
540 
541 RooProdPdf* RooFactoryWSTool::prod(const char *objName, const char* pdfList)
542 {
543  _of = this ;
544 
545  // Separate conditional and non-conditional p.d.f terms
546  RooLinkedList cmdList ;
547  string regPdfList="{" ;
548  char buf[BUFFER_SIZE] ;
549  strlcpy(buf,pdfList,BUFFER_SIZE) ;
550  char* save ;
551  char* tok = strtok_r(buf,",",&save) ;
552  while(tok) {
553  char *sep = strchr(tok,'|') ;
554  if (sep) {
555  // Conditional term
556  *sep=0 ;
557  sep++ ;
558 
559  // |x is conditional on x, |~x is conditional on all but x
560  Bool_t invCond(kFALSE) ;
561  if (*sep=='~') {
562  invCond=kTRUE ;
563  sep++ ;
564  }
565 
566  try {
567  cmdList.Add(Conditional(asSET(tok),asSET(sep),!invCond).Clone()) ;
568  } catch (string err) {
569  coutE(ObjectHandling) << "RooFactoryWSTool::prod(" << objName << ") ERROR creating RooProdPdf Conditional argument: " << err << endl ;
570  logError() ;
571  return 0 ;
572  }
573 
574  } else {
575  // Regular term
576  if (regPdfList.size()>1) {
577  regPdfList += "," ;
578  }
579  regPdfList += tok ;
580  }
581  tok = strtok_r(0,",",&save) ;
582  }
583  regPdfList += "}" ;
584 
585  RooProdPdf* pdf = 0 ;
586  try {
587  pdf = new RooProdPdf(objName,objName,asSET(regPdfList.c_str()),cmdList) ;
588  } catch (string err) {
589  coutE(ObjectHandling) << "RooFactoryWSTool::prod(" << objName << ") ERROR creating RooProdPdf input set of regular p.d.f.s: " << err << endl ;
590  logError() ;
591  pdf = 0 ;
592  }
593  cmdList.Delete() ;
594 
595  if (pdf) {
596  pdf->setStringAttribute("factory_tag",Form("PROD::%s(%s)",objName,pdfList)) ;
597  if (_ws->import(*pdf,Silence())) logError() ;
598  delete pdf ;
599  return (RooProdPdf*) _ws->pdf(objName) ;
600  } else {
601  return 0 ;
602  }
603 }
604 
605 
606 
607 ////////////////////////////////////////////////////////////////////////////////
608 
609 RooSimultaneous* RooFactoryWSTool::simul(const char* objName, const char* indexCat, const char* pdfMap)
610 {
611  map<string,RooAbsPdf*> theMap ;
612  // Add p.d.f. to index state mappings
613  char buf[BUFFER_SIZE] ;
614  strlcpy(buf,pdfMap,BUFFER_SIZE) ;
615  char* save ;
616  char* tok = strtok_r(buf,",",&save) ;
617  while(tok) {
618  char* eq = strchr(tok,'=') ;
619  if (!eq) {
620  coutE(ObjectHandling) << "RooFactoryWSTool::simul(" << objName << ") ERROR creating RooSimultaneous::" << objName
621  << " expect mapping token of form 'state=pdfName', but found '" << tok << "'" << endl ;
622  logError() ;
623  return 0 ;
624  } else {
625  *eq = 0 ;
626 
627  try {
628  theMap[tok] = &asPDF(eq+1) ;
629  } catch ( string err ) {
630  coutE(ObjectHandling) << "RooFactoryWSTool::simul(" << objName << ") ERROR creating RooSimultaneous: " << err << endl ;
631  logError() ;
632  }
633  }
634  tok = strtok_r(0,",",&save) ;
635  }
636 
637 
638  // Create simultaneous p.d.f.
639  RooSimultaneous* pdf(0) ;
640  try {
641  pdf = new RooSimultaneous(objName,objName,theMap,asCATLV(indexCat)) ;
642  } catch (string err) {
643  coutE(ObjectHandling) << "RooFactoryWSTool::simul(" << objName << ") ERROR creating RooSimultaneous::" << objName << " " << err << endl ;
644  logError() ;
645  }
646 
647  // Import p.d.f into workspace
648  pdf->setStringAttribute("factory_tag",Form("SIMUL::%s(%s,%s)",objName,indexCat,pdfMap)) ;
649  if (_ws->import(*pdf,Silence())) logError() ;
650  return (RooSimultaneous*) _ws->pdf(objName) ;
651 }
652 
653 
654 
655 
656 ////////////////////////////////////////////////////////////////////////////////
657 
658 RooAddition* RooFactoryWSTool::addfunc(const char *objName, const char* specList)
659 {
660  RooArgList sumlist1 ;
661  RooArgList sumlist2 ;
662 
663  try {
664 
665  char buf[BUFFER_SIZE] ;
666  strlcpy(buf,specList,BUFFER_SIZE) ;
667  char* save ;
668  char* tok = strtok_r(buf,",",&save) ;
669  while(tok) {
670  char* star=strchr(tok,'*') ;
671  if (star) {
672  *star=0 ;
673  sumlist2.add(asFUNC(star+1)) ;
674  sumlist1.add(asFUNC(tok)) ;
675  } else {
676  sumlist1.add(asFUNC(tok)) ;
677  }
678  tok = strtok_r(0,",",&save) ;
679  }
680 
681  } catch (string err) {
682  coutE(ObjectHandling) << "RooFactoryWSTool::addfunc(" << objName << ") ERROR creating RooAddition: " << err << endl ;
683  logError() ;
684  return 0 ;
685  }
686 
687  if (sumlist2.getSize()>0 && (sumlist1.getSize()!=sumlist2.getSize())) {
688  coutE(ObjectHandling) << "RooFactoryWSTool::addfunc(" << objName << ") ERROR creating RooAddition: syntax error: either all sum terms must be products or none" << endl ;
689  logError() ;
690  return 0 ;
691  }
692 
693 
694  RooAddition* sum ;
695  if (sumlist2.getSize()>0) {
696  sum = new RooAddition(objName,objName,sumlist1,sumlist2) ;
697  } else {
698  sum = new RooAddition(objName,objName,sumlist1) ;
699  }
700 
701  sum->setStringAttribute("factory_tag",Form("sum::%s(%s)",objName,specList)) ;
702  if (_ws->import(*sum,Silence())) logError() ;
703  delete sum ;
704  return (RooAddition*) _ws->pdf(objName) ;
705 
706 }
707 
708 
709 
710 
711 ////////////////////////////////////////////////////////////////////////////////
712 
713 RooProduct* RooFactoryWSTool::prodfunc(const char *objName, const char* pdfList)
714 {
715  return (RooProduct*) createArg("RooProduct",objName,Form("{%s}",pdfList)) ;
716 }
717 
718 
719 
720 
721 
722 ////////////////////////////////////////////////////////////////////////////////
723 /// Process high-level object creation syntax
724 /// Accepted forms of syntax are
725 ///
726 ///
727 /// Creating variables
728 ///
729 /// x[-10,10] - Create variable x with given range and put it in workspace
730 /// x[3,-10,10] - Create variable x with given range and initial value and put it in workspace
731 /// x[3] - Create variable x with given constant value
732 ///
733 /// <numeric literal> - Numeric literal expressions (0.5, -3 etc..) are converted to a RooConst(<numeric literal>)
734 /// where ever a RooAbsReal or RooAbsArg argument is expected
735 ///
736 /// Creating categories
737 ///
738 /// c[lep,kao,nt1,nt2] - Create category c with given state names
739 /// tag[B0=1,B0bar=-1] - Create category tag with given state names and index assignments
740 ///
741 ///
742 /// Creating functions and p.d.f.s
743 ///
744 /// MyPdf::g(x,m,s) - Create p.d.f or function of type MyPdf with name g with argument x,m,s
745 /// Interpretation and number of arguments are mapped to the constructor arguments of the class
746 /// (after the name and title).
747 ///
748 /// MyPdf(x,m,s) - As above, but with an implicitly defined (unique) object name
749 ///
750 ///
751 /// Creating sets and lists (to be used as inputs above)
752 ///
753 /// {a,b,c} - Create RooArgSet or RooArgList (as determined by context) from given contents
754 ///
755 ///
756 ///
757 /// Objects that are not created, are assumed to exist in the workspace
758 /// Object creation expressions as shown above can be nested, e.g. one can do
759 ///
760 /// RooGaussian::g(x[-10,10],m[0],3)
761 ///
762 /// to create a p.d.f and its variables in one go. This nesting can be applied recursively e.g.
763 ///
764 /// SUM::model( f[0.5,0,1] * RooGaussian::g( x[-10,10], m[0], 3] ),
765 /// RooChebychev::c( x, {a0[0.1],a1[0.2],a2[-0.3]} ))
766 ///
767 /// creates the sum of a Gaussian and a Chebychev and all its variables
768 ///
769 ///
770 /// A seperate series of operator meta-type exists to simplify the construction of composite expressions
771 /// meta-types in all capitals (SUM) create p.d.f.s, meta types in lower case (sum) create
772 /// functions.
773 ///
774 ///
775 /// SUM::name(f1*pdf1,f2*pdf2,pdf3] -- Create sum p.d.f name with value f1*pdf1+f2*pdf2+(1-f1-f2)*pdf3
776 /// RSUM::name(f1*pdf1,f2*pdf2,pdf3] -- Create recursive sum p.d.f. name with value f1*pdf1 + (1-f1)(f2*pdf2 + (1-f2)pdf3)
777 /// ASUM::name(f1*amp1,f2*amp2,amp3] -- Create sum p.d.f. name with value f1*amp1+f2*amp2+(1-f1-f2)*amp3 where amplX are amplitudes of type RooAbsReal
778 /// sum::name(a1,a2,a3] -- Create sum function with value a1+a2+a3
779 /// sum::name(a1*b1,a2*b2,a3*b 3] -- Create sum function with value a1*b1+a2*b2+a3*b3
780 ///
781 /// PROD::name(pdf1,pdf2] -- Create product of p.d.f with 'name' with given input p.d.fs
782 /// PROD::name(pdf1|x,pdf2] -- Create product of conditional p.d.f. pdf1 given x and pdf2
783 /// prod::name(a,b,c] -- Create production function with value a*b*c
784 ///
785 /// SIMUL::name(cat,a=pdf1,b=pdf2] -- Create simultaneous p.d.f index category cat. Make pdf1 to state a, pdf2 to state b
786 ///
787 /// EXPR::name('expr',var,...] -- Create an generic p.d.f that interprets the given expression
788 /// expr::name('expr',var,...] -- Create an generic function that interprets the given expression
789 ///
790 ///
791 /// The functionality of high level object creation tools like RooSimWSTool, RooCustomizer and RooClassFactory
792 /// is also interfaced through meta-types in the factory
793 ///
794 ///
795 /// Interface to RooSimWSTool
796 ///
797 /// SIMCLONE::name( modelPdf, $ParamSplit(...),
798 /// $ParamSplitConstrained(...), $Restrict(...) ] -- Clone-and-customize modelPdf according to ParamSplit and ParamSplitConstrained()
799 /// specifications and return a RooSimultaneous p.d.f. of all built clones
800 ///
801 /// MSIMCLONE::name( masterIndex,
802 /// $AddPdf(mstate1, modelPdf1, $ParamSplit(...)),
803 /// $AddPdf(mstate2,modelPdf2),...) ] -- Clone-and-customize multiple models (modelPdf1,modelPdf2) according to ParamSplit and
804 /// ParamSplitConstrained() specifications and return a RooSimultaneous p.d.f. of all built clones,
805 /// using the specified master index to map prototype p.d.f.s to master states
806 /// Interface to RooCustomizer
807 ///
808 /// EDIT::name( orig, substNode=origNode), ... ] -- Create a clone of input object orig, with the specified replacements operations executed
809 /// EDIT::name( orig, origNode=$REMOVE(), ... ] -- Create clone of input removing term origNode from all PROD() terms that contained it
810 /// EDIT::name( orig, origNode=$REMOVE(prodname,...), ... ] -- As above, but restrict removal of origNode to PROD term(s) prodname,...
811 ///
812 ///
813 /// Interface to RooClassFactory
814 ///
815 /// CEXPR::name('expr',var,...] -- Create an custom compiled p.d.f that evaluates the given expression
816 /// cexpr::name('expr',var,...] -- Create an custom compiled function that evaluates the given expression
817 ///
818 ///
819 /// $MetaType(...) - Meta argument that does not result in construction of an object but is used logically organize
820 /// input arguments in certain operator p.d.f. constructions. The defined meta arguments are context dependent.
821 ///
822 /// The only meta argument that is defined globally is $Alias(typeName,aliasName) to
823 /// define aliases for type names. For the definition of meta arguments in operator p.d.f.s
824 /// see the definitions below
825 
827 {
828 
829 // cout << "RooFactoryWSTool::process() " << expr << endl ;
830 
831  // First perform basic syntax check
832  if (checkSyntax(expr)) {
833  return 0 ;
834  }
835 
836  // Allocate work buffer
837  char* buf = new char[strlen(expr)+1] ;
838 
839  // Copy to buffer while absorbing white space and newlines
840  char* buftmp = buf ;
841  while(*expr) {
842  if (!isspace(*expr)) {
843  *buftmp = *expr ;
844  buftmp++ ;
845  }
846  expr++ ;
847  }
848  *buftmp=0 ;
849 
850 
851  // Clear error count and start a transaction in the workspace
852  clearError() ;
853  ws().startTransaction() ;
854 
855  // Process buffer
856  string out ;
857  try {
858  out = processExpression(buf) ;
859  } catch (string error) {
860  coutE(ObjectHandling) << "RooFactoryWSTool::processExpression() ERROR in parsing: " << error << endl ;
861  logError() ;
862  }
863 
864  // If there were no errors commit the transaction, cancel it otherwise
865  if (errorCount()>0) {
866  coutE(ObjectHandling) << "RooFactoryWSTool::processExpression() ERRORS detected, transaction to workspace aborted, no objects committed" << endl ;
867  ws().cancelTransaction() ;
868  } else {
869  ws().commitTransaction() ;
870  }
871 
872 
873  // Delete buffer
874  delete[] buf ;
875 
876  return out.size() ? ws().arg(out.c_str()) : 0 ;
877 }
878 
879 
880 
881 
882 ////////////////////////////////////////////////////////////////////////////////
883 /// Process a single high-level expression or list of
884 /// expressions. The returned string a the reduced expression where
885 /// all inline object creations have been executed and substituted
886 /// with the name of the created object
887 ///
888 /// e.g. 'RooGaussian::g(x,m,s)' --> 'g'
889 /// '{x(-10,10),s} --> '{x,s}'
890 
891 std::string RooFactoryWSTool::processExpression(const char* token)
892 {
893  // Delegate handling to list processor if token starts with {, otherwise
894  // call single expression processor
895  if (string(token).find("$Alias(")==0) {
896  processAliasExpression(token) ;
897  }
898 
899  if (token[0]=='{') {
900  // Process token as list if it starts with '{'
901  return processListExpression(token) ;
902  } else {
903  // Process token as single item otherwise
904  return processCompositeExpression(token) ;
905  }
906 }
907 
908 
909 
910 ////////////////////////////////////////////////////////////////////////////////
911 /// Process a single composite expression
912 ///
913 /// e.g. 'A=RooGaussian::g[x,m,s]' --> 'A=g'
914 /// e.g. 'f[0,1]*RooGaussian::g[x,m,s]' --> 'f*g'
915 /// e.g. 'RooGaussian::g(x,y,s)|x' --> g|x'
916 /// e.g. '$MetaArg(RooGaussian::g[x,m,s],blah)' --> '$MetaArg(g,blah)'
917 
918 std::string RooFactoryWSTool::processCompositeExpression(const char* token)
919 {
920  // Allocate and fill work buffer
921  const size_t bufBaseSize = strlen(token)+1;
922  char* buf_base = new char[bufBaseSize] ;
923  char* buf = buf_base ;
924  strlcpy(buf,token,bufBaseSize) ;
925  char* p = buf ;
926 
927  list<string> singleExpr ;
928  list<char> separator ;
929  Int_t blevel(0) ;
930  Bool_t litmode(kFALSE) ;
931  while(*p) {
932 
933  // Keep track of opening and closing brackets
934  if (*p=='{' || *p=='(' || *p=='[') blevel++ ;
935  if (*p=='}' || *p==')' || *p==']') blevel-- ;
936 
937  // Keep track of string literals
938  if (*p=='"' || *p=='\'') litmode = !litmode ;
939 
940  // If we are zero-bracket level and encounter a |, store
941  // the remainder of the string as suffix and exit loop
942  if (!litmode && blevel==0 && ( (*p)=='=' || (*p) == '|' || (*p) == '*')) {
943  separator.push_back(*p) ;
944  *p=0 ;
945  singleExpr.push_back(buf) ;
946  buf = p+1 ;
947  }
948  p++ ;
949  }
950  if (*buf) {
951  singleExpr.push_back(buf) ;
952  }
953  if (singleExpr.size()==1) {
954  string ret = processSingleExpression(token) ;
955  delete[] buf_base ;
956  return ret ;
957  }
958 
959  string ret ;
960  list<char>::iterator ic = separator.begin() ;
961  for (list<string>::iterator ii = singleExpr.begin() ; ii!=singleExpr.end() ; ii++) {
962  ret += processSingleExpression(ii->c_str()) ;
963  if (ic != separator.end()) {
964  ret += *ic ;
965  ic++ ;
966  }
967  }
968 
969  delete[] buf_base ;
970  return ret ;
971 }
972 
973 
974 
975 ////////////////////////////////////////////////////////////////////////////////
976 /// Process a single high-level expression. The returned string a the reduced
977 /// expression where all inline object creations have been executed and substituted
978 /// with the name of the created object
979 ///
980 /// e.g. 'RooGaussian::g(x,m,s)' --> 'g'
981 /// e.g. 'x[-10,10]' --> 'x'
982 
983 std::string RooFactoryWSTool::processSingleExpression(const char* arg)
984 {
985  // Handle empty strings here
986  if (strlen(arg)==0) {
987  return string("") ;
988  }
989 
990  // Handle string literal case
991  if (arg[0]=='\'' || arg[0]=='"') {
992  return string(arg) ;
993  }
994 
995  // Allocate and fill work buffer
996  const size_t bufSize = strlen(arg)+1;
997  char* buf = new char[bufSize] ;
998  strlcpy(buf,arg,bufSize) ;
999  char* bufptr = buf ;
1000 
1001  string func,prefix ;
1002  vector<string> args ;
1003 
1004  // Process token into arguments
1005  char* save ;
1006  char* tmpx = strtok_r(buf,"([",&save) ;
1007  func = tmpx ? tmpx : "" ;
1008  char* p = strtok_r(0,"",&save) ;
1009 
1010  // Return here if token is fundamental
1011  if (!p) {
1012  delete[] buf ;
1013  return arg ;
1014  }
1015 
1016 
1017  char* tok = p ;
1018  Int_t blevel=0 ;
1019  Bool_t litmode(kFALSE) ;
1020  while(*p) {
1021 
1022  // Keep track of opening and closing brackets
1023  if (*p=='{' || *p=='(' || *p=='[') blevel++ ;
1024  if (*p=='}' || *p==')' || *p==']') blevel-- ;
1025 
1026  // Keep track of string literals
1027  if (*p=='"' || *p=='\'') litmode = !litmode ;
1028 
1029 
1030  // If we encounter a comma at zero bracket level
1031  // finalize the current token as a completed argument
1032  // and start the next token
1033  if (!litmode && blevel==0 && ((*p)==',')) {
1034  *p = 0 ;
1035  args.push_back(tok) ;
1036  tok = p+1 ;
1037  }
1038 
1039  p++ ;
1040  }
1041 
1042  // If the last character was a closing bracket, kill
1043  // it in the buffer
1044  if (p>bufptr && (*(p-1)==')'||*(p-1)==']')) {
1045  *(p-1)=0 ;
1046  }
1047 
1048  // Finalize last token as argument
1049  string tmp = tok ;
1050 
1051  // If there is a suffix left in the work buffer attach it to
1052  // this argument
1053  p = strtok_r(0,"",&save) ;
1054  if (p) tmp += p ;
1055  args.push_back(tmp) ;
1056 
1057  // Delete the work buffer
1058  delete[] buf ;
1059 
1060  // If function contains :: then call createArg to process this arg, otherwise
1061  // call createVariable
1062  string ret ;
1063 
1064  // Determine type of leading bracket
1065  char lb = ' ' ;
1066  for(const char* pp=arg ; *pp!=0 ; pp++) {
1067  if (*pp=='(' || *pp=='[' || *pp=='{') {
1068  lb = *pp ;
1069  break ;
1070  }
1071  }
1072 
1073  if (strstr(func.c_str(),"::")) {
1074  if (lb=='(') {
1075  // Create function argument with instance name
1076  ret= processCreateArg(func,args) ;
1077  } else {
1078  coutE(ObjectHandling) << "RooFactoryWSTool::processSingleExpression(" << arg << "): ERROR: Syntax error: Class::Instance must be followed by (...)" << endl ;
1079  logError() ;
1080  }
1081  } else if (func[0]!='$'){
1082  if (lb=='[') {
1083  // Create variable argument
1084  ret= processCreateVar(func,args) ;
1085  } else if (lb=='(') {
1086 
1087  // Create function argument with autoname
1088  string autoname ;
1089  if (!_autoNamePrefix.empty()) {
1090  // If we're inside a function creation call to a higher level object, use its
1091  // name as base for the autoname
1092  autoname = (Form("%s::%s",func.c_str(),_autoNamePrefix.top().c_str())) ;
1093  } else {
1094  // Otherwise find a free global_%d name
1095  static Int_t globCounter = 0 ;
1096  while(true) {
1097  autoname = Form("gobj%d",globCounter) ;
1098  globCounter++ ;
1099  if (!ws().arg(autoname.c_str())) {
1100  break ;
1101  }
1102  }
1103  autoname = Form("%s::%s",func.c_str(),autoname.c_str()) ;
1104  }
1105  ret= processCreateArg(autoname,args) ;
1106  } else {
1107  coutE(ObjectHandling) << "RooFactoryWSTool::processSingleExpression(" << arg << "): ERROR: Syntax error: expect either Class(...) or Instance[...]" << endl ;
1108  logError() ;
1109  }
1110  } else {
1111  if (lb=='(') {
1112  // Process meta function (compile arguments, but not meta-function itself)
1113  ret= processMetaArg(func,args) ;
1114  } else {
1115  coutE(ObjectHandling) << "RooFactoryWSTool::processSingleExpression(" << arg << "): ERROR: Syntax error: $MetaClass must be followed by (...)" << endl ;
1116  logError() ;
1117  }
1118  }
1119 
1120  // Return reduced token with suffix
1121  return ret ;
1122 }
1123 
1124 
1125 ////////////////////////////////////////////////////////////////////////////////
1126 /// Process a list of high-level expression. The returned string a the reduced
1127 /// expression list where all inline object creations have been executed and substituted
1128 /// with the name of the created object
1129 ///
1130 /// E.g. '{x(-10,10),s} --> '{x,s}'
1131 
1133 {
1134  // Allocate and fill work buffer
1135  const size_t bufSize = strlen(arg)+1;
1136  char* buf = new char[bufSize] ;
1137  strlcpy(buf,arg,bufSize) ;
1138 
1139  vector<string> args ;
1140 
1141  // Start running pointer at position 1 to skip opening bracket
1142  char* tok = buf+1 ;
1143  char* p = buf+1 ;
1144 
1145  // Processing look
1146  Int_t level(0) ;
1147  while(*p) {
1148 
1149  // Track bracketing level
1150  if (*p=='{' || *p=='(' || *p=='[') level++ ;
1151  if (*p=='}' || *p==')' || *p==']') level-- ;
1152 
1153 
1154  // If we encounter a comma at zero bracket level
1155  // finalize the current token as a completed argument
1156  // and start the next token
1157  if (level==0 && ((*p)==',')) {
1158  *p = 0 ;
1159  args.push_back(tok) ;
1160  tok = p+1 ;
1161  }
1162 
1163  p++ ;
1164  }
1165 
1166  // Finalize token as last argument
1167  if (p>buf && *(p-1)=='}') {
1168  *(p-1)=0 ;
1169  }
1170  args.push_back(tok) ;
1171 
1172  // Delete work buffer
1173  delete[] buf ;
1174 
1175  // Process each argument in list and construct reduced
1176  // expression to be returned
1177  string ret("{") ;
1178  vector<string>::iterator iter = args.begin() ;
1179  Int_t i(0) ;
1180  while(iter!= args.end()) {
1181  if (strlen(ret.c_str())>1) ret += "," ;
1182  if (!_autoNamePrefix.empty()) {
1183  _autoNamePrefix.push(Form("%s%d",_autoNamePrefix.top().c_str(),i+1)) ;
1184  }
1185  ret += processSingleExpression(iter->c_str()) ;
1186  if (!_autoNamePrefix.empty()) {
1187  _autoNamePrefix.pop() ;
1188  }
1189  iter++ ;
1190  i++ ;
1191  }
1192  ret += "}" ;
1193 
1194  return ret ;
1195 }
1196 
1197 
1198 
1199 ////////////////////////////////////////////////////////////////////////////////
1200 /// Parse token
1201 
1203 {
1204  vector<string> args = splitFunctionArgs(token) ;
1205  if (args.size()!=2) {
1206  coutE(ObjectHandling) << "RooFactorWSTool::processAliasExpression() ERROR $Alias() takes exactly two arguments, " << args.size() << " args found" << endl ;
1207  logError() ;
1208  return string() ;
1209  }
1210 
1211  // Insert alias in table
1212  _typeAliases[args[1]] = args[0] ;
1213 
1214  return string() ;
1215 }
1216 
1217 
1218 
1219 
1220 ////////////////////////////////////////////////////////////////////////////////
1221 
1223 {
1224  // First do recursive alias expansion
1225  while (true) {
1226  map<string,string>::iterator item = _typeAliases.find(className) ;
1227 
1228  // If an alias is found, recurse
1229  if (item != _typeAliases.end()) {
1230  className = item->second.c_str() ;
1231  } else {
1232  break ;
1233  }
1234  }
1235 
1236  // Now find dealiased class in ROOT class table
1237  TClass* tc = TClass::GetClass(className,kTRUE,kTRUE) ;
1238 
1239  // If its not there, try prefixing with Roo
1240  if (!tc) {
1241  tc = TClass::GetClass(Form("Roo%s",className)) ;
1242  if (!tc) {
1243  coutE(ObjectHandling) << "RooFactoryWSTool::createArg() ERROR class " << className << " not defined in ROOT class table" << endl ;
1244  logError() ;
1245  return 0 ;
1246  }
1247  }
1248  return tc ;
1249 }
1250 
1251 
1252 
1253 ////////////////////////////////////////////////////////////////////////////////
1254 
1255 string RooFactoryWSTool::varTag(string& func, vector<string>& args)
1256 {
1257  string ret ;
1258  ret += func ;
1259  ret += "[" ;
1260  for (vector<string>::iterator iter = args.begin() ; iter!=args.end() ; ++iter) {
1261  if (iter!=args.begin()) {
1262  ret += "," ;
1263  }
1264  ret += *iter ;
1265  }
1266  ret += "]" ;
1267  return ret ;
1268 }
1269 
1270 
1271 
1272 
1273 ////////////////////////////////////////////////////////////////////////////////
1274 /// Glue function between high-level syntax and low-level factory call to createVariable:
1275 /// Process a parsed call to create a variable named 'func'
1276 ///
1277 /// If initial token is non-numeric, a RooCategory will be created, and the args are interpreted
1278 /// as either state names or 'name=id' assignments. Otherwise a RooRealvar is created and the
1279 /// arg list is interpreted as follows:
1280 /// If list has two args, these are interpreted as xmin,xmax
1281 /// If list has three args, these are interpreted as xinit,xmin,xmax
1282 /// If list has one arg, this is interpreted as xinit and the variable is set as constant
1283 
1284 string RooFactoryWSTool::processCreateVar(string& func, vector<string>& args)
1285 {
1286 
1287  // Determine if first arg is numeric
1288  string first = *(args.begin()) ;
1289  if (isdigit(first[0]) || first[0]=='.' || first[0]=='+' || first[0]=='-') {
1290 
1291  // Create a RooRealVar
1292  vector<string>::iterator ai = args.begin() ;
1293  if (args.size()==1) {
1294 
1295  // One argument, create constant variable with given value
1296  Double_t xinit = atof((ai)->c_str()) ;
1297  cxcoutD(ObjectHandling) << "CREATE variable " << func << " xinit = " << xinit << endl ;
1298  RooRealVar tmp(func.c_str(),func.c_str(),xinit) ;
1299  tmp.setStringAttribute("factory_tag",varTag(func,args).c_str()) ;
1300  if (_ws->import(tmp,Silence())) {
1301  logError() ;
1302  }
1303 
1304  } else if (args.size()==2) {
1305 
1306  // Two arguments, create variable with given range
1307  Double_t xlo = atof((ai++)->c_str()) ;
1308  Double_t xhi = atof(ai->c_str()) ;
1309  cxcoutD(ObjectHandling) << "CREATE variable " << func << " xlo = " << xlo << " xhi = " << xhi << endl ;
1310  RooRealVar tmp(func.c_str(),func.c_str(),xlo,xhi) ;
1311  tmp.setStringAttribute("factory_tag",varTag(func,args).c_str()) ;
1312  if (_ws->import(tmp,Silence())) {
1313  logError() ;
1314  }
1315 
1316  } else if (args.size()==3) {
1317 
1318  // Three arguments, create variable with given initial value and range
1319  Double_t xinit = atof((ai++)->c_str()) ;
1320  Double_t xlo = atof((ai++)->c_str()) ;
1321  Double_t xhi = atof(ai->c_str()) ;
1322  cxcoutD(ObjectHandling) << "CREATE variable " << func << " xinit = " << xinit << " xlo = " << xlo << " xhi = " << xhi << endl ;
1323  RooRealVar tmp(func.c_str(),func.c_str(),xinit,xlo,xhi) ;
1324  tmp.setStringAttribute("factory_tag",varTag(func,args).c_str()) ;
1325  if (_ws->import(tmp,Silence())) {
1326  logError() ;
1327  }
1328  }
1329  } else {
1330 
1331  // Create a RooAbsCategory
1332  string allStates ;
1333  for (vector<string>::iterator ai = args.begin() ; ai!=args.end() ; ai++) {
1334  if (allStates.size()>0) {
1335  allStates += "," ;
1336  }
1337  allStates += *ai ;
1338  }
1339  createCategory(func.c_str(),allStates.c_str()) ;
1340 
1341  }
1342  return func ;
1343 }
1344 
1345 
1346 ////////////////////////////////////////////////////////////////////////////////
1347 /// Glue function between high-level syntax and low-level factory call to createArg:
1348 /// Process a parsed call to create a p.d.f named func
1349 ///
1350 /// The func arg is interpreted as ClassName::ObjectName and the arglist is passed
1351 /// verbatim to createArg. The received arglist is expected to be fully reduced (i.e.
1352 /// all inline object creations must have been compiled)
1353 
1354 string RooFactoryWSTool::processCreateArg(string& func, vector<string>& args)
1355 {
1356  // Allocate and fill work buffer
1357  char buf[BUFFER_SIZE] ;
1358  strlcpy(buf,func.c_str(),BUFFER_SIZE) ;
1359 
1360  // Split function part in class name and instance name
1361  char* save ;
1362  const char *className = strtok_r(buf,":",&save) ;
1363  const char *instName = strtok_r(0,":",&save) ;
1364  if (!className) className = "";
1365  if (!instName) instName = "" ;
1366 
1367  // Concatenate list of args into comma separated string
1368  char pargs[BUFFER_SIZE] ;
1369  pargs[0] = 0 ;
1370  vector<string>::iterator iter = args.begin() ;
1371  vector<string> pargv ;
1372  Int_t iarg(0) ;
1373  while(iter!=args.end()) {
1374  if (strlen(pargs)>0) strlcat(pargs,",",BUFFER_SIZE) ;
1375  _autoNamePrefix.push(Form("%s_%d",instName,iarg+1)) ;
1376  string tmp = processExpression(iter->c_str()) ;
1377  _autoNamePrefix.pop() ;
1378  strlcat(pargs,tmp.c_str(),BUFFER_SIZE) ;
1379  pargv.push_back(tmp) ;
1380  iter++ ;
1381  iarg++ ;
1382  }
1383 
1384  // Look up if func is a special
1385  for (map<string,IFace*>::iterator ii=hooks().begin() ; ii!=hooks().end() ; ii++) {
1386  }
1387  if (hooks().find(className) != hooks().end()) {
1388  IFace* iface = hooks()[className] ;
1389  return iface->create(*this, className,instName,pargv) ;
1390  }
1391 
1392  createArg(className,instName,pargs) ;
1393 
1394  return string(instName) ;
1395 }
1396 
1397 
1398 
1399 ////////////////////////////////////////////////////////////////////////////////
1400 /// Concatenate list of args into comma separated string
1401 
1402 std::string RooFactoryWSTool::processMetaArg(std::string& func, std::vector<std::string>& args)
1403 {
1404  char pargs[BUFFER_SIZE] ;
1405  pargs[0] = 0 ;
1406  vector<string>::iterator iter = args.begin() ;
1407  vector<string> pargv ;
1408  while(iter!=args.end()) {
1409  if (strlen(pargs)>0) strlcat(pargs,",",BUFFER_SIZE) ;
1410  string tmp = processExpression(iter->c_str()) ;
1411  strlcat(pargs,tmp.c_str(),BUFFER_SIZE) ;
1412  pargv.push_back(tmp) ;
1413  iter++ ;
1414  }
1415 
1416  string ret = func+"("+pargs+")" ;
1417  return ret ;
1418 }
1419 
1420 
1421 
1422 
1423 ////////////////////////////////////////////////////////////////////////////////
1424 /// Allocate and fill work buffer
1425 
1426 vector<string> RooFactoryWSTool::splitFunctionArgs(const char* funcExpr)
1427 {
1428  const size_t bufSize = strlen(funcExpr)+1;
1429  char* buf = new char[bufSize] ;
1430  strlcpy(buf,funcExpr,bufSize) ;
1431  char* bufptr = buf ;
1432 
1433  string func ;
1434  vector<string> args ;
1435 
1436  // Process token into arguments
1437  char* save ;
1438  char* tmpx = strtok_r(buf,"(",&save) ;
1439  func = tmpx ? tmpx : "" ;
1440  char* p = strtok_r(0,"",&save) ;
1441 
1442  // Return here if token is fundamental
1443  if (!p) {
1444  delete[] buf ;
1445  return args ;
1446  }
1447 
1448  char* tok = p ;
1449  Int_t blevel=0 ;
1450  Bool_t litmode(kFALSE) ;
1451  while(*p) {
1452 
1453  // Keep track of opening and closing brackets
1454  if (*p=='{' || *p=='(' || *p=='[') blevel++ ;
1455  if (*p=='}' || *p==')' || *p==']') blevel-- ;
1456 
1457  // Keep track of string literals
1458  if (*p=='"' || *p=='\'') litmode = !litmode ;
1459 
1460 
1461  // If we encounter a comma at zero bracket level
1462  // finalize the current token as a completed argument
1463  // and start the next token
1464  if (!litmode && blevel==0 && ((*p)==',')) {
1465  *p = 0 ;
1466  args.push_back(tok) ;
1467  tok = p+1 ;
1468  }
1469 
1470  p++ ;
1471  }
1472 
1473  // If the last character was a closing bracket, kill
1474  // it in the buffer
1475  if (p>bufptr && *(p-1)==')') {
1476  *(p-1)=0 ;
1477  }
1478 
1479  // Finalize last token as argument
1480  string tmp = tok ;
1481 
1482  // If there is a suffix left in the work buffer attach it to
1483  // this argument
1484  p = strtok_r(0,"",&save) ;
1485  if (p) tmp += p ;
1486  args.push_back(tmp) ;
1487 
1488  // Delete the work buffer
1489  delete[] buf ;
1490 
1491  return args ;
1492 }
1493 
1494 
1495 
1496 
1497 
1498 ////////////////////////////////////////////////////////////////////////////////
1499 /// Perform basic syntax on given factory expression. If function returns
1500 /// true syntax errors are found.
1501 
1503 {
1504  // Count parentheses
1505  Int_t nParentheses(0), nBracket(0), nAccolade(0) ;
1506  const char* ptr = arg ;
1507  while(*ptr) {
1508  if (*ptr=='(') nParentheses++ ;
1509  if (*ptr==')') nParentheses-- ;
1510  if (*ptr=='[') nBracket++ ;
1511  if (*ptr==']') nBracket-- ;
1512  if (*ptr=='{') nAccolade++ ;
1513  if (*ptr=='}') nAccolade-- ;
1514  ptr++ ;
1515  }
1516  if (nParentheses!=0) {
1517  coutE(ObjectHandling) << "RooFactoryWSTool::checkSyntax ERROR non-matching '" << (nParentheses>0?"(":")") << "' in expression" << endl ;
1518  return kTRUE ;
1519  }
1520  if (nBracket!=0) {
1521  coutE(ObjectHandling) << "RooFactoryWSTool::checkSyntax ERROR non-matching '" << (nBracket>0?"[":"]") << "' in expression" << endl ;
1522  return kTRUE ;
1523  }
1524  if (nAccolade!=0) {
1525  coutE(ObjectHandling) << "RooFactoryWSTool::checkSyntax ERROR non-matching '" << (nAccolade>0?"{":"}") << "' in expression" << endl ;
1526  return kTRUE ;
1527  }
1528  return kFALSE ;
1529 }
1530 
1531 
1532 
1533 ////////////////////////////////////////////////////////////////////////////////
1534 
1536 {
1537  if (idx>_of->_args.size()-1) {
1538  throw string(Form("Need argument number %d, but only %d args are provided",idx,(Int_t)_of->_args.size())) ;
1539  }
1540 }
1541 
1542 
1543 
1544 ////////////////////////////////////////////////////////////////////////////////
1545 /// CINT constructor interface, return constructor string argument #idx as RooAbsArg reference found in workspace
1546 
1548  {
1549  // If arg is a numeric string, make a RooConst() of it here
1550  if (arg[0]=='.' || arg[0]=='+' || arg[0] == '-' || isdigit(arg[0])) {
1551  return RooConst(atof(arg)) ;
1552  }
1553 
1554  // Otherwise look it up by name in the workspace
1555  RooAbsArg* rarg = ws().arg(arg) ;
1556  if (!rarg) {
1557  throw string(Form("RooAbsArg named %s not found",arg)) ;
1558  }
1559  return *rarg ;
1560 }
1561 
1562 
1563 
1564 ////////////////////////////////////////////////////////////////////////////////
1565 /// CINT constructor interface, return constructor string argument #idx as RooAbsReal reference found in workspace
1566 
1568 {
1569  // If arg is a numeric string, make a RooConst() of it here
1570  if (arg[0]=='.' || arg[0]=='+' || arg[0] == '-' || isdigit(arg[0])) {
1571  return RooConst(atof(arg)) ;
1572  }
1573 
1574  RooAbsArg* rarg = ws().arg(arg) ;
1575  if (!rarg) {
1576  throw string(Form("RooAbsReal named %s not found",arg)) ;
1577  }
1578  RooAbsReal* real = dynamic_cast<RooAbsReal*>(rarg) ;
1579  if (!real) {
1580  throw string(Form("Object named %s is not of type RooAbsReal",arg)) ;
1581  }
1582  return *real ;
1583 }
1584 
1585 
1586 
1587 ////////////////////////////////////////////////////////////////////////////////
1588 /// CINT constructor interface, return constructor string argument #idx as RooAbsRealLValue reference found in workspace
1589 
1591 {
1592  // If arg is a numeric string, throw error as lvalue is required
1593  if (arg[0]=='.' || arg[0]=='+' || arg[0] == '-' || isdigit(arg[0])) {
1594  throw string(Form("Numeric literal provided for argument (%s), but lvalue is required",arg)) ;
1595  }
1596 
1597  RooAbsArg* rarg = ws().arg(arg) ;
1598  if (!rarg) {
1599  throw string(Form("RooAbsRealLValue named %s not found",arg)) ;
1600  }
1601  RooAbsRealLValue* reallv = dynamic_cast<RooAbsRealLValue*>(rarg) ;
1602  if (!reallv) {
1603  throw string(Form("Object named %s is not of type RooAbsRealLValue",arg)) ;
1604  }
1605  return *reallv ;
1606 }
1607 
1608 
1609 
1610 ////////////////////////////////////////////////////////////////////////////////
1611 /// CINT constructor interface, return constructor string argument #idx as RooRealVar reference found in workspace
1612 
1614 {
1615  RooRealVar* var = ws().var(arg) ;
1616  if (!var) {
1617  throw string(Form("RooRealVar named %s not found",arg)) ;
1618  }
1619  return *var ;
1620 }
1621 
1622 
1623 
1624 
1625 ////////////////////////////////////////////////////////////////////////////////
1626 /// CINT constructor interface, return constructor string argument #idx as RooAbsPdf reference found in workspace
1627 
1629 {
1630  RooAbsPdf* pdf = ws().pdf(arg) ;
1631  if (!pdf) {
1632  throw string(Form("RooAbsPdf named %s not found",arg)) ;
1633  }
1634  return *pdf ;
1635 }
1636 
1637 
1638 
1639 
1640 ////////////////////////////////////////////////////////////////////////////////
1641 /// CINT constructor interface, return constructor string argument #idx as RooResolutionModel reference found in workspace
1642 
1644 {
1645  RooAbsArg* rarg = ws().arg(arg) ;
1646  if (!rarg) {
1647  throw string(Form("RooResolutionModel named %s not found",arg)) ;
1648  }
1649  RooResolutionModel * rmodel = dynamic_cast<RooResolutionModel*>(rarg) ;
1650  if (!rmodel) {
1651  throw string(Form("Object named %s is not of type RooResolutionModel",arg)) ;
1652  }
1653  return *rmodel ;
1654 }
1655 
1656 
1657 
1658 
1659 ////////////////////////////////////////////////////////////////////////////////
1660 /// CINT constructor interface, return constructor string argument #idx as RooAbsCategory reference found in workspace
1661 
1663 {
1664  RooAbsArg* rarg = ws().arg(arg) ;
1665  if (!rarg) {
1666  throw string(Form("RooAbsCategory named %s not found",arg)) ;
1667  }
1668  RooAbsCategory* catf = dynamic_cast<RooAbsCategory*>(rarg) ;
1669  if (!catf) {
1670  throw string(Form("Object named %s is not of type RooAbsCategory",arg)) ;
1671  }
1672  return *catf ;
1673 }
1674 
1675 
1676 
1677 ////////////////////////////////////////////////////////////////////////////////
1678 /// CINT constructor interface, return constructor string argument #idx as RooAbsCategoryLValue reference found in workspace
1679 
1681 {
1682  RooAbsArg* rarg = ws().arg(arg) ;
1683  if (!rarg) {
1684  throw string(Form("RooAbsCategoryLValue named %s not found",arg)) ;
1685  }
1686 
1687  RooAbsCategoryLValue* catlv = dynamic_cast<RooAbsCategoryLValue*>(rarg) ;
1688  if (!catlv) {
1689  throw string(Form("Object named %s is not of type RooAbsCategoryLValue",arg)) ;
1690  }
1691  return *catlv ;
1692 }
1693 
1694 
1695 
1696 ////////////////////////////////////////////////////////////////////////////////
1697 /// CINT constructor interface, return constructor string argument #idx as RooCategory reference found in workspace
1698 
1700 {
1701  RooCategory* cat = ws().cat(arg) ;
1702  if (!cat) {
1703  throw string(Form("RooCategory named %s not found",arg)) ;
1704  }
1705  return *cat ;
1706 }
1707 
1708 
1709 
1710 
1711 
1712 ////////////////////////////////////////////////////////////////////////////////
1713 /// CINT constructor interface, return constructor string argument #idx as RooArgSet of objects found in workspace
1714 
1716 {
1717  char tmp[BUFFER_SIZE] ;
1718  strlcpy(tmp,arg,BUFFER_SIZE) ;
1719 
1720  RooArgSet s ;
1721 
1722  // If given object is not of {,,,} form, interpret given string as name of defined set
1723  if (arg[0]!='{') {
1724  // cout << "asSet(arg='" << arg << "') parsing as defined set" << endl ;
1725  const RooArgSet* defSet = ws().set(arg) ;
1726  if (defSet) {
1727  // cout << "found defined set: " << *defSet << endl ;
1728  s.add(*defSet) ;
1729  return s ;
1730  }
1731  }
1732 
1733  char* save ;
1734  char* tok = strtok_r(tmp,",{}",&save) ;
1735  int i(0);
1736  while(tok) {
1737 
1738  // If arg is a numeric string, make a RooConst() of it here
1739  if (tok[0]=='.' || tok[0]=='+' || tok[0] == '-' || isdigit(tok[0])) {
1740  s.add(RooConst(atof(tok))) ;
1741  } else if (tok[0] == '\'') {
1742  tok[strlen(tok) - 1] = 0;
1743  RooStringVar *sv = new RooStringVar(Form("string_set_item%03d", i++), "string_set_item", tok + 1);
1744  s.add(*sv);
1745  } else {
1746  RooAbsArg* aarg = ws().arg(tok) ;
1747  if (aarg) {
1748  s.add(*aarg) ;
1749  } else {
1750  throw string(Form("RooAbsArg named %s not found",tok)) ;
1751  }
1752  }
1753  tok = strtok_r(0,",{}",&save) ;
1754  }
1755 
1756  return s ;
1757 }
1758 
1759 
1760 
1761 ////////////////////////////////////////////////////////////////////////////////
1762 /// CINT constructor interface, return constructor string argument #idx as RooArgList of objects found in workspace
1763 
1765 {
1766  char tmp[BUFFER_SIZE] ;
1767  strlcpy(tmp,arg,BUFFER_SIZE) ;
1768 
1769  RooArgList l ;
1770  char* save ;
1771  char* tok = strtok_r(tmp,",{}",&save) ;
1772  while(tok) {
1773 
1774  // If arg is a numeric string, make a RooConst() of it here
1775  if (tok[0]=='.' || tok[0]=='+' || tok[0] == '-' || isdigit(tok[0])) {
1776  l.add(RooConst(atof(tok))) ;
1777  } else if (tok[0] == '\'') {
1778  tok[strlen(tok) - 1] = 0;
1779  RooStringVar *sv = new RooStringVar("listarg", "listarg", tok + 1);
1780  l.add(*sv);
1781  } else {
1782  RooAbsArg* aarg = ws().arg(tok) ;
1783  if (aarg) {
1784  l.add(*aarg) ;
1785  } else {
1786  throw string(Form("RooAbsArg named %s not found",tok)) ;
1787  }
1788  }
1789  tok = strtok_r(0,",{}",&save) ;
1790  }
1791 
1792  return l ;
1793 }
1794 
1795 
1796 
1797 ////////////////////////////////////////////////////////////////////////////////
1798 /// CINT constructor interface, return constructor string argument #idx as RooAbsData object found in workspace
1799 
1801 {
1802  RooAbsData* data = ws().data(arg) ;
1803  if (!data) {
1804  throw string(Form("RooAbsData named %s not found",arg)) ;
1805  }
1806  return *data ;
1807 }
1808 
1809 
1810 
1811 ////////////////////////////////////////////////////////////////////////////////
1812 /// CINT constructor interface, return constructor string argument #idx as RooDataHist object found in workspace
1813 
1815 {
1816  RooAbsData* data = ws().data(arg) ;
1817  if (!data) {
1818  throw string(Form("RooAbsData named %s not found",arg)) ;
1819  }
1820  RooDataHist* hist = dynamic_cast<RooDataHist*>(data) ;
1821  if (!hist) {
1822  throw string(Form("Dataset named %s is not of type RooDataHist",arg)) ;
1823  }
1824  return *hist ;
1825 }
1826 
1827 
1828 ////////////////////////////////////////////////////////////////////////////////
1829 /// CINT constructor interface, return constructor string argument #idx as RooDataSet object found in workspace
1830 
1832 {
1833  RooAbsData* data = ws().data(arg) ;
1834  if (!data) {
1835  throw string(Form("RooAbsData named %s not found",arg)) ;
1836  }
1837  RooDataSet* dset = dynamic_cast<RooDataSet*>(data) ;
1838  if (!dset) {
1839  throw string(Form("Dataset named %s is not of type RooDataSet",arg)) ;
1840  }
1841  return *dset ;
1842 }
1843 
1844 
1845 
1846 ////////////////////////////////////////////////////////////////////////////////
1847 
1849 {
1850  TObject* obj = ws().obj(arg) ;
1851  if (!obj) {
1852  throw string(Form("Object named %s not found",arg)) ;
1853  }
1854  return *obj ;
1855 }
1856 
1857 
1858 
1859 ////////////////////////////////////////////////////////////////////////////////
1860 /// CINT constructor interface, return constructor string argument #idx as const char*
1861 
1862 const char* RooFactoryWSTool::asSTRING(const char* arg)
1863 {
1864  static vector<string> cbuf(10) ;
1865  static unsigned int cbuf_idx = 0 ;
1866 
1867  // Handle empty string case: return null pointer
1868  if (arg==0 || strlen(arg)==0) {
1869  return 0 ;
1870  }
1871 
1872  // Fill cyclical buffer entry with quotation marked stripped version of string literal
1873  // and return pointer to stripped buffer
1874  cbuf[cbuf_idx].clear() ;
1875  const char* p = arg+1 ;
1876  while(*p && (*p) != '"' && (*p) !='\'' ) {
1877  cbuf[cbuf_idx] += *(p++) ;
1878  }
1879  const char* ret = cbuf[cbuf_idx].c_str() ;
1880 
1881  // Increment buffer pointer by one
1882  cbuf_idx++ ;
1883  if (cbuf_idx==cbuf.size()) cbuf_idx=0 ;
1884 
1885  return ret ;
1886 }
1887 
1888 
1889 ////////////////////////////////////////////////////////////////////////////////
1890 /// CINT constructor interface, return constructor string argument #idx as Int_t
1891 
1893 {
1894  return atoi(arg) ;
1895 }
1896 
1897 
1898 ////////////////////////////////////////////////////////////////////////////////
1899 /// CINT constructor interface, return constructor string argument #idx as Double_t
1900 
1902 {
1903  return atof(arg) ;
1904 }
1905 
1906 
1907 ////////////////////////////////////////////////////////////////////////////////
1908 /// Register foreign special objects in factory
1909 
1911 {
1912  hooks()[typeName] = iface ;
1913 }
1914 
1915 
1916 
1917 ////////////////////////////////////////////////////////////////////////////////
1918 
1919 std::map<std::string,RooFactoryWSTool::IFace*>& RooFactoryWSTool::hooks()
1920 {
1921  if (_hooks) return *_hooks ;
1922  _hooks = new map<string,IFace*> ;
1923  return *_hooks ;
1924 }
1925 
1926 
1927 
1928 ////////////////////////////////////////////////////////////////////////////////
1929 /// Concatenate list of args into comma separated string
1930 
1931 std::string RooFactoryWSTool::SpecialsIFace::create(RooFactoryWSTool& ft, const char* typeName, const char* instName, std::vector<std::string> args)
1932 {
1933  char pargs[BUFFER_SIZE] ;
1934  pargs[0] = 0 ;
1935  vector<string>::iterator iter = args.begin() ;
1936  vector<string> pargv ;
1937  while(iter!=args.end()) {
1938  if (strlen(pargs)>0) strlcat(pargs,",",BUFFER_SIZE) ;
1939  string tmp = ft.processExpression(iter->c_str()) ;
1940  strlcat(pargs,tmp.c_str(),BUFFER_SIZE) ;
1941  pargv.push_back(tmp) ;
1942  iter++ ;
1943  }
1944 
1945  // Handling of special operator pdf class names
1946  string cl(typeName) ;
1947  if (cl=="SUM") {
1948 
1949  // SUM::name[a*A,b*B,C]
1950  ft.add(instName,pargs,kFALSE) ;
1951 
1952  } else if (cl=="RSUM") {
1953 
1954  // RSUM::name[a*A,b*B,C]
1955  ft.add(instName,pargs,kTRUE) ;
1956 
1957  } else if (cl=="ASUM") {
1958 
1959  // ASUM::name[a*A,b*B,C]
1960  ft.amplAdd(instName,pargs) ;
1961 
1962  } else if (cl=="PROD") {
1963 
1964  // PROD::name[A,B,C]
1965  ft.prod(instName,pargs) ;
1966 
1967  } else if (cl=="SIMUL") {
1968 
1969  // PROD::name[cat,state=Pdf,...]
1970  if (pargv.size()>1) {
1971  ft.simul(instName,pargv[0].c_str(),strchr(pargs,',')+1) ;
1972  } else {
1973  throw string(Form("Need at least two arguments in call to SIMUL::%s, have %d: %s",instName,(Int_t)pargv.size(),pargs)) ;
1974  }
1975 
1976  } else if (cl=="EXPR") {
1977 
1978  // EXPR::name['expr',var,var,...]
1979  if (args.size()<=2) {
1980  ft.createArg("RooGenericPdf",instName,pargs) ;
1981  } else {
1982  char genargs[BUFFER_SIZE] ;
1983  strlcpy(genargs,args[0].c_str(),BUFFER_SIZE) ;
1984  strlcat(genargs,",{",BUFFER_SIZE) ;
1985  for (UInt_t i=1 ; i<args.size() ; i++) {
1986  if (i!=1) strlcat(genargs,",",BUFFER_SIZE) ;
1987  strlcat(genargs,args[i].c_str(),BUFFER_SIZE) ;
1988  }
1989  strlcat(genargs,"}",BUFFER_SIZE) ;
1990  ft.createArg("RooGenericPdf",instName,genargs) ;
1991  }
1992 
1993  } else if (cl=="FCONV") {
1994 
1995  // FCONV::name[var,pdf1,pdf2]
1996  ft.createArg("RooFFTConvPdf",instName,pargs) ;
1997 
1998  } else if (cl=="NCONV") {
1999 
2000  // NCONV::name[var,pdf1,pdf2]
2001  ft.createArg("RooNumConvPdf",instName,pargs) ;
2002 
2003  } else if (cl=="sum") {
2004 
2005  // sum::name[a,b,c]
2006  ft.addfunc(instName,pargs) ;
2007 
2008  } else if (cl=="prod") {
2009 
2010  // prod::name[a,b,c]
2011  ft.prodfunc(instName,pargs) ;
2012 
2013  } else if (cl=="expr") {
2014 
2015  // expr::name['expr',var,var,...]
2016  if (args.size()<=2) {
2017  ft.createArg("RooFormulaVar",instName,pargs) ;
2018  } else {
2019  char genargs[BUFFER_SIZE] ;
2020  strlcpy(genargs,args[0].c_str(),BUFFER_SIZE) ;
2021  strlcat(genargs,",{",BUFFER_SIZE) ;
2022  for (UInt_t i=1 ; i<args.size() ; i++) {
2023  if (i!=1) strlcat(genargs,",",BUFFER_SIZE) ;
2024  strlcat(genargs,args[i].c_str(),BUFFER_SIZE) ;
2025  }
2026  strlcat(genargs,"}",BUFFER_SIZE) ;
2027  ft.createArg("RooFormulaVar",instName,genargs) ;
2028  }
2029 
2030  } else if (cl=="nconv") {
2031 
2032  // nconv::name[var,pdf1,pdf2]
2033  ft.createArg("RooNumConvolution",instName,pargs) ;
2034 
2035  } else if (cl=="nll") {
2036 
2037  // nll::name[pdf,data]
2038  RooNLLVar nll(instName,instName,ft.asPDF(pargv[0].c_str()),ft.asDATA(pargv[1].c_str())) ;
2039  if (ft.ws().import(nll,Silence())) ft.logError() ;
2040 
2041  } else if (cl=="chi2") {
2042 
2043  // chi2::name[pdf,data]
2044  RooChi2Var nll(instName,instName,ft.asPDF(pargv[0].c_str()),ft.asDHIST(pargv[1].c_str())) ;
2045  if (ft.ws().import(nll,Silence())) ft.logError() ;
2046 
2047  } else if (cl=="profile") {
2048 
2049  // profile::name[func,vars]
2050  ft.createArg("RooProfileLL",instName,pargs) ;
2051 
2052  } else if (cl=="dataobs") {
2053 
2054  // dataobs::name[dset,func]
2055  RooAbsArg* funcClone = static_cast<RooAbsArg*>(ft.asARG(pargv[1].c_str()).clone(instName)) ;
2056  RooAbsArg* arg = ft.asDSET(pargv[0].c_str()).addColumn(*funcClone) ;
2057  if (!ft.ws().fundArg(arg->GetName())) {
2058  if (ft.ws().import(*arg,Silence())) ft.logError() ;
2059  }
2060  delete funcClone ;
2061 
2062  } else if (cl=="int") {
2063 
2064  // int::name[func,intobs]
2065  // int::name[func,intobs|range]
2066  // int::name[func,intobs,normobs]
2067  // int::name[func,intobs|range,normobs]
2068 
2069  if (pargv.size()<2 || pargv.size()>3) {
2070  throw string(Form("int::%s, requires 2 or 3 arguments, have %d arguments",instName,(Int_t)pargv.size())) ;
2071  }
2072 
2073  RooAbsReal& func = ft.asFUNC(pargv[0].c_str()) ;
2074 
2075  char buf[256] ;
2076  strlcpy(buf,pargv[1].c_str(),256) ;
2077  char* save ;
2078  const char* intobs = strtok_r(buf,"|",&save) ;
2079  if (!intobs) intobs="" ;
2080 
2081  const char* range = strtok_r(0,"",&save) ;
2082  if (!range) range="" ;
2083 
2084  RooAbsReal* integral = 0 ;
2085  if (pargv.size()==2) {
2086  if (range && strlen(range)) {
2087  integral = func.createIntegral(ft.asSET(intobs),Range(range)) ;
2088  } else {
2089  integral = func.createIntegral(ft.asSET(intobs)) ;
2090  }
2091  } else {
2092  if (range && strlen(range)) {
2093  integral = func.createIntegral(ft.asSET(intobs),Range(range),NormSet(ft.asSET(pargv[2].c_str()))) ;
2094  } else {
2095  integral = func.createIntegral(ft.asSET(intobs),NormSet(ft.asSET(pargv[2].c_str()))) ;
2096  }
2097  }
2098 
2099  integral->SetName(instName) ;
2100  if (ft.ws().import(*integral,Silence())) ft.logError() ;
2101 
2102  } else if (cl=="deriv") {
2103 
2104  // derive::name[func,obs,order]
2105 
2106  if (pargv.size()<2 || pargv.size()>3) {
2107  throw string(Form("deriv::%s, requires 2 or 3 arguments, have %d arguments",instName,(Int_t)pargv.size())) ;
2108  }
2109 
2110  RooAbsReal& func = ft.asFUNC(pargv[0].c_str()) ;
2111 
2112  RooAbsReal* derivative(0) ;
2113  if (pargv.size()==2) {
2114  derivative = func.derivative(ft.asVAR(pargv[1].c_str()),1) ;
2115  } else {
2116  derivative = func.derivative(ft.asVAR(pargv[1].c_str()),ft.asINT(pargv[2].c_str())) ;
2117  }
2118 
2119  derivative->SetName(instName) ;
2120  if (ft.ws().import(*derivative,Silence())) ft.logError() ;
2121 
2122  } else if (cl=="cdf") {
2123 
2124  // cdf::name[pdf,obs,extranormobs]
2125 
2126  if (pargv.size()<2 || pargv.size()>3) {
2127  throw string(Form("cdf::%s, requires 2 or 3 arguments, have %d arguments",instName,(Int_t)pargv.size())) ;
2128  }
2129 
2130  RooAbsPdf& pdf = ft.asPDF(pargv[0].c_str()) ;
2131 
2132  RooAbsReal* cdf(0) ;
2133  if (pargv.size()==2) {
2134  cdf = pdf.createCdf(ft.asSET(pargv[1].c_str())) ;
2135  } else {
2136  cdf = pdf.createCdf(ft.asSET(pargv[1].c_str()),ft.asSET(pargv[2].c_str())) ;
2137  }
2138 
2139  cdf->SetName(instName) ;
2140  if (ft.ws().import(*cdf,Silence())) ft.logError() ;
2141 
2142 
2143  } else if (cl=="PROJ") {
2144 
2145  // PROJ::name(pdf,intobs)
2146  if (pargv.size()!=2) {
2147  throw string(Form("PROJ::%s, requires 2 arguments, have %d arguments",instName,(Int_t)pargv.size())) ;
2148  }
2149 
2150  RooAbsPdf& pdf = ft.asPDF(pargv[0].c_str()) ;
2151  RooAbsPdf* projection = pdf.createProjection(ft.asSET(pargv[1].c_str())) ;
2152  projection->SetName(instName) ;
2153 
2154  if (ft.ws().import(*projection,Silence())) ft.logError() ;
2155 
2156  } else if (cl=="set") {
2157 
2158  // set::name(arg,arg,...)
2159  if (ft.ws().defineSet(instName,pargs)) {
2160  ft.logError() ;
2161  return string(instName) ;
2162  }
2163 
2164  } else {
2165 
2166  throw string(Form("RooFactoryWSTool::SpecialsIFace::create() ERROR: Unknown meta-type %s",typeName)) ;
2167 
2168  }
2169  return string(instName) ;
2170 }
2171 
2172 
2174 {
2175  return _of ;
2176 }
2177 
virtual TObject * clone(const char *newname=0) const =0
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
RooRealVar * createVariable(const char *name, Double_t xmin, Double_t xmax)
Low-level factory interface for creating a RooRealVar with a given range and initial value...
RooAddPdf is an efficient implementation of a sum of PDFs of the form.
Definition: RooAddPdf.h:29
std::string processSingleExpression(const char *arg)
Process a single high-level expression.
static RooResolutionModel & as_RMODEL(UInt_t idx)
static long int sum(long int i)
Definition: Factory.cxx:2173
#define coutE(a)
Definition: RooMsgService.h:34
virtual Bool_t add(const RooAbsArg &var, Bool_t silent=kFALSE)
Add the specified argument to list.
float xmin
Definition: THbookFile.cxx:93
RooProduct * prodfunc(const char *objName, const char *pdfList)
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 isValidEnumValue(const char *typeName, const char *value)
TObject & asOBJ(const char *)
std::vector< std::string > splitFunctionArgs(const char *funcExpr)
Allocate and fill work buffer.
Bool_t isEnum(const char *typeName)
RooArgList asLIST(const char *)
CINT constructor interface, return constructor string argument #idx as RooArgList of objects found in...
static RooRealVar & as_VAR(UInt_t idx)
RooAddPdf * add(const char *objName, const char *specList, Bool_t recursiveCoefs=kFALSE)
RooProdPdf is an efficient implementation of a product of PDFs of the form.
Definition: RooProdPdf.h:31
#define cxcoutD(a)
Definition: RooMsgService.h:79
RooWorkspace & ws()
static RooFactoryWSTool * _of
Bool_t cancelTransaction()
Cancel an ongoing import transaction.
RooCmdArg NormSet(const RooArgSet &nset)
RooFactoryWSTool is a clase like TTree::MakeClass() that generates skeleton code for RooAbsPdf and Ro...
RooSimultaneous * simul(const char *objName, const char *indexCat, const char *pdfMap)
static std::map< std::string, IFace * > & hooks()
#define BUFFER_SIZE
#define gROOT
Definition: TROOT.h:402
RooCmdArg Conditional(const RooArgSet &pdfSet, const RooArgSet &depSet, Bool_t depsAreCond=kFALSE)
static RooAbsCategoryLValue & as_CATLV(UInt_t idx)
static Double_t as_DOUBLE(UInt_t idx)
RooAbsCategory & asCATFUNC(const char *)
CINT constructor interface, return constructor string argument #idx as RooAbsCategory reference found...
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
RooAbsArg * fundArg(const char *name) const
Return fundamental (i.e.
RooRealSumPdf * amplAdd(const char *objName, const char *specList)
RooAbsArg * arg(const char *name) const
Return RooAbsArg with given name. A null pointer is returned if none is found.
STL namespace.
Class RooRealSumPdf implements a PDF constructed from a sum of functions:
Definition: RooRealSumPdf.h:24
static RooAbsData & as_DATA(UInt_t idx)
static RooArgSet as_SET(UInt_t idx)
static void checkIndex(UInt_t index)
std::map< std::string, std::string > _typeAliases
std::vector< std::string > _args
RooAbsReal * createCdf(const RooArgSet &iset, const RooArgSet &nset=RooArgSet())
Create a cumulative distribution function of this p.d.f in terms of the observables listed in iset...
Definition: RooAbsPdf.cxx:3050
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
RooAbsArg * process(const char *expr)
Process high-level object creation syntax Accepted forms of syntax are.
std::pair< std::list< std::string >, unsigned int > ctorArgs(const char *classname, UInt_t nMinArgs=0)
static RooAbsRealLValue & as_VARLV(UInt_t idx)
const char * asSTRING(const char *)
CINT constructor interface, return constructor string argument #idx as const char*.
RooDataSet is a container class to hold N-dimensional binned data.
Definition: RooDataHist.h:40
virtual RooAbsArg * addColumn(RooAbsArg &var, Bool_t adjustRange=kTRUE)
Add a column with the values of the given (function) argument to this dataset.
Bool_t startTransaction()
Open an import transaction operations.
void Class()
Definition: Class.C:29
std::string varTag(std::string &func, std::vector< std::string > &args)
static RooAbsPdf & as_PDF(UInt_t idx)
RooResolutionModel & asRMODEL(const char *)
CINT constructor interface, return constructor string argument #idx as RooResolutionModel reference f...
static RooDataSet & as_DSET(UInt_t idx)
std::string processExpression(const char *expr)
Process a single high-level expression or list of expressions.
RooCmdArg Silence(Bool_t flag=kTRUE)
virtual RooAbsPdf * createProjection(const RooArgSet &iset)
Return a p.d.f that represent a projection of this p.d.f integrated over given observables.
Definition: RooAbsPdf.cxx:3012
RooAbsCategoryLValue is the common abstract base class for objects that represent a discrete value th...
RooCategory * cat(const char *name) const
Retrieve discrete variable (RooCategory) with given name. A null pointer is returned if not found...
std::string processAliasExpression(const char *arg)
Parse token.
static RooArgList as_LIST(UInt_t idx)
RooRealVar represents a fundamental (non-derived) real valued object.
Definition: RooRealVar.h:36
RooAbsArg & asARG(const char *)
CINT constructor interface, return constructor string argument #idx as RooAbsArg reference found in w...
RooAbsCategoryLValue & asCATLV(const char *)
CINT constructor interface, return constructor string argument #idx as RooAbsCategoryLValue reference...
std::string trueName(const char *typeDefName)
RooAbsData * data(const char *name) const
Retrieve dataset (binned or unbinned) with given name. A null pointer is returned if not found...
static Int_t init()
static const char * as_STRING(UInt_t idx)
RooRealVar & asVAR(const char *)
CINT constructor interface, return constructor string argument #idx as RooRealVar reference found in ...
Int_t asINT(const char *)
CINT constructor interface, return constructor string argument #idx as Int_t.
virtual void Add(TObject *arg)
Definition: RooLinkedList.h:62
Int_t getSize() const
RooAbsReal * createIntegral(const RooArgSet &iset, const RooCmdArg &arg1, const RooCmdArg &arg2=RooCmdArg::none(), const RooCmdArg &arg3=RooCmdArg::none(), const RooCmdArg &arg4=RooCmdArg::none(), const RooCmdArg &arg5=RooCmdArg::none(), const RooCmdArg &arg6=RooCmdArg::none(), const RooCmdArg &arg7=RooCmdArg::none(), const RooCmdArg &arg8=RooCmdArg::none()) const
Create an object that represents the integral of the function over one or more observables listed in ...
Definition: RooAbsReal.cxx:501
Class RooNLLVar implements a a -log(likelihood) calculation from a dataset and a PDF.
Definition: RooNLLVar.h:26
RooAbsReal & asFUNC(const char *)
CINT constructor interface, return constructor string argument #idx as RooAbsReal reference found in ...
std::stack< std::string > _autoNamePrefix
Bool_t defineSet(const char *name, const RooArgSet &aset, Bool_t importMissing=kFALSE)
Define a named RooArgSet with given constituents.
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition: TObject.cxx:443
unsigned int UInt_t
Definition: RtypesCore.h:42
void SetName(const char *name)
Set the name of the TNamed.
Definition: RooAbsArg.cxx:2386
char * Form(const char *fmt,...)
static RooDataHist & as_DHIST(UInt_t idx)
RooArgSet asSET(const char *)
CINT constructor interface, return constructor string argument #idx as RooArgSet of objects found in ...
The ROOT global object gROOT contains a list of all defined classes.
Definition: TClass.h:75
RooAbsData is the common abstract base class for binned and unbinned datasets.
Definition: RooAbsData.h:37
float xmax
Definition: THbookFile.cxx:93
Bool_t InheritsFrom(const char *cl) const
Return kTRUE if this class inherits from a class with name "classname".
Definition: TClass.cxx:4688
std::string processCreateArg(std::string &func, std::vector< std::string > &args)
Glue function between high-level syntax and low-level factory call to createArg: Process a parsed cal...
RooDataHist & asDHIST(const char *)
CINT constructor interface, return constructor string argument #idx as RooDataHist object found in wo...
RooDataSet is a container class to hold unbinned data.
Definition: RooDataSet.h:29
RooCategory represents a fundamental (non-derived) discrete value object.
Definition: RooCategory.h:24
static Int_t as_INT(UInt_t idx)
RooProduct a RooAbsReal implementation that represent the product of a given set of other RooAbsReal ...
Definition: RooProduct.h:32
TObject * obj(const char *name) const
Return any type of object (RooAbsArg, RooAbsData or generic object) with given name) ...
const Bool_t kFALSE
Definition: RtypesCore.h:88
RooProdPdf * prod(const char *objName, const char *pdfList)
RooFactoryWSTool(RooWorkspace &ws)
static RooFactoryWSTool * of()
RooAbsRealLValue & asVARLV(const char *)
CINT constructor interface, return constructor string argument #idx as RooAbsRealLValue reference fou...
RooAbsData & asDATA(const char *)
CINT constructor interface, return constructor string argument #idx as RooAbsData object found in wor...
RooLinkedList is an collection class for internal use, storing a collection of RooAbsArg pointers in ...
Definition: RooLinkedList.h:35
Double_t asDOUBLE(const char *)
CINT constructor interface, return constructor string argument #idx as Double_t.
void Delete(Option_t *o=0)
Remove all elements in collection and delete all elements NB: Collection does not own elements...
#define ClassImp(name)
Definition: Rtypes.h:359
RooAbsPdf * pdf(const char *name) const
Retrieve p.d.f (RooAbsPdf) with given name. A null pointer is returned if not found.
double Double_t
Definition: RtypesCore.h:55
RooAbsReal is the common abstract base class for objects that represent a real value and implements f...
Definition: RooAbsReal.h:53
RooAddition * addfunc(const char *objName, const char *specList)
std::vector< std::string > ctorArgs(const char *className)
static RooAbsCategory & as_CATFUNC(UInt_t idx)
RooDataSet & asDSET(const char *)
CINT constructor interface, return constructor string argument #idx as RooDataSet object found in wor...
static constexpr double s
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition: TClass.cxx:2887
RooRealVar * var(const char *name) const
Retrieve real-valued variable (RooRealVar) with given name. A null pointer is returned if not found...
TClass * resolveClassName(const char *className)
static std::map< std::string, IFace * > * _hooks
virtual TObject * Clone(const char *newname="") const
Make a clone of an object using the Streamer facility.
Definition: TNamed.cxx:74
Mother of all ROOT objects.
Definition: TObject.h:37
std::string create(RooFactoryWSTool &ft, const char *typeName, const char *instanceName, std::vector< std::string > args)
Concatenate list of args into comma separated string.
void clearError()
Associated workspace.
Bool_t commitTransaction()
typedef void((*Func_t)())
RooConstVar & RooConst(Double_t val)
Ta Range(0, 0, 1, 1)
RooAbsRealLValue is the common abstract base class for objects that represent a real value that may a...
RooAbsPdf is the abstract interface for all probability density functions The class provides hybrid a...
Definition: RooAbsPdf.h:41
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.
auto * l
Definition: textangle.C:4
RooCategory & asCAT(const char *)
CINT constructor interface, return constructor string argument #idx as RooCategory reference found in...
RooAbsCategory is the common abstract base class for objects that represent a discrete value with a f...
const RooArgSet * set(const char *name)
Return pointer to previously defined named set with given nmame If no such set is found a null pointe...
std::string processCompositeExpression(const char *arg)
Process a single composite expression.
std::string processCreateVar(std::string &func, std::vector< std::string > &args)
Glue function between high-level syntax and low-level factory call to createVariable: Process a parse...
Bool_t defineType(const char *label)
Define a state with given name, the lowest available positive integer is assigned as index...
std::string processListExpression(const char *arg)
Process a list of high-level expression.
static void registerSpecial(const char *typeName, RooFactoryWSTool::IFace *iface)
Register foreign special objects in factory.
RooAddition calculates the sum of a set of RooAbsReal terms, or when constructed with two sets...
Definition: RooAddition.h:26
RooDerivative * derivative(RooRealVar &obs, Int_t order=1, Double_t eps=0.001)
Return function representing first, second or third order derivative of this function.
Definition: first.py:1
RooAbsArg is the common abstract base class for objects that represent a value (of arbitrary type) an...
Definition: RooAbsArg.h:66
RooCategory * createCategory(const char *name, const char *stateNameList=0)
Low-level factory interface for creating a RooCategory with a given list of state names...
std::string processMetaArg(std::string &func, std::vector< std::string > &args)
Concatenate list of args into comma separated string.
RooWorkspace * _ws
RooAbsArg * createArg(const char *className, const char *objName, const char *varList)
Low-level factory interface for creating a RooAbsPdf of a given class with a given list of input vari...
RooStringVar implements a string values RooAbsArg.
Definition: RooStringVar.h:23
RooSimultaneous facilitates simultaneous fitting of multiple PDFs to subsets of a given dataset...
const Bool_t kTRUE
Definition: RtypesCore.h:87
RooAbsPdf & asPDF(const char *)
CINT constructor interface, return constructor string argument #idx as RooAbsPdf reference found in w...
Bool_t checkSyntax(const char *arg)
Perform basic syntax on given factory expression.
static TObject & as_OBJ(UInt_t idx)
static RooCategory & as_CAT(UInt_t idx)
char name[80]
Definition: TGX11.cxx:109
static Int_t dummy
static RooAbsArg & as_ARG(UInt_t idx)
static RooAbsReal & as_FUNC(UInt_t idx)
The RooWorkspace is a persistable container for RooFit projects.
Definition: RooWorkspace.h:42
virtual std::string create(RooFactoryWSTool &ft, const char *typeName, const char *instanceName, std::vector< std::string > args)=0
virtual ~RooFactoryWSTool()
Destructor.