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