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