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