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