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