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