ROOT  6.06/09
Reference Guide
RooClassFactory.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 // RooClassFactory 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 #include "TClass.h"
30 #include "RooClassFactory.h"
31 #include "RooErrorHandler.h"
32 #include "RooAbsReal.h"
33 #include "RooAbsCategory.h"
34 #include "RooArgList.h"
35 #include "RooMsgService.h"
36 #include "TInterpreter.h"
37 #include "RooWorkspace.h"
38 #include "RooGlobalFunc.h"
39 #include "RooAbsPdf.h"
40 #include <fstream>
41 #include <vector>
42 #include <string>
43 
44 using namespace std ;
45 
47 ;
48 
49 static Int_t init();
50 
51 static Int_t dummy = init() ;
52 
53 static Int_t init()
54 {
56  RooFactoryWSTool::registerSpecial("CEXPR",iface) ;
57  RooFactoryWSTool::registerSpecial("cexpr",iface) ;
58  (void)dummy;
59  return 0 ;
60 }
61 
62 
63 
64 
65 ////////////////////////////////////////////////////////////////////////////////
66 /// Default constructor
67 
69 {
70 }
71 
72 
73 
74 ////////////////////////////////////////////////////////////////////////////////
75 /// Destructor
76 
78 {
79 }
80 
81 
82 
83 ////////////////////////////////////////////////////////////////////////////////
84 
85 Bool_t RooClassFactory::makeAndCompilePdf(const char* name, const char* expression, const RooArgList& vars, const char* intExpression)
86 {
87  string realArgNames,catArgNames ;
88  TIterator* iter = vars.createIterator() ;
89  RooAbsArg* arg ;
90  while((arg=(RooAbsArg*)iter->Next())) {
91  if (dynamic_cast<RooAbsReal*>(arg)) {
92  if (realArgNames.size()>0) realArgNames += "," ;
93  realArgNames += arg->GetName() ;
94  } else if (dynamic_cast<RooAbsCategory*>(arg)) {
95  if (catArgNames.size()>0) catArgNames += "," ;
96  catArgNames += arg->GetName() ;
97  } else {
98  oocoutE((RooAbsArg*)0,InputArguments) << "RooClassFactory::makeAndCompilePdf ERROR input argument " << arg->GetName()
99  << " is neither RooAbsReal nor RooAbsCategory and is ignored" << endl ;
100  }
101  }
102  delete iter ;
103 
104  Bool_t ret = makePdf(name,realArgNames.c_str(),catArgNames.c_str(),expression,intExpression?kTRUE:kFALSE,kFALSE,intExpression) ;
105  if (ret) {
106  return ret ;
107  }
108 
109  if (gInterpreter->GetRootMapFiles()==0) {
110  gInterpreter->EnableAutoLoading() ;
111  }
112 
114  gInterpreter->ProcessLineSynch(Form(".L %s.cxx+",name),&ecode) ;
115  return (ecode!=TInterpreter::kNoError) ;
116 }
117 
118 
119 
120 ////////////////////////////////////////////////////////////////////////////////
121 /// Write, compile and load code for a RooAbsReal implementation with
122 /// class name 'name', taking all elements of 'vars' as constructor
123 /// arguments. The initial value expression is taken to be
124 /// 'expression' which can be any one-line C++ expression in terms of
125 /// variables that occur in 'vars'. You can add optional expressions
126 /// for analytical integrals to be advertised by your class in the
127 /// syntax
128 /// "<intObsName>:<CPPAnaIntExpression>;<intObsName,intObsName>:<CPPAnaIntExpression>"
129 /// where <intObsName> a name of the observable integrated over and
130 /// <CPPAnaIntExpression> is the C++ expression that calculates that
131 /// integral.
132 
133 Bool_t RooClassFactory::makeAndCompileFunction(const char* name, const char* expression, const RooArgList& vars, const char* intExpression)
134 {
135  string realArgNames,catArgNames ;
136  TIterator* iter = vars.createIterator() ;
137  RooAbsArg* arg ;
138  while((arg=(RooAbsArg*)iter->Next())) {
139  if (dynamic_cast<RooAbsReal*>(arg)) {
140  if (realArgNames.size()>0) realArgNames += "," ;
141  realArgNames += arg->GetName() ;
142  } else if (dynamic_cast<RooAbsCategory*>(arg)) {
143  if (catArgNames.size()>0) catArgNames += "," ;
144  catArgNames += arg->GetName() ;
145  } else {
146  oocoutE((RooAbsArg*)0,InputArguments) << "RooClassFactory::makeAndCompileFunction ERROR input argument " << arg->GetName()
147  << " is neither RooAbsReal nor RooAbsCategory and is ignored" << endl ;
148  }
149  }
150  delete iter ;
151 
152  Bool_t ret = makeFunction(name,realArgNames.c_str(),catArgNames.c_str(),expression,intExpression?kTRUE:kFALSE,intExpression) ;
153  if (ret) {
154  return ret ;
155  }
156 
157  if (gInterpreter->GetRootMapFiles()==0) {
158  gInterpreter->EnableAutoLoading() ;
159  }
160 
162  gInterpreter->ProcessLineSynch(Form(".L %s.cxx+",name),&ecode) ;
163  return (ecode!=TInterpreter::kNoError) ;
164 }
165 
166 
167 ////////////////////////////////////////////////////////////////////////////////
168 /// Write, compile and load code and instantiate object for a
169 /// RooAbsReal implementation with class name 'name', taking all
170 /// elements of 'vars' as constructor arguments. The initial value
171 /// expression is taken to be 'expression' which can be any one-line
172 /// C++ expression in terms of variables that occur in 'vars'.
173 ///
174 /// The returned object is an instance of the object you just defined
175 /// connected to the variables listed in 'vars'. The name of the
176 /// object is 'name', its class name Roo<name>Class.
177 ///
178 /// This function is an effective compiled replacement of RooFormulaVar
179 ///
180 /// You can add optional expressions for analytical integrals to be
181 /// advertised by your class in the syntax
182 /// "<intObsName>:<CPPAnaIntExpression>;<intObsName,intObsName>:<CPPAnaIntExpression>"
183 /// where <intObsName> a name of the observable integrated over and
184 /// <CPPAnaIntExpression> is the C++ expression that calculates that
185 /// integral.
186 
187 RooAbsReal* RooClassFactory::makeFunctionInstance(const char* name, const char* expression, const RooArgList& vars, const char* intExpression)
188 {
189  // Construct unique class name for this function expression
190  string tmpName(name) ;
191  tmpName[0] = toupper(tmpName[0]) ;
192  string className = Form("Roo%sFunc",tmpName.c_str()) ;
193 
194  return makeFunctionInstance(className.c_str(),name,expression,vars,intExpression) ;
195 }
196 
197 ////////////////////////////////////////////////////////////////////////////////
198 /// Write, compile and load code and instantiate object for a
199 /// RooAbsReal implementation with class name 'name', taking all
200 /// elements of 'vars' as constructor arguments. The initial value
201 /// expression is taken to be 'expression' which can be any one-line
202 /// C++ expression in terms of variables that occur in 'vars'.
203 ///
204 /// The returned object is an instance of the object you just defined
205 /// connected to the variables listed in 'vars'. The name of the
206 /// object is 'name', its class name Roo<name>Class.
207 ///
208 /// This function is an effective compiled replacement of RooFormulaVar
209 ///
210 /// You can add optional expressions for analytical integrals to be
211 /// advertised by your class in the syntax
212 /// "<intObsName>:<CPPAnaIntExpression>;<intObsName,intObsName>:<CPPAnaIntExpression>"
213 /// where <intObsName> a name of the observable integrated over and
214 /// <CPPAnaIntExpression> is the C++ expression that calculates that
215 /// integral.
216 
217 RooAbsReal* RooClassFactory::makeFunctionInstance(const char* className, const char* name, const char* expression, const RooArgList& vars, const char* intExpression)
218 {
219  if (gInterpreter->GetRootMapFiles()==0) {
220  gInterpreter->EnableAutoLoading() ;
221  }
222 
223  // Use class factory to compile and link specialized function
224  Bool_t error = makeAndCompileFunction(className,expression,vars,intExpression) ;
225 
226  // Check that class was created OK
227  if (error) {
229  }
230 
231  // Create CINT line that instantiates specialized object
232  string line = Form("new %s(\"%s\",\"%s\"",className,name,name) ;
233 
234  // Make list of pointer values (represented in hex ascii) to be passed to cint
235  // Note that the order of passing arguments must match the convention in which
236  // the class code is generated: first all reals, then all categories
237 
238  TIterator* iter = vars.createIterator() ;
239  string argList ;
240  // First pass the RooAbsReal arguments in the list order
241  RooAbsArg* var ;
242  while((var=(RooAbsArg*)iter->Next())) {
243  if (dynamic_cast<RooAbsReal*>(var)) {
244  argList += Form(",*((RooAbsReal*)0x%lx)",(ULong_t)var) ;
245  }
246  }
247  iter->Reset() ;
248  // Next pass the RooAbsCategory arguments in the list order
249  while((var=(RooAbsArg*)iter->Next())) {
250  if (dynamic_cast<RooAbsCategory*>(var)) {
251  argList += Form(",*((RooAbsCategory*)0x%lx)",(ULong_t)var) ;
252  }
253  }
254  delete iter ;
255 
256  line += argList + ") ;" ;
257 
258  // Let CINT instantiate specialized formula
259  return (RooAbsReal*) gInterpreter->ProcessLineSynch(line.c_str()) ;
260 }
261 
262 
263 
264 
265 ////////////////////////////////////////////////////////////////////////////////
266 /// Write, compile and load code and instantiate object for a
267 /// RooAbsPdf implementation with class name 'name', taking all
268 /// elements of 'vars' as constructor arguments. The initial value
269 /// expression is taken to be 'expression' which can be any one-line
270 /// C++ expression in terms of variables that occur in 'vars'.
271 ///
272 /// The returned object is an instance of the object you just defined
273 /// connected to the variables listed in 'vars'. The name of the
274 /// object is 'name', its class name Roo<name>Class.
275 ///
276 /// This function is an effective compiled replacement of RooGenericPdf
277 ///
278 /// You can add optional expressions for analytical integrals to be
279 /// advertised by your class in the syntax
280 /// "<intObsName>:<CPPAnaIntExpression>;<intObsName,intObsName>:<CPPAnaIntExpression>"
281 /// where <intObsName> a name of the observable integrated over and
282 /// <CPPAnaIntExpression> is the C++ expression that calculates that
283 /// integral.
284 
285 RooAbsPdf* RooClassFactory::makePdfInstance(const char* name, const char* expression,
286  const RooArgList& vars, const char* intExpression)
287 {
288  // Construct unique class name for this function expression
289  string tmpName(name) ;
290  tmpName[0] = toupper(tmpName[0]) ;
291  string className = Form("Roo%sPdf",tmpName.c_str()) ;
292 
293  return makePdfInstance(className.c_str(),name,expression,vars,intExpression) ;
294 }
295 
296 ////////////////////////////////////////////////////////////////////////////////
297 /// Write, compile and load code and instantiate object for a
298 /// RooAbsPdf implementation with class name 'name', taking all
299 /// elements of 'vars' as constructor arguments. The initial value
300 /// expression is taken to be 'expression' which can be any one-line
301 /// C++ expression in terms of variables that occur in 'vars'.
302 ///
303 /// The returned object is an instance of the object you just defined
304 /// connected to the variables listed in 'vars'. The name of the
305 /// object is 'name', its class name Roo<name>Class.
306 ///
307 /// This function is an effective compiled replacement of RooGenericPdf
308 ///
309 /// You can add optional expressions for analytical integrals to be
310 /// advertised by your class in the syntax
311 /// "<intObsName>:<CPPAnaIntExpression>;<intObsName,intObsName>:<CPPAnaIntExpression>"
312 /// where <intObsName> a name of the observable integrated over and
313 /// <CPPAnaIntExpression> is the C++ expression that calculates that
314 /// integral.
315 
316 RooAbsPdf* RooClassFactory::makePdfInstance(const char* className, const char* name, const char* expression,
317  const RooArgList& vars, const char* intExpression)
318 {
319  if (gInterpreter->GetRootMapFiles()==0) {
320  gInterpreter->EnableAutoLoading() ;
321  }
322 
323  // Use class factory to compile and link specialized function
324  Bool_t error = makeAndCompilePdf(className,expression,vars,intExpression) ;
325 
326  // Check that class was created OK
327  if (error) {
329  }
330 
331  // Create CINT line that instantiates specialized object
332  string line = Form("new %s(\"%s\",\"%s\"",className,name,name) ;
333 
334  // Make list of pointer values (represented in hex ascii) to be passed to cint
335  // Note that the order of passing arguments must match the convention in which
336  // the class code is generated: first all reals, then all categories
337 
338  TIterator* iter = vars.createIterator() ;
339  string argList ;
340  // First pass the RooAbsReal arguments in the list order
341  RooAbsArg* var ;
342  while((var=(RooAbsArg*)iter->Next())) {
343  if (dynamic_cast<RooAbsReal*>(var)) {
344  argList += Form(",*((RooAbsReal*)0x%lx)",(ULong_t)var) ;
345  }
346  }
347  iter->Reset() ;
348  // Next pass the RooAbsCategory arguments in the list order
349  while((var=(RooAbsArg*)iter->Next())) {
350  if (dynamic_cast<RooAbsCategory*>(var)) {
351  argList += Form(",*((RooAbsCategory*)0x%lx)",(ULong_t)var) ;
352  }
353  }
354  delete iter ;
355 
356  line += argList + ") ;" ;
357 
358  // Let CINT instantiate specialized formula
359  return (RooAbsPdf*) gInterpreter->ProcessLineSynch(line.c_str()) ;
360 }
361 
362 
363 
364 ////////////////////////////////////////////////////////////////////////////////
365 /// Write code for a RooAbsPdf implementation with class name 'name',
366 /// taking RooAbsReal arguments with names listed in argNames and
367 /// RooAbsCategory arguments with names listed in catArgNames as
368 /// constructor arguments (use a comma separated list for multiple
369 /// arguments). The initial value expression is taken to be
370 /// 'expression' which can be any one-line C++ expression in terms of
371 /// variables that occur in 'vars'. Skeleton code for handling of
372 /// analytical integrals is added if hasAnaInt is true. You can add
373 /// optional expressions for analytical integrals to be advertised by
374 /// your class in the syntax
375 /// "<intObsName>:<CPPAnaIntExpression>;<intObsName,intObsName>:<CPPAnaIntExpression>"
376 /// where <intObsName> a name of the observable integrated over and
377 /// <CPPAnaIntExpression> is the C++ expression that calculates that
378 /// integral. Skeleton code for internal event generation is added
379 /// if hasIntGen is true
380 ///
381 
382 Bool_t RooClassFactory::makePdf(const char* name, const char* argNames, const char* catArgNames, const char* expression,
383  Bool_t hasAnaInt, Bool_t hasIntGen, const char* intExpression)
384 {
385  return makeClass("RooAbsPdf",name,argNames,catArgNames,expression,hasAnaInt,hasIntGen,intExpression) ;
386 }
387 
388 
389 ////////////////////////////////////////////////////////////////////////////////
390 /// Write code for a RooAbsReal implementation with class name 'name',
391 /// taking RooAbsReal arguments with names listed in argNames and
392 /// RooAbsCategory arguments with names listed in catArgNames as
393 /// constructor arguments (use a comma separated list for multiple
394 /// arguments). The initial value expression is taken to be
395 /// 'expression' which can be any one-line C++ expression in terms of
396 /// variables that occur in 'vars'. Skeleton code for handling of
397 /// analytical integrals is added if hasAnaInt is true. You can add
398 /// optional expressions for analytical integrals to be advertised by
399 /// your class in the syntax
400 /// "<intObsName>:<CPPAnaIntExpression>;<intObsName,intObsName>:<CPPAnaIntExpression>"
401 /// where <intObsName> a name of the observable integrated over and
402 /// <CPPAnaIntExpression> is the C++ expression that calculates that
403 /// integral.
404 
405 Bool_t RooClassFactory::makeFunction(const char* name, const char* argNames, const char* catArgNames, const char* expression, Bool_t hasAnaInt, const char* intExpression)
406 {
407  return makeClass("RooAbsReal",name,argNames,catArgNames,expression,hasAnaInt,kFALSE,intExpression) ;
408 }
409 
410 
411 ////////////////////////////////////////////////////////////////////////////////
412 /// Write code for a 'baseName' implementation with class name 'className',
413 /// taking RooAbsReal arguments with names listed in argNames and
414 /// RooAbsCategory arguments with names listed in catArgNames as
415 /// constructor arguments (use a comma separated list for multiple
416 /// arguments). The initial value expression is taken to be
417 /// 'expression' which can be any one-line C++ expression in terms of
418 /// variables that occur in 'vars'. Skeleton code for handling of
419 /// analytical integrals is added if hasAnaInt is true. You can add
420 /// optional expressions for analytical integrals to be advertised by
421 /// your class in the syntax
422 /// "<intObsName>:<CPPAnaIntExpression>;<intObsName,intObsName>:<CPPAnaIntExpression>"
423 /// where <intObsName> a name of the observable integrated over and
424 /// <CPPAnaIntExpression> is the C++ expression that calculates that
425 /// integral. Skeleton code for internal event generation is added
426 /// if hasIntGen is true
427 ///
428 
429 Bool_t RooClassFactory::makeClass(const char* baseName, const char* className, const char* realArgNames, const char* catArgNames,
430  const char* expression, Bool_t hasAnaInt, Bool_t hasIntGen, const char* intExpression)
431 {
432  // Check that arguments were given
433  if (!baseName) {
434  oocoutE((TObject*)0,InputArguments) << "RooClassFactory::makeClass: ERROR: a base class name must be given" << endl ;
435  return kTRUE ;
436  }
437 
438  if (!className) {
439  oocoutE((TObject*)0,InputArguments) << "RooClassFactory::makeClass: ERROR: a class name must be given" << endl ;
440  return kTRUE ;
441  }
442 
443  if ((!realArgNames || !*realArgNames) && (!catArgNames || !*catArgNames)) {
444  oocoutE((TObject*)0,InputArguments) << "RooClassFactory::makeClass: ERROR: A list of input argument names must be given" << endl ;
445  return kTRUE ;
446  }
447 
448  if (intExpression && !hasAnaInt) {
449  oocoutE((TObject*)0,InputArguments) << "RooClassFactory::makeClass: ERROR no analytical integration code requestion, but expression for analytical integral provided" << endl ;
450  return kTRUE ;
451  }
452 
453  // Parse comma separated list of argument names into list of strings
454  vector<string> alist ;
455  vector<bool> isCat ;
456 
457  if (realArgNames && *realArgNames) {
458  const size_t bufSize = strlen(realArgNames)+1;
459  char* buf = new char[bufSize] ;
460  strlcpy(buf,realArgNames,bufSize) ;
461  char* token = strtok(buf,",") ;
462  while(token) {
463  alist.push_back(token) ;
464  isCat.push_back(false) ;
465  token = strtok(0,",") ;
466  }
467  delete[] buf ;
468  }
469  if (catArgNames && *catArgNames) {
470  const size_t bufSize = strlen(catArgNames)+1;
471  char* buf = new char[bufSize] ;
472  strlcpy(buf,catArgNames,bufSize) ;
473  char* token = strtok(buf,",") ;
474  while(token) {
475  alist.push_back(token) ;
476  isCat.push_back(true) ;
477  token = strtok(0,",") ;
478  }
479  delete[] buf ;
480  }
481 
482  TString impFileName(className), hdrFileName(className) ;
483  impFileName += ".cxx" ;
484  hdrFileName += ".h" ;
485 
486  TString ifdefName(className) ;
487  ifdefName.ToUpper() ;
488 
489  ofstream hf(hdrFileName) ;
490  hf << "/*****************************************************************************" << endl
491  << " * Project: RooFit *" << endl
492  << " * *" << endl
493  << " * This code was autogenerated by RooClassFactory * " << endl
494  << " *****************************************************************************/" << endl
495  << endl
496  << "#ifndef " << ifdefName << endl
497  << "#define " << ifdefName << endl
498  << "" << endl
499  << "#include \"" << baseName << ".h\"" << endl
500  << "#include \"RooRealProxy.h\"" << endl
501  << "#include \"RooCategoryProxy.h\"" << endl
502  << "#include \"RooAbsReal.h\"" << endl
503  << "#include \"RooAbsCategory.h\"" << endl
504  << " " << endl
505  << "class " << className << " : public " << baseName << " {" << endl
506  << "public:" << endl
507  << " " << className << "() {} ; " << endl
508  << " " << className << "(const char *name, const char *title," << endl ;
509 
510  // Insert list of input arguments
511  unsigned int i ;
512  for (i=0 ; i<alist.size() ; i++) {
513  if (!isCat[i]) {
514  hf << " RooAbsReal& _" ;
515  } else {
516  hf << " RooAbsCategory& _" ;
517  }
518  hf << alist[i] ;
519  if (i==alist.size()-1) {
520  hf << ");" << endl ;
521  } else {
522  hf << "," << endl ;
523  }
524  }
525 
526  hf << " " << className << "(const " << className << "& other, const char* name=0) ;" << endl
527  << " virtual TObject* clone(const char* newname) const { return new " << className << "(*this,newname); }" << endl
528  << " inline virtual ~" << className << "() { }" << endl
529  << endl ;
530 
531  if (hasAnaInt) {
532  hf << " Int_t getAnalyticalIntegral(RooArgSet& allVars, RooArgSet& analVars, const char* rangeName=0) const ;" << endl
533  << " Double_t analyticalIntegral(Int_t code, const char* rangeName=0) const ;" << endl
534  << "" << endl ;
535  }
536 
537  if (hasIntGen) {
538  hf << " Int_t getGenerator(const RooArgSet& directVars, RooArgSet &generateVars, Bool_t staticInitOK=kTRUE) const;" << endl
539  << " void initGenerator(Int_t code) {} ; // optional pre-generation initialization" << endl
540  << " void generateEvent(Int_t code);" << endl
541  << endl ;
542  }
543 
544  hf << "protected:" << endl
545  << "" << endl ;
546 
547  // Insert list of input arguments
548  for (i=0 ; i<alist.size() ; i++) {
549  if (!isCat[i]) {
550  hf << " RooRealProxy " << alist[i] << " ;" << endl ;
551  } else {
552  hf << " RooCategoryProxy " << alist[i] << " ;" << endl ;
553  }
554  }
555 
556  hf << " " << endl
557  << " Double_t evaluate() const ;" << endl
558  << "" << endl
559  << "private:" << endl
560  << "" << endl
561  << " ClassDef(" << className << ",1) // Your description goes here..." << endl
562  << "};" << endl
563  << " " << endl
564  << "#endif" << endl ;
565 
566 
567  ofstream cf(impFileName) ;
568 
569  cf << "/***************************************************************************** " << endl
570  << " * Project: RooFit * " << endl
571  << " * * " << endl
572  << " * This code was autogenerated by RooClassFactory * " << endl
573  << " *****************************************************************************/ " << endl
574  << endl
575  << "// Your description goes here... " << endl
576  << endl
577 
578  << "#include \"Riostream.h\" " << endl
579  << endl
580 
581  << "#include \"" << className << ".h\" " << endl
582  << "#include \"RooAbsReal.h\" " << endl
583  << "#include \"RooAbsCategory.h\" " << endl
584  << "#include <math.h> " << endl
585  << "#include \"TMath.h\" " << endl
586  << endl
587 
588  << "ClassImp(" << className << ") " << endl
589  << endl
590 
591  << " " << className << "::" << className << "(const char *name, const char *title, " << endl ;
592 
593  // Insert list of proxy constructors
594  for (i=0 ; i<alist.size() ; i++) {
595  if (!isCat[i]) {
596  cf << " RooAbsReal& _" << alist[i] ;
597  } else {
598  cf << " RooAbsCategory& _" << alist[i] ;
599  }
600  if (i<alist.size()-1) {
601  cf << "," ;
602  } else {
603  cf << ") :" ;
604  }
605  cf << endl ;
606  }
607 
608  // Insert base class constructor
609  cf << " " << baseName << "(name,title), " << endl ;
610 
611  // Insert list of proxy constructors
612  for (i=0 ; i<alist.size() ; i++) {
613  cf << " " << alist[i] << "(\"" << alist[i] << "\",\"" << alist[i] << "\",this,_" << alist[i] << ")" ;
614  if (i<alist.size()-1) {
615  cf << "," ;
616  }
617  cf << endl ;
618  }
619 
620  cf << " { " << endl
621  << " } " << endl
622  << endl
623  << endl
624 
625  << " " << className << "::" << className << "(const " << className << "& other, const char* name) : " << endl
626  << " " << baseName << "(other,name), " << endl ;
627 
628  for (i=0 ; i<alist.size() ; i++) {
629  cf << " " << alist[i] << "(\"" << alist[i] << "\",this,other." << alist[i] << ")" ;
630  if (i<alist.size()-1) {
631  cf << "," ;
632  }
633  cf << endl ;
634  }
635 
636  cf << " { " << endl
637  << " } " << endl
638  << endl
639  << endl
640  << endl
641 
642  << " Double_t " << className << "::evaluate() const " << endl
643  << " { " << endl
644  << " // ENTER EXPRESSION IN TERMS OF VARIABLE ARGUMENTS HERE " << endl
645  << " return " << expression << " ; " << endl
646  << " } " << endl
647  << endl
648  << endl
649  << endl ;
650 
651  if (hasAnaInt) {
652 
653  vector<string> intObs ;
654  vector<string> intExpr ;
655  // Parse analytical integration expression if provided
656  // Expected form is observable:expression,observable,observable:expression;[...]
657  if (intExpression && *intExpression) {
658  const size_t bufSize = strlen(intExpression)+1;
659  char* buf = new char[bufSize] ;
660  strlcpy(buf,intExpression,bufSize) ;
661  char* ptr = strtok(buf,":") ;
662  while(ptr) {
663  intObs.push_back(ptr) ;
664  intExpr.push_back(strtok(0,";")) ;
665  ptr = strtok(0,":") ;
666  }
667  delete[] buf ;
668  }
669 
670  cf << " Int_t " << className << "::getAnalyticalIntegral(RooArgSet& allVars, RooArgSet& analVars, const char* /*rangeName*/) const " << endl
671  << " { " << endl
672  << " // LIST HERE OVER WHICH VARIABLES ANALYTICAL INTEGRATION IS SUPPORTED, " << endl
673  << " // ASSIGN A NUMERIC CODE FOR EACH SUPPORTED (SET OF) PARAMETERS " << endl
674  << " // THE EXAMPLE BELOW ASSIGNS CODE 1 TO INTEGRATION OVER VARIABLE X" << endl
675  << " // YOU CAN ALSO IMPLEMENT MORE THAN ONE ANALYTICAL INTEGRAL BY REPEATING THE matchArgs " << endl
676  << " // EXPRESSION MULTIPLE TIMES" << endl
677  << endl ;
678 
679  if (intObs.size()>0) {
680  for (UInt_t ii=0 ; ii<intObs.size() ; ii++) {
681  cf << " if (matchArgs(allVars,analVars," << intObs[ii] << ")) return " << ii+1 << " ; " << endl ;
682  }
683  } else {
684  cf << " // if (matchArgs(allVars,analVars,x)) return 1 ; " << endl ;
685  }
686 
687  cf << " return 0 ; " << endl
688  << " } " << endl
689  << endl
690  << endl
691  << endl
692 
693  << " Double_t " << className << "::analyticalIntegral(Int_t code, const char* rangeName) const " << endl
694  << " { " << endl
695  << " // RETURN ANALYTICAL INTEGRAL DEFINED BY RETURN CODE ASSIGNED BY getAnalyticalIntegral" << endl
696  << " // THE MEMBER FUNCTION x.min(rangeName) AND x.max(rangeName) WILL RETURN THE INTEGRATION" << endl
697  << " // BOUNDARIES FOR EACH OBSERVABLE x" << endl
698  << endl ;
699 
700  if (intObs.size()>0) {
701  for (UInt_t ii=0 ; ii<intObs.size() ; ii++) {
702  cf << " if (code==" << ii+1 << ") { return (" << intExpr[ii] << ") ; } " << endl ;
703  }
704  } else {
705  cf << " // assert(code==1) ; " << endl
706  << " // return (x.max(rangeName)-x.min(rangeName)) ; " << endl ;
707  }
708 
709  cf << " return 0 ; " << endl
710  << " } " << endl
711  << endl
712  << endl
713  << endl ;
714  }
715 
716  if (hasIntGen) {
717  cf << " Int_t " << className << "::getGenerator(const RooArgSet& directVars, RooArgSet &generateVars, Bool_t /*staticInitOK*/) const " << endl
718  << " { " << endl
719  << " // LIST HERE OVER WHICH VARIABLES INTERNAL GENERATION IS SUPPORTED, " << endl
720  << " // ASSIGN A NUMERIC CODE FOR EACH SUPPORTED (SET OF) PARAMETERS " << endl
721  << " // THE EXAMPLE BELOW ASSIGNS CODE 1 TO INTEGRATION OVER VARIABLE X" << endl
722  << " // YOU CAN ALSO IMPLEMENT MORE THAN ONE GENERATOR CONFIGURATION BY REPEATING THE matchArgs " << endl
723  << " // EXPRESSION MULTIPLE TIMES. IF THE FLAG staticInitOK IS TRUE THEN IT IS SAFE TO PRECALCULATE " << endl
724  << " // INTERMEDIATE QUANTITIES IN initGenerator(), IF IT IS NOT SET THEN YOU SHOULD NOT ADVERTISE" << endl
725  << " // ANY GENERATOR METHOD THAT RELIES ON PRECALCULATIONS IN initGenerator()" << endl
726  << endl
727  << " // if (matchArgs(directVars,generateVars,x)) return 1 ; " << endl
728  << " return 0 ; " << endl
729  << " } " << endl
730  << endl
731  << endl
732  << endl
733 
734  << " void " << className << "::generateEvent(Int_t code) " << endl
735  << " { " << endl
736  << " // GENERATE SET OF OBSERVABLES DEFINED BY RETURN CODE ASSIGNED BY getGenerator()" << endl
737  << " // RETURN THE GENERATED VALUES BY ASSIGNING THEM TO THE PROXY DATA MEMBERS THAT" << endl
738  << " // REPRESENT THE CHOSEN OBSERVABLES" << endl
739  << endl
740  << " // assert(code==1) ; " << endl
741  << " // x = 0 ; " << endl
742  << " return; " << endl
743  << " } " << endl
744  << endl
745  << endl
746  << endl ;
747  }
748 
749 
750  return kFALSE ;
751 }
752 
753 ////////////////////////////////////////////////////////////////////////////////
754 
755 std::string RooClassFactory::ClassFacIFace::create(RooFactoryWSTool& ft, const char* typeName, const char* instanceName, std::vector<std::string> args)
756 {
757  static int classCounter = 0 ;
758 
759  string tn(typeName) ;
760  if (tn=="CEXPR" || tn=="cexpr") {
761 
762  if (args.size()<2) {
763  throw string(Form("RooClassFactory::ClassFacIFace::create() ERROR: CEXPR requires at least 2 arguments (expr,var,...), but only %u args found",
764  (UInt_t)args.size())) ;
765  }
766 
767  RooAbsArg* ret ;
768  // Strip quotation marks from expression string
769  char expr[1024] ;
770  strncpy(expr,args[0].c_str()+1,args[0].size()-2) ;
771  expr[args[0].size()-2]=0 ;
772 
773 
774  RooArgList varList ;
775 
776  try {
777  if (args.size()==2) {
778  // Interpret 2nd arg as list
779  varList.add(ft.asLIST(args[1].c_str())) ;
780  } else {
781  for (unsigned int i=1 ; i<args.size() ; i++) {
782  varList.add(ft.asARG(args[i].c_str())) ;
783  }
784  }
785  } catch (string err) {
786  throw string(Form("RooClassFactory::ClassFacIFace::create() ERROR: %s",err.c_str())) ;
787  }
788 
789  string className ;
790  while(true) {
791  className = Form("RooCFAuto%03d%s%s",classCounter,(tn=="CEXPR")?"Pdf":"Func",ft.autoClassNamePostFix()) ;
792  TClass* tc = TClass::GetClass(className.c_str(),kTRUE,kTRUE) ;
793  classCounter++ ;
794  if (!tc) {
795  break ;
796  }
797  }
798 
799  if (tn=="CEXPR") {
800  ret = makePdfInstance(className.c_str(),instanceName,expr,varList) ;
801  } else {
802  ret = makeFunctionInstance(className.c_str(),instanceName,expr,varList) ;
803  }
804  if (!ret) {
805  throw string(Form("RooClassFactory::ClassFacIFace::create() ERROR creating %s %s with RooClassFactory",((tn=="CEXPR")?"pdf":"function"),instanceName)) ;
806  }
807 
808  // Import object
809  ft.ws().import(*ret,RooFit::Silence()) ;
810 
811  // Import class code as well
812  ft.ws().importClassCode(ret->IsA()) ;
813 
814 
815  } else {
816 
817  throw string(Form("RooClassFactory::ClassFacIFace::create() ERROR: Unknown meta-type %s requested",typeName)) ;
818 
819  }
820  return string(instanceName) ;
821 }
static RooAbsPdf * makePdfInstance(const char *className, const char *name, const char *expression, const RooArgList &vars, const char *intExpression=0)
Write, compile and load code and instantiate object for a RooAbsPdf implementation with class name 'n...
virtual Bool_t add(const RooAbsArg &var, Bool_t silent=kFALSE)
Add the specified argument to list.
static void softAbort()
virtual void Reset()=0
TLine * line
RooArgList asLIST(const char *)
CINT constructor interface, return constructor string argument #idx as RooArgList of objects found in...
RooWorkspace & ws()
void ToUpper()
Change string to upper case.
Definition: TString.cxx:1101
Basic string class.
Definition: TString.h:137
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
const Bool_t kFALSE
Definition: Rtypes.h:92
#define gInterpreter
Definition: TInterpreter.h:502
STL namespace.
Iterator abstract base class.
Definition: TIterator.h:32
Bool_t importClassCode(const char *pat="*", Bool_t doReplace=kFALSE)
Inport code of all classes in the workspace that have a class name that matches pattern 'pat' and whi...
static RooAbsReal * makeFunctionInstance(const char *className, const char *name, const char *expression, const RooArgList &vars, const char *intExpression=0)
Write, compile and load code and instantiate object for a RooAbsReal implementation with class name '...
#define oocoutE(o, a)
Definition: RooMsgService.h:48
std::map< std::string, std::string >::const_iterator iter
Definition: TAlienJob.cxx:54
static Int_t dummy
TIterator * createIterator(Bool_t dir=kIterForward) const
RooCmdArg Silence(Bool_t flag=kTRUE)
RooAbsArg & asARG(const char *)
CINT constructor interface, return constructor string argument #idx as RooAbsArg reference found in w...
static Bool_t makePdf(const char *name, const char *realArgNames=0, const char *catArgNames=0, const char *expression="1.0", Bool_t hasAnaInt=kFALSE, Bool_t hasIntGen=kFALSE, const char *intExpression=0)
Write code for a RooAbsPdf implementation with class name 'name', taking RooAbsReal arguments with na...
static Bool_t makeFunction(const char *name, const char *realArgNames=0, const char *catArgNames=0, const char *expression="1.0", Bool_t hasAnaInt=kFALSE, const char *intExpression=0)
Write code for a RooAbsReal implementation with class name 'name', taking RooAbsReal arguments with n...
def makeClass(name)
Definition: cppyy.py:205
unsigned int UInt_t
Definition: RtypesCore.h:42
char * Form(const char *fmt,...)
RooClassFactory()
Default constructor.
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:51
The ROOT global object gROOT contains a list of all defined classes.
Definition: TClass.h:81
static Int_t init()
RooAbsReal is the common abstract base class for objects that represent a real value and implements f...
Definition: RooAbsReal.h:53
static Bool_t makeAndCompilePdf(const char *name, const char *expression, const RooArgList &vars, const char *intExpression=0)
unsigned long ULong_t
Definition: RtypesCore.h:51
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
#define name(a, b)
Definition: linkTestLib0.cpp:5
ClassImp(RooClassFactory)
Mother of all ROOT objects.
Definition: TObject.h:58
typedef void((*Func_t)())
std::string create(RooFactoryWSTool &ft, const char *typeName, const char *instanceName, std::vector< std::string > args)
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.
virtual TObject * Next()=0
virtual ~RooClassFactory()
Destructor.
static void registerSpecial(const char *typeName, RooFactoryWSTool::IFace *iface)
Register foreign special objects in factory.
RooAbsArg is the common abstract base class for objects that represent a value (of arbitrary type) an...
Definition: RooAbsArg.h:66
const Bool_t kTRUE
Definition: Rtypes.h:91
static Bool_t makeClass(const char *className, const char *name, const char *realArgNames=0, const char *catArgNames=0, const char *expression="1.0", Bool_t hasAnaInt=kFALSE, Bool_t hasIntGen=kFALSE, const char *intExpression=0)
Write code for a 'baseName' implementation with class name 'className', taking RooAbsReal arguments w...
const char * autoClassNamePostFix() const
static Bool_t makeAndCompileFunction(const char *name, const char *expression, const RooArgList &args, const char *intExpression=0)
Write, compile and load code for a RooAbsReal implementation with class name 'name', taking all elements of 'vars' as constructor arguments.