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