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
22RooClassFactory is a clase like TTree::MakeClass() that generates
23skeleton code for RooAbsPdf and RooAbsReal functions given
24a list of input parameter names. The factory can also compile
25the generated code on the fly, and on request also immediate
26instantiate 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
44using namespace std;
45
47
48namespace {
49
50static Int_t init();
51
52Int_t dummy = init();
53
54static Int_t init()
55{
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
86Bool_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
130Bool_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
180RooAbsReal* 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
210RooAbsReal* 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%zx)",(size_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%zx)",(size_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
274RooAbsPdf* 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
305RooAbsPdf* 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%zx)",(size_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%zx)",(size_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
367Bool_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
390Bool_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
414Bool_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
740std::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}
typedef void(GLAPIENTRYP _GLUfuncptr)(void)
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
#define oocoutE(o, a)
Definition: RooMsgService.h:48
const Bool_t kFALSE
Definition: RtypesCore.h:101
const Bool_t kTRUE
Definition: RtypesCore.h:100
#define ClassImp(name)
Definition: Rtypes.h:364
char name[80]
Definition: TGX11.cxx:110
#define gInterpreter
Definition: TInterpreter.h:562
char * Form(const char *fmt,...)
RooAbsArg is the common abstract base class for objects that represent a value and a "shape" in RooFi...
Definition: RooAbsArg.h:75
RooAbsCategory is the base class for objects that represent a discrete value with a finite number of ...
virtual Bool_t add(const RooAbsArg &var, Bool_t silent=kFALSE)
Add the specified argument to list.
TIterator * createIterator(Bool_t dir=kIterForward) const
TIterator-style iteration over contained elements.
RooAbsReal is the common abstract base class for objects that represent a real value and implements f...
Definition: RooAbsReal.h:63
RooArgList is a container object that can hold multiple RooAbsArg objects.
Definition: RooArgList.h:22
std::string create(RooFactoryWSTool &ft, const char *typeName, const char *instanceName, std::vector< std::string > args)
RooClassFactory is a clase like TTree::MakeClass() that generates skeleton code for RooAbsPdf and Roo...
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',...
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 '...
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...
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...
RooClassFactory()
Default constructor.
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...
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...
virtual ~RooClassFactory()
Destructor.
static Bool_t makeAndCompilePdf(const char *name, const char *expression, const RooArgList &vars, const char *intExpression=0)
static void softAbort()
RooFactoryWSTool is a class similar to TTree::MakeClass() that generates skeleton code for RooAbsPdf ...
RooWorkspace & ws()
const char * autoClassNamePostFix() const
RooAbsArg & asARG(const char *)
CINT constructor interface, return constructor string argument #idx as RooAbsArg reference found in w...
static void registerSpecial(const char *typeName, RooFactoryWSTool::IFace *iface)
Register foreign special objects in factory.
RooArgList asLIST(const char *)
CINT constructor interface, return constructor string argument #idx as RooArgList of objects found in...
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.
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...
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition: TClass.h:80
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
Iterator abstract base class.
Definition: TIterator.h:30
virtual void Reset()=0
virtual TObject * Next()=0
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
Mother of all ROOT objects.
Definition: TObject.h:37
Basic string class.
Definition: TString.h:136
void ToUpper()
Change string to upper case.
Definition: TString.cxx:1163
TLine * line
RooCmdArg Silence(Bool_t flag=kTRUE)
@ InputArguments
Definition: RooGlobalFunc.h:61