Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RooFactoryWSTool.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 RooFactoryWSTool.cxx
19\class RooFactoryWSTool
20\ingroup Roofitcore
21
22Implementation detail of the RooWorkspace.
23
24It interprets all expressions for RooWorkspace::factory(const char*).
25**/
26
27#include "RooFactoryWSTool.h"
28#include "RooAbsReal.h"
29#include "RooAbsCategory.h"
30#include "RooArgList.h"
31#include "RooRealVar.h"
32#include "RooCategory.h"
33#include "RooMsgService.h"
34#include "RooWorkspace.h"
35#include "TInterpreter.h"
36#include "TEnum.h"
37#include "RooAbsPdf.h"
38#include <array>
39#include <fstream>
40#include "strtok.h"
41#include "strlcpy.h"
42#include "RooGlobalFunc.h"
43#include "RooDataSet.h"
44#include "RooDataHist.h"
45#include "RooAddPdf.h"
46#include "RooProdPdf.h"
47#include "RooPolyFunc.h"
48#include "RooSimultaneous.h"
49#include "RooFFTConvPdf.h"
50#include "RooNumConvPdf.h"
51#include "RooResolutionModel.h"
52#include "RooProduct.h"
53#include "RooAddition.h"
54#include "RooRealSumPdf.h"
55#include "RooConstVar.h"
56#include "RooDerivative.h"
57#include "RooStringVar.h"
58#include "TROOT.h"
59
60#ifdef ROOFIT_LEGACY_EVAL_BACKEND
61#include "RooChi2Var.h"
62#include "RooNLLVar.h"
63#endif
64
65using namespace RooFit;
66using std::string, std::map, std::list, std::pair, std::endl, std::vector;
67
68#define BUFFER_SIZE 64000
69
70
73
74namespace {
75
76static Int_t init();
77
78Int_t dummy = init() ;
79
80Int_t init()
81{
83
84 // Operator pdfs
93
94 // Operator functions
100
101 // Test statistics
105
106 // Integration and derivation
111
112 // Miscellaneous
115
116 (void) dummy;
117 return 0 ;
118}
119
120}
121
122////////////////////////////////////////////////////////////////////////////////
123/// Low-level factory interface for creating a RooRealVar with a given range and initial value
124
126{
127 // First check if variable already exists
128 if (_ws->var(name)) {
129 coutE(ObjectHandling) << "RooFactoryWSTool::createFactory() ERROR: variable with name '" << name << "' already exists" << std::endl ;
130 logError() ;
131 return nullptr ;
132 }
133
134 // Create variable
136
137 // Put in workspace
138 if (_ws->import(var,Silence())) logError() ;
139
140 return _ws->var(name) ;
141}
142
143
144
145////////////////////////////////////////////////////////////////////////////////
146/// Low-level factory interface for creating a RooCategory with a given list of state names. The State name list
147/// can be of the form `name1,name2,name3` or of the form `name1=id1,name2=id2,name3=id3`
148
150{
151 // Create variable
152 RooCategory cat(name,name) ;
153
154 // Add listed state names
155 if (stateNameList) {
156 const size_t tmpSize = strlen(stateNameList)+1;
157 std::vector<char> tmp(tmpSize);
158 strlcpy(tmp.data(),stateNameList,tmpSize) ;
159 char* save ;
160 char* tok = R__STRTOK_R(tmp.data(),",",&save) ;
161 while(tok) {
162 char* sep = strchr(tok,'=') ;
163 if (sep) {
164 *sep = 0 ;
165 Int_t id = atoi(sep+1) ;
166 cat.defineType(tok,id) ;
167 *sep = '=' ;
168 } else {
169 cat.defineType(tok) ;
170 }
171 tok = R__STRTOK_R(nullptr,",",&save) ;
172 }
173 }
174
175 cat.setStringAttribute("factory_tag",Form("%s[%s]",name,stateNameList)) ;
176
177 // Put in workspace
178 if (_ws->import(cat,Silence())) logError() ;
179
180 return _ws->cat(name) ;
181}
182
183namespace {
184 bool isEnum(const char* classname) {
185 // Returns true if given type is an enum
186 ClassInfo_t* cls = gInterpreter->ClassInfo_Factory(classname);
187 long property = gInterpreter->ClassInfo_Property(cls);
188 gInterpreter->ClassInfo_Delete(cls);
189 return (property&kIsEnum);
190 }
191
192
193 bool isValidEnumValue(const char* enumName, const char* enumConstantName) {
194 // Returns true if given type is an enum
195
196 if (!enumName) return false;
197
199 if (!enumName) return false;
200
201 // Attempt 1: Enum constant name as is
202 if (theEnum->GetConstant(enumConstantName)) return true;
203 // Attempt 2: Remove the scope preceding the enum constant name
205 if (tmp) {
207 if (theEnum->GetConstant(enumConstantNameNoScope)) return true;
208 }
209
210 return false;
211 }
212
213 pair<list<string>,unsigned int> ctorArgs(const char* classname, std::size_t nPassedArgs) {
214 // Utility function for RooFactoryWSTool. Return arguments of 'first' non-default, non-copy constructor of any RooAbsArg
215 // derived class. Only constructors that start with two `const char*` arguments (for name and title) are considered
216 // The returned object contains
217
218 Int_t nreq(0);
220
221 ClassInfo_t* cls = gInterpreter->ClassInfo_Factory(classname);
222 MethodInfo_t* func = gInterpreter->MethodInfo_Factory(cls);
223 while(gInterpreter->MethodInfo_Next(func)) {
224 ret.clear();
225 nreq=0;
226
227 // Find 'the' constructor
228
229 // Skip non-public methods
230 if (!(gInterpreter->MethodInfo_Property(func) & kIsPublic)) {
231 continue;
232 }
233
234 // Return type must be class name
235 if (string(classname) != gInterpreter->MethodInfo_TypeName(func)) {
236 continue;
237 }
238
239 // Skip default constructor
240 int nargs = gInterpreter->MethodInfo_NArg(func);
241 int nDefaultArgs = gInterpreter->MethodInfo_NDefaultArg(func);
242 if (nargs == nDefaultArgs) {
243 continue;
244 }
245
246 MethodArgInfo_t* arg = gInterpreter->MethodArgInfo_Factory(func);
247 while (gInterpreter->MethodArgInfo_Next(arg)) {
248 // Require that first two arguments are of type const char*
249 const char* argTypeName = gInterpreter->MethodArgInfo_TypeName(arg);
250 if (nreq<2 && ((string("char*") != argTypeName
251 && !(gInterpreter->MethodArgInfo_Property(arg) & kIsConstPointer))
252 && string("const char*") != argTypeName)) {
253 continue ;
254 }
255 ret.push_back(argTypeName) ;
256 if(!gInterpreter->MethodArgInfo_DefaultValue(arg)) nreq++;
257 }
258 gInterpreter->MethodArgInfo_Delete(arg);
259
260 // If the number of passed args (plus 2 for name and title) is somewhere
261 // between the number of minimum and maximum arguments that the
262 // constructor can take, it's a match!
263 if(static_cast<int>(nPassedArgs) >= nargs - nDefaultArgs && static_cast<int>(nPassedArgs) <= nargs) {
264 break;
265 }
266 }
267 gInterpreter->MethodInfo_Delete(func);
268 gInterpreter->ClassInfo_Delete(cls);
269 return pair<list<string>,unsigned int>(ret,nreq);
270 }
271}
272
273////////////////////////////////////////////////////////////////////////////////
274/// Low-level factory interface for creating a RooAbsPdf of a given class with a given list of input variables
275/// The variable list varList should be of the form "a,b,c" where the interpretation of the argument is
276/// dependent on the pdf. Set and List arguments can be passed by substituting a single argument with
277/// the form (a,b,c), i.e. one can set varList to "x,(a0,a1,a2)" to pass a RooAbsReal and a RooArgSet as arguments.
278
279RooAbsArg* RooFactoryWSTool::createArg(const char* className, const char* objName, const char* varList)
280{
281 // Find class in ROOT class table
282 TClass* tc = resolveClassName(className);
283 if (!tc) {
284 coutE(ObjectHandling) << "RooFactoryWSTool::createArg() ERROR class " << className << " not found in factory alias table, nor in ROOT class table" << std::endl;
285 logError();
286 return nullptr;
287 }
288
289 className = tc->GetName();
290
291 // Check that class inherits from RooAbsPdf
292 if (!tc->InheritsFrom(RooAbsArg::Class())) {
293 coutE(ObjectHandling) << "RooFactoryWSTool::createArg() ERROR class " << className << " does not inherit from RooAbsArg" << std::endl;
294 logError();
295 return nullptr;
296 }
297
298 _args.clear();
299 string tmp(varList);
300 size_t blevel = 0;
301 size_t end_tok;
302 size_t start_tok = 0;
303 bool litmode = false;
304 for (end_tok = 0; end_tok < tmp.length(); end_tok++) {
305 // Keep track of opening and closing brackets
306 if (tmp[end_tok]=='{' || tmp[end_tok]=='(' || tmp[end_tok]=='[') blevel++;
307 if (tmp[end_tok]=='}' || tmp[end_tok]==')' || tmp[end_tok]==']') blevel--;
308
309 // Keep track of string literals
310 if (tmp[end_tok]=='"' || tmp[end_tok]=='\'') litmode = !litmode;
311
312 // If we encounter a comma at zero bracket level
313 // push the current substring from start_tok to end_tok
314 // and start the next token
315 if (litmode == false && blevel == 0 && tmp[end_tok] == ',') {
316 _args.push_back(tmp.substr(start_tok, end_tok - start_tok));
317 start_tok = end_tok+1;
318 }
319 }
320 _args.push_back(tmp.substr(start_tok, end_tok));
321
322 // Try CINT interface
323 pair<list<string>,unsigned int> ca = ctorArgs(className,_args.size()+2) ;
324 if (ca.first.empty()) {
325 coutE(ObjectHandling) << "RooFactoryWSTool::createArg() ERROR no suitable constructor found for class " << className << std::endl ;
326 logError() ;
327 return nullptr ;
328 }
329
330
331 // Check if number of provided args is in valid range (add two to accomomdate name and title strings)
332 if (_args.size()+2<ca.second || _args.size()+2>ca.first.size()) {
333 if (ca.second==ca.first.size()) {
334 coutE(ObjectHandling) << "RooFactoryWSTool::createArg() ERROR number of arguments provided (" << _args.size() << ") for class is invalid, " << className
335 << " expects " << ca.first.size()-2 << std::endl ;
336 logError() ;
337 } else {
338 coutE(ObjectHandling) << "RooFactoryWSTool::createArg() ERROR number of arguments provided (" << _args.size() << ") for class is invalid " << className
339 << " expect number between " << ca.second-2 << " and " << ca.first.size()-2 << std::endl ;
340 logError() ;
341 }
342 return nullptr ;
343 }
344
345 // Now construct CINT constructor spec, start with mandatory name and title args
346 string cintExpr(Form("new %s(\"%s\",\"%s\"",className,objName,objName)) ;
347
348 // Install argument in static data member to be accessed below through static CINT interface functions
349 _of = this ;
350
351
352 try {
353 Int_t i(0) ;
354 list<string>::iterator ti = ca.first.begin() ; ++ti ; ++ti ;
355 for (vector<string>::iterator ai = _args.begin() ; ai != _args.end() ; ++ai,++ti,++i) {
356 if ((*ti)=="RooAbsReal&" || (*ti)=="const RooAbsReal&" || (*ti)=="RooAbsReal::Ref") {
358 cintExpr += Form(",RooFactoryWSTool::as_FUNC(%d)",i) ;
359 } else if ((*ti)=="RooAbsArg&" || (*ti)=="const RooAbsArg&") {
361 cintExpr += Form(",RooFactoryWSTool::as_ARG(%d)",i) ;
362 } else if ((*ti)=="RooRealVar&" || (*ti)=="const RooRealVar&") {
364 cintExpr += Form(",RooFactoryWSTool::as_VAR(%d)",i) ;
365 } else if ((*ti)=="RooAbsRealLValue&" || (*ti)=="const RooAbsRealLValue&") {
367 cintExpr += Form(",RooFactoryWSTool::as_VARLV(%d)",i) ;
368 } else if ((*ti)=="RooCategory&" || (*ti)=="const RooCategory&") {
370 cintExpr += Form(",RooFactoryWSTool::as_CAT(%d)",i) ;
371 } else if ((*ti)=="RooAbsCategory&" || (*ti)=="const RooAbsCategory&") {
373 cintExpr += Form(",RooFactoryWSTool::as_CATFUNC(%d)",i) ;
374 } else if ((*ti)=="RooAbsCategoryLValue&" || (*ti)=="const RooAbsCategoryLValue&") {
376 cintExpr += Form(",RooFactoryWSTool::as_CATLV(%d)",i) ;
377 } else if ((*ti)=="RooAbsPdf&" || (*ti)=="const RooAbsPdf&") {
379 cintExpr += Form(",RooFactoryWSTool::as_PDF(%d)",i) ;
380 } else if ((*ti)=="RooResolutionModel&" || (*ti)=="const RooResolutionModel&") {
382 cintExpr += Form(",RooFactoryWSTool::as_RMODEL(%d)",i) ;
383 } else if ((*ti)=="RooAbsData&" || (*ti)=="const RooAbsData&") {
385 cintExpr += Form(",RooFactoryWSTool::as_DATA(%d)",i) ;
386 } else if ((*ti)=="RooDataSet&" || (*ti)=="const RooDataSet&") {
388 cintExpr += Form(",RooFactoryWSTool::as_DSET(%d)",i) ;
389 } else if ((*ti)=="RooDataHist&" || (*ti)=="const RooDataHist&") {
391 cintExpr += Form(",RooFactoryWSTool::as_DHIST(%d)",i) ;
392 } else if ((*ti)=="const RooArgSet&") {
394 cintExpr += Form(",RooFactoryWSTool::as_SET(%d)",i) ;
395 } else if ((*ti)=="const RooArgList&") {
397 cintExpr += Form(",RooFactoryWSTool::as_LIST(%d)",i) ;
398 } else if ((*ti)=="const char*") {
400 cintExpr += Form(",RooFactoryWSTool::as_STRING(%d)",i) ;
401 } else if ((*ti)=="Int_t" || (*ti)=="int" || (*ti)=="bool" || (*ti)=="bool") {
403 cintExpr += Form(",RooFactoryWSTool::as_INT(%d)",i) ;
404 } else if ((*ti)=="double") {
406 cintExpr += Form(",RooFactoryWSTool::as_DOUBLE(%d)",i) ;
407 } else if (isEnum(ti->c_str())) {
408
409 string qualvalue ;
410 if (_args[i].find(Form("%s::",className)) != string::npos) {
411 qualvalue = _args[i] ;
412 } else {
413 qualvalue = Form("%s::%s",className,_args[i].c_str()) ;
414 }
415 if (isValidEnumValue(ti->c_str(),qualvalue.c_str())) {
416 cintExpr += Form(",(%s)%s",ti->c_str(),qualvalue.c_str()) ;
417 } else {
418 throw string(Form("Supplied argument %s does not represent a valid state of enum %s",_args[i].c_str(),ti->c_str())) ;
419 }
420 } else {
421 // Check if generic object store has argument of given name and type
423
424 // Strip argument type to bare type (i.e. const X& -> X)
425 string btype ;
426 if (ti->find("const ")==0) {
427 btype = ti->c_str()+6 ;
428 } else {
429 btype = *ti ;
430 }
431 if (btype.find('&')) {
432 btype.erase(btype.size()-1,btype.size()) ;
433 }
434
435 // If btype if a typedef, substitute it by the true type name
436 btype = string(TEnum::GetEnum(btype.c_str())->GetName());
437
438 if (obj.InheritsFrom(btype.c_str())) {
439 cintExpr += Form(",(%s&)RooFactoryWSTool::as_OBJ(%d)",ti->c_str(),i) ;
440 } else {
441 throw string(Form("Required argument with name %s of type '%s' is not in the workspace",_args[i].c_str(),ti->c_str())) ;
442 }
443 }
444 }
445 cintExpr += ") ;" ;
446 } catch (const string &err) {
447 coutE(ObjectHandling) << "RooFactoryWSTool::createArg() ERROR constructing " << className << "::" << objName << ": " << err << std::endl ;
448 logError() ;
449 return nullptr ;
450 }
451
452 cxcoutD(ObjectHandling) << "RooFactoryWSTool::createArg() Construct expression is " << cintExpr << std::endl ;
453
454 // Call CINT to perform constructor call. Catch any error thrown by argument conversion method
455 if (std::unique_ptr<RooAbsArg> arg{reinterpret_cast<RooAbsArg*>(gROOT->ProcessLineFast(cintExpr.c_str()))}) {
456 if (string(className)=="RooGenericPdf") {
457 arg->setStringAttribute("factory_tag",Form("EXPR::%s(%s)",objName,varList)) ;
458 } else if (string(className)=="RooFormulaVar") {
459 arg->setStringAttribute("factory_tag",Form("expr::%s(%s)",objName,varList)) ;
460 } else {
461 arg->setStringAttribute("factory_tag",Form("%s::%s(%s)",className,objName,varList)) ;
462 }
463 if (_ws->import(*arg,Silence())) logError() ;
465 return ret ;
466 } else {
467 coutE(ObjectHandling) << "RooFactoryWSTool::createArg() ERROR in CINT constructor call to create object" << std::endl ;
468 logError() ;
469 return nullptr ;
470 }
471}
472
473////////////////////////////////////////////////////////////////////////////////
474
476{
477 // Spec list is of form a*A,b*B,c*C,D [ *d]
478
479 RooArgList pdfList ;
480 RooArgList coefList ;
482
483 try {
484
485 char buf[BUFFER_SIZE] ;
487 char* save ;
488 char* tok = R__STRTOK_R(buf,",",&save) ;
489 while(tok) {
490 char* star=strchr(tok,'*') ;
491 if (star) {
492 *star=0 ;
493 pdfList.add(asPDF(star+1)) ;
494 coefList.add(asFUNC(tok)) ;
495 } else {
496 pdfList2.add(asPDF(tok)) ;
497 }
498 tok = R__STRTOK_R(nullptr,",",&save) ;
499 }
500 pdfList.add(pdfList2) ;
501
502 } catch (const string &err) {
503 coutE(ObjectHandling) << "RooFactoryWSTool::add(" << objName << ") ERROR creating RooAddPdf: " << err << std::endl ;
504 logError() ;
505 return nullptr;
506 }
507
508 RooAddPdf pdf{objName,objName,pdfList,coefList,recursiveCoefs};
509 pdf.setStringAttribute("factory_tag",Form("SUM::%s(%s)",objName,specList)) ;
510 if (_ws->import(pdf,Silence())) logError() ;
511 return static_cast<RooAddPdf*>(_ws->pdf(objName));
512}
513
514
515////////////////////////////////////////////////////////////////////////////////
516
518{
519 // Spec list is of form a*A,b*B,c*C,D [ *d]
520
522 RooArgList coefList ;
524
525 try {
526
527 char buf[BUFFER_SIZE] ;
529 char* save ;
530 char* tok = R__STRTOK_R(buf,",",&save) ;
531 while(tok) {
532 char* star=strchr(tok,'*') ;
533 if (star) {
534 *star=0 ;
535 amplList.add(asFUNC(star+1)) ;
536 coefList.add(asFUNC(tok)) ;
537 } else {
538 amplList2.add(asFUNC(tok)) ;
539 }
540 tok = R__STRTOK_R(nullptr,",",&save) ;
541 }
542 amplList.add(amplList2) ;
543
544 } catch (const string &err) {
545 coutE(ObjectHandling) << "RooFactoryWSTool::add(" << objName << ") ERROR creating RooRealSumPdf: " << err << std::endl ;
546 logError() ;
547 return nullptr;
548 }
549
550 RooRealSumPdf pdf(objName,objName,amplList,coefList,(amplList.size()==coefList.size())) ;
551 pdf.setStringAttribute("factory_tag",Form("ASUM::%s(%s)",objName,specList)) ;
552 if (_ws->import(pdf,Silence())) logError() ;
553 return static_cast<RooRealSumPdf*>(_ws->pdf(objName));
554}
555
556
557////////////////////////////////////////////////////////////////////////////////
558
559RooProdPdf* RooFactoryWSTool::prod(const char *objName, const char* pdfList)
560{
561 _of = this ;
562
563 // Separate conditional and non-conditional pdf terms
565 string regPdfList="{" ;
566 char buf[BUFFER_SIZE] ;
567 strlcpy(buf,pdfList,BUFFER_SIZE) ;
568 char* save ;
569 char* tok = R__STRTOK_R(buf,",",&save) ;
570 while(tok) {
571 char *sep = strchr(tok,'|') ;
572 if (sep) {
573 // Conditional term
574 *sep=0 ;
575 sep++ ;
576
577 // |x is conditional on x, |~x is conditional on all but x
578 bool invCond(false) ;
579 if (*sep=='~') {
580 invCond=true ;
581 sep++ ;
582 }
583
584 try {
586 } catch (const string &err) {
587 coutE(ObjectHandling) << "RooFactoryWSTool::prod(" << objName << ") ERROR creating RooProdPdf Conditional argument: " << err << std::endl ;
588 logError() ;
589 return nullptr ;
590 }
591
592 } else {
593 // Regular term
594 if (regPdfList.size()>1) {
595 regPdfList += "," ;
596 }
597 regPdfList += tok ;
598 }
599 tok = R__STRTOK_R(nullptr,",",&save) ;
600 }
601 regPdfList += "}" ;
602
603 std::unique_ptr<RooProdPdf> pdf;
604 try {
605 pdf = std::make_unique<RooProdPdf>(objName,objName,asSET(regPdfList.c_str()),cmdList);
606 } catch (const string &err) {
607 coutE(ObjectHandling) << "RooFactoryWSTool::prod(" << objName << ") ERROR creating RooProdPdf input set of regular pdfs: " << err << std::endl ;
608 logError() ;
609 }
610 cmdList.Delete() ;
611
612 if (pdf) {
613 pdf->setStringAttribute("factory_tag",Form("PROD::%s(%s)",objName,pdfList)) ;
614 if (_ws->import(*pdf,Silence())) logError() ;
615 return static_cast<RooProdPdf*>(_ws->pdf(objName)) ;
616 } else {
617 return nullptr;
618 }
619}
620
621
622
623////////////////////////////////////////////////////////////////////////////////
624
625RooSimultaneous* RooFactoryWSTool::simul(const char* objName, const char* indexCat, const char* pdfMap)
626{
628 // Add pdf to index state mappings
629 char buf[BUFFER_SIZE] ;
631 char* save ;
632 char* tok = R__STRTOK_R(buf,",",&save) ;
633 while(tok) {
634 char* eq = strchr(tok,'=') ;
635 if (!eq) {
636 coutE(ObjectHandling) << "RooFactoryWSTool::simul(" << objName << ") ERROR creating RooSimultaneous::" << objName
637 << " expect mapping token of form 'state=pdfName', but found '" << tok << "'" << std::endl ;
638 logError() ;
639 return nullptr ;
640 } else {
641 *eq = 0 ;
642
643 try {
644 theMap[tok] = &asPDF(eq+1) ;
645 } catch (const string &err ) {
646 coutE(ObjectHandling) << "RooFactoryWSTool::simul(" << objName << ") ERROR creating RooSimultaneous: " << err << std::endl ;
647 logError() ;
648 }
649 }
650 tok = R__STRTOK_R(nullptr,",",&save) ;
651 }
652
653
654 // Create simultaneous pdf.
655 std::unique_ptr<RooSimultaneous> pdf;
656 try {
657 pdf = std::make_unique<RooSimultaneous>(objName,objName,theMap,asCATLV(indexCat)) ;
658 } catch (const string &err) {
659 coutE(ObjectHandling) << "RooFactoryWSTool::simul(" << objName << ") ERROR creating RooSimultaneous::" << objName << " " << err << std::endl ;
660 logError() ;
661 return nullptr;
662 }
663
664 // Import pdf into workspace
665 pdf->setStringAttribute("factory_tag",Form("SIMUL::%s(%s,%s)",objName,indexCat,pdfMap)) ;
666 if (_ws->import(*pdf,Silence())) logError() ;
667 return static_cast<RooSimultaneous*>(_ws->pdf(objName)) ;
668}
669
670
671
672
673////////////////////////////////////////////////////////////////////////////////
674
676{
679
680 try {
681
682 char buf[BUFFER_SIZE] ;
684 char* save ;
685 char* tok = R__STRTOK_R(buf,",",&save) ;
686 while(tok) {
687 char* star=strchr(tok,'*') ;
688 if (star) {
689 *star=0 ;
690 sumlist2.add(asFUNC(star+1)) ;
691 sumlist1.add(asFUNC(tok)) ;
692 } else {
693 sumlist1.add(asFUNC(tok)) ;
694 }
695 tok = R__STRTOK_R(nullptr,",",&save) ;
696 }
697
698 } catch (const string &err) {
699 coutE(ObjectHandling) << "RooFactoryWSTool::addfunc(" << objName << ") ERROR creating RooAddition: " << err << std::endl ;
700 logError() ;
701 return nullptr ;
702 }
703
704 if (!sumlist2.empty() && (sumlist1.size()!=sumlist2.size())) {
705 coutE(ObjectHandling) << "RooFactoryWSTool::addfunc(" << objName << ") ERROR creating RooAddition: syntax error: either all sum terms must be products or none" << std::endl ;
706 logError() ;
707 return nullptr ;
708 }
709
710
711 auto sum = sumlist2.empty() ? std::make_unique<RooAddition>(objName,objName,sumlist1)
712 : std::make_unique<RooAddition>(objName,objName,sumlist1,sumlist2);
713
714 sum->setStringAttribute("factory_tag",Form("sum::%s(%s)",objName,specList)) ;
715 if (_ws->import(*sum,Silence())) logError() ;
716 return static_cast<RooAddition*>(_ws->function(objName));
717
718}
719
720
721
722
723////////////////////////////////////////////////////////////////////////////////
724
725RooProduct* RooFactoryWSTool::prodfunc(const char *objName, const char* pdfList)
726{
727 return static_cast<RooProduct*>(createArg("RooProduct",objName,Form("{%s}",pdfList))) ;
728}
729
730
731
732
733
734////////////////////////////////////////////////////////////////////////////////
735/// Create a RooFit object from the given expression.
736///
737/// <table>
738/// <tr><th> Creating variables <th>
739/// <tr><td> `x[-10,10]` <td> Create variable x with given range and put it in workspace
740/// <tr><td> `x[3,-10,10]` <td> Create variable x with given range and initial value and put it in workspace
741/// <tr><td> `x[3]` <td> Create variable x with given constant value
742/// <tr><td> `<numeric literal>` <td> Numeric literal expressions (0.5, -3 etc..) are converted to a RooConst(<numeric literal>)
743/// wherever a RooAbsReal or RooAbsArg argument is expected
744/// <tr><th> Creating categories <th>
745/// <tr><td> `c[lep,kao,nt1,nt2]` <td> Create category c with given state names
746/// <tr><td> `tag[B0=1,B0bar=-1]` <td> Create category tag with given state names and index assignments
747/// <tr><th> Creating functions and pdfs <th>
748/// <tr><td> `MyPdf::g(x,m,s)` <td> Create pdf or function of type MyPdf with name g with argument x,m,s
749/// Interpretation and number of arguments are mapped to the constructor arguments of the class
750/// (after the name and title).
751/// <tr><td> `MyPdf(x,m,s)` <td> As above, but with an implicitly defined (unique) object name
752/// <tr><th> Creating sets and lists (to be used as inputs above) <th>
753/// <tr><td> `{a,b,c}` <td> Create RooArgSet or RooArgList (as determined by context) from given contents
754/// </table>
755///
756///
757/// Objects that are not created, are assumed to exist in the workspace
758/// Object creation expressions as shown above can be nested, e.g. one can do
759/// ```
760/// RooGaussian::g(x[-10,10],m[0],3)
761/// ```
762/// to create a pdf and its variables in one go. This nesting can be applied recursively e.g.
763/// ```
764/// SUM::model( f[0.5,0,1] * RooGaussian::g( x[-10,10], m[0], 3] ),
765/// RooChebychev::c( x, {a0[0.1],a1[0.2],a2[-0.3]} ))
766/// ```
767/// creates the sum of a Gaussian and a Chebychev and all its variables.
768///
769///
770/// A separate series of operator meta-type exists to simplify the construction of composite expressions
771/// meta-types in all capitals (SUM) create pdfs, meta types in lower case (sum) create
772/// functions.
773///
774/// <table>
775/// <tr><th> Expression <th> Effect
776/// <tr><td> `SUM::name(f1*pdf1,f2*pdf2,pdf3]` <td> Create sum pdf name with value `f1*pdf1+f2*pdf2+(1-f1-f2)*pdf3`
777/// <tr><td> `RSUM::name(f1*pdf1,f2*pdf2,pdf3]` <td> Create recursive sum pdf name with value `f1*pdf1 + (1-f1)(f2*pdf2 + (1-f2)pdf3)`
778/// <tr><td> `ASUM::name(f1*amp1,f2*amp2,amp3]` <td> Create sum pdf name with value `f1*amp1+f2*amp2+(1-f1-f2)*amp3` where `amplX` are amplitudes of type RooAbsReal
779/// <tr><td> `sum::name(a1,a2,a3]` <td> Create sum function with value `a1+a2+a3`
780/// <tr><td> `sum::name(a1*b1,a2*b2,a3*b 3]` <td> Create sum function with value `a1*b1+a2*b2+a3*b3`
781/// <tr><td> `PROD::name(pdf1,pdf2]` <td> Create product of pdf with `name` with given input pdfs
782/// <tr><td> `PROD::name(pdf1|x,pdf2]` <td> Create product of conditional pdf `pdf1` given `x` and `pdf2`
783/// <tr><td> `prod::name(a,b,c]` <td> Create production function with value `a*b*c`
784/// <tr><td> `SIMUL::name(cat,a=pdf1,b=pdf2]` <td> Create simultaneous pdf index category `cat`. Make `pdf1` to state `a`, `pdf2` to state `b`
785/// <tr><td> `EXPR::name(<expr>,var,...]` <td> Create a generic pdf that interprets the given expression
786/// <tr><td> `expr::name(<expr>,var,...]` <td> Create a generic function that interprets the given expression
787/// <tr><td> `taylorexpand::name(func,{var1,var2,...},val,order,eps1,eps2]` <td> Create a taylor expansion of func w.r.t. `{var1,var2,..}` around `val` up to `order`
788/// <tr><td> `lagrangianmorph::name("$fileName('infile.root'),$observableName(obs),$couplings({var1[-10,10],var2[-10,10]}),$folders({'sample1,sample2,sample3'}),$NewPhysics(var1=1,var2=0)"]` <td> Create a RooLagrangianMorphFunc function for the observable obs as a function of `var1`, `var2` based on input templates stored in the folders in the file
789/// </table>
790///
791/// The functionality of high-level object creation tools like RooSimWSTool, RooCustomizer and RooClassFactory
792/// is also interfaced through meta-types in the factory.
793/// <table>
794/// <tr><th> Interface to %RooSimWSTool <th>
795/// <tr><td> `SIMCLONE::name( modelPdf, $ParamSplit(...), $ParamSplitConstrained(...), $Restrict(...) ]`
796/// <td> Clone-and-customize modelPdf according to ParamSplit and ParamSplitConstrained()
797/// specifications and return a RooSimultaneous pdf of all built clones
798///
799/// <tr><td> `MSIMCLONE::name( masterIndex, $AddPdf(mstate1, modelPdf1, $ParamSplit(...)), $AddPdf(mstate2,modelPdf2),...) ]`
800/// <td> Clone-and-customize multiple models (modelPdf1,modelPdf2) according to ParamSplit and
801/// ParamSplitConstrained() specifications and return a RooSimultaneous pdf of all built clones,
802/// using the specified master index to map prototype pdfs to master states
803/// <tr><th> Interface to %RooCustomizer <th>
804/// <tr><td> `EDIT::name( orig, substNode=origNode), ... ]` <td> Create a clone of input object orig, with the specified replacements operations executed
805/// <tr><td> `EDIT::name( orig, origNode=$REMOVE(), ... ]` <td> Create clone of input removing term origNode from all PROD() terms that contained it
806/// <tr><td> `EDIT::name( orig, origNode=$REMOVE(prodname,...), ... ]` <td> As above, but restrict removal of origNode to PROD term(s) prodname,...
807///
808///
809/// <tr><th> Interface to %RooClassFactory <th>
810/// <tr><td> `CEXPR::name(<expr>,var,...]` <td> Create a custom compiled pdf that evaluates the given expression
811/// <tr><td> `cexpr::name(<expr>,var,...]` <td> Create a custom compiled function that evaluates the given expression
812///
813///
814/// <tr><td> `$MetaType(...)` <td> Meta argument that does not result in construction of an object but is used logically organize
815/// input arguments in certain operator pdf constructions. The defined meta arguments are context dependent.
816/// The only meta argument that is defined globally is `$Alias(typeName,aliasName)` to
817/// define aliases for type names. For the definition of meta arguments in operator pdfs
818/// see the definitions below.
819/// </table>
821{
822
823// std::cout << "RooFactoryWSTool::process() " << expr << std::endl ;
824
825 // First perform basic syntax check
826 if (checkSyntax(expr)) {
827 return nullptr ;
828 }
829
830 // Allocate work buffer
831 std::vector<char> buf(strlen(expr)+1);
832
833 // Copy to buffer while absorbing white space and newlines
834 char* buftmp = buf.data();
835 while(*expr) {
836 if (!isspace(*expr)) {
837 *buftmp = *expr ;
838 buftmp++ ;
839 }
840 expr++ ;
841 }
842 *buftmp=0 ;
843
844
845 // Clear error count and start a transaction in the workspace
846 clearError() ;
847 ws().startTransaction() ;
848
849 // Process buffer
850 string out ;
851 try {
852 out = processExpression(buf.data()) ;
853 } catch (const string &error) {
854 coutE(ObjectHandling) << "RooFactoryWSTool::processExpression() ERROR in parsing: " << error << std::endl ;
855 logError() ;
856 }
857
858 // If there were no errors commit the transaction, cancel it otherwise
859 if (errorCount()>0) {
860 coutE(ObjectHandling) << "RooFactoryWSTool::processExpression() ERRORS detected, transaction to workspace aborted, no objects committed" << std::endl ;
862 } else {
864 }
865
866 return !out.empty() ? ws().arg(out) : nullptr ;
867}
868
869
870
871
872////////////////////////////////////////////////////////////////////////////////
873/// Process a single high-level expression or list of
874/// expressions. The returned string a the reduced expression where
875/// all inline object creations have been executed and substituted
876/// with the name of the created object
877///
878/// - e.g. `RooGaussian::g(x,m,s)` --> `g`
879/// - e.g. `{x(-10,10),s}` --> `{x,s}`
880
882{
883 // Delegate handling to list processor if token starts with {, otherwise
884 // call single expression processor
885 if (string(token).find("$Alias(")==0) {
887 }
888
889 if (token[0]=='{') {
890 // Process token as list if it starts with '{'
892 } else {
893 // Process token as single item otherwise
895 }
896}
897
898
899
900////////////////////////////////////////////////////////////////////////////////
901/// Process a single composite expression
902///
903/// - e.g. `A=RooGaussian::g[x,m,s]` --> `A=g`
904/// - e.g. `f[0,1]*RooGaussian::g[x,m,s]` --> `f*g`
905/// - e.g. `RooGaussian::g(x,y,s)|x` --> `g|x`
906/// - e.g. `$MetaArg(RooGaussian::g[x,m,s],blah)` --> `$MetaArg(g,blah)`
907
909{
910 // Allocate and fill work buffer
911 const size_t bufBaseSize = strlen(token)+1;
912 std::vector<char> buf_base(bufBaseSize);
913 char* buf = buf_base.data();
915 char* p = buf ;
916
918 list<char> separator ;
919 Int_t blevel(0) ;
920 bool litmode(false) ;
921 while(*p) {
922
923 // Keep track of opening and closing brackets
924 if (*p=='{' || *p=='(' || *p=='[') blevel++ ;
925 if (*p=='}' || *p==')' || *p==']') blevel-- ;
926
927 // Keep track of string literals
928 if (*p=='"' || *p=='\'') litmode = !litmode ;
929
930 // If we are zero-bracket level and encounter a |, store
931 // the remainder of the string as suffix and exit loop
932 if (!litmode && blevel==0 && ( (*p)=='=' || (*p) == '|' || (*p) == '*')) {
933 separator.push_back(*p) ;
934 *p=0 ;
935 singleExpr.push_back(buf) ;
936 buf = p+1 ;
937 }
938 p++ ;
939 }
940 if (*buf) {
941 singleExpr.push_back(buf) ;
942 }
943 if (singleExpr.size()==1) {
945 return ret ;
946 }
947
948 string ret ;
949 list<char>::iterator ic = separator.begin() ;
950 for (list<string>::iterator ii = singleExpr.begin() ; ii!=singleExpr.end() ; ++ii) {
951 ret += processSingleExpression(ii->c_str()) ;
952 if (ic != separator.end()) {
953 ret += *ic ;
954 ++ic ;
955 }
956 }
957
958 return ret ;
959}
960
961
962
963////////////////////////////////////////////////////////////////////////////////
964/// Process a single high-level expression. The returned string a the reduced
965/// expression where all inline object creations have been executed and substituted
966/// with the name of the created object
967///
968/// - e.g. `RooGaussian::g(x,m,s)` --> `g`
969/// - e.g. `x[-10,10]` --> `x`
970
972{
973 // Handle empty strings here
974 if (strlen(arg)==0) {
975 return string("") ;
976 }
977
978 // Handle string literal case
979 if (arg[0]=='\'' || arg[0]=='"') {
980 return string(arg) ;
981 }
982
983 // Allocate and fill work buffer
984 const size_t bufSize = strlen(arg)+1;
985 std::vector<char> buf(bufSize);
986 strlcpy(buf.data(),arg,bufSize) ;
987 char* bufptr = buf.data();
988
989 string func;
990 string prefix;
991 vector<string> args ;
992
993 // Process token into arguments
994 char* save ;
995 char* tmpx = R__STRTOK_R(buf.data(),"([",&save) ;
996 func = tmpx ? tmpx : "" ;
997 char* p = R__STRTOK_R(nullptr,"",&save) ;
998
999 // Return here if token is fundamental
1000 if (!p) {
1001 return arg ;
1002 }
1003
1004
1005 char* tok = p ;
1006 Int_t blevel=0 ;
1007 bool litmode(false) ;
1008 while(*p) {
1009
1010 // Keep track of opening and closing brackets
1011 if (*p=='{' || *p=='(' || *p=='[') blevel++ ;
1012 if (*p=='}' || *p==')' || *p==']') blevel-- ;
1013
1014 // Keep track of string literals
1015 if (*p=='"' || *p=='\'') litmode = !litmode ;
1016
1017
1018 // If we encounter a comma at zero bracket level
1019 // finalize the current token as a completed argument
1020 // and start the next token
1021 if (!litmode && blevel==0 && ((*p)==',')) {
1022 *p = 0 ;
1023 args.push_back(tok) ;
1024 tok = p+1 ;
1025 }
1026
1027 p++ ;
1028 }
1029
1030 // If the last character was a closing bracket, kill
1031 // it in the buffer
1032 if (p>bufptr && (*(p-1)==')'||*(p-1)==']')) {
1033 *(p-1)=0 ;
1034 }
1035
1036 // Finalize last token as argument
1037 string tmp = tok ;
1038
1039 // If there is a suffix left in the work buffer attach it to
1040 // this argument
1041 p = R__STRTOK_R(nullptr,"",&save) ;
1042 if (p) tmp += p ;
1043 args.push_back(tmp) ;
1044
1045 // If function contains :: then call createArg to process this arg, otherwise
1046 // call createVariable
1047 string ret ;
1048
1049 // Determine type of leading bracket
1050 char lb = ' ' ;
1051 for(const char* pp=arg ; *pp!=0 ; pp++) {
1052 if (*pp=='(' || *pp=='[' || *pp=='{') {
1053 lb = *pp ;
1054 break ;
1055 }
1056 }
1057
1058 if (strstr(func.c_str(),"::")) {
1059 if (lb=='(') {
1060 // Create function argument with instance name
1061 ret= processCreateArg(func,args) ;
1062 } else {
1063 coutE(ObjectHandling) << "RooFactoryWSTool::processSingleExpression(" << arg << "): ERROR: Syntax error: Class::Instance must be followed by (...)" << std::endl ;
1064 logError() ;
1065 }
1066 } else if (func[0]!='$'){
1067 if (lb=='[') {
1068 // Create variable argument
1069 ret= processCreateVar(func,args) ;
1070 } else if (lb=='(') {
1071
1072 // Create function argument with autoname
1073 string autoname ;
1074 if (!_autoNamePrefix.empty()) {
1075 // If we're inside a function creation call to a higher level object, use its
1076 // name as base for the autoname
1077 autoname = (Form("%s::%s",func.c_str(),_autoNamePrefix.top().c_str())) ;
1078 } else {
1079 // Otherwise find a free global_%d name
1080 static Int_t globCounter = 0 ;
1081 while(true) {
1082 autoname = Form("gobj%d",globCounter) ;
1083 globCounter++ ;
1084 if (!ws().arg(autoname)) {
1085 break ;
1086 }
1087 }
1088 autoname = Form("%s::%s",func.c_str(),autoname.c_str()) ;
1089 }
1091 } else {
1092 coutE(ObjectHandling) << "RooFactoryWSTool::processSingleExpression(" << arg << "): ERROR: Syntax error: expect either Class(...) or Instance[...]" << std::endl ;
1093 logError() ;
1094 }
1095 } else {
1096 if (lb=='(') {
1097 // Process meta function (compile arguments, but not meta-function itself)
1098 ret= processMetaArg(func,args) ;
1099 } else {
1100 coutE(ObjectHandling) << "RooFactoryWSTool::processSingleExpression(" << arg << "): ERROR: Syntax error: $MetaClass must be followed by (...)" << std::endl ;
1101 logError() ;
1102 }
1103 }
1104
1105 // Return reduced token with suffix
1106 return ret ;
1107}
1108
1109
1110////////////////////////////////////////////////////////////////////////////////
1111/// Process a list of high-level expression. The returned string a the reduced
1112/// expression list where all inline object creations have been executed and substituted
1113/// with the name of the created object
1114///
1115/// - E.g. `{x(-10,10),s}` --> `{x,s}`
1116
1118{
1119 // Allocate and fill work buffer
1120 const size_t bufSize = strlen(arg)+1;
1121 std::vector<char> buf(bufSize);
1122 strlcpy(buf.data(),arg,bufSize) ;
1123
1124 std::vector<string> args ;
1125
1126 // Start running pointer at position 1 to skip opening bracket
1127 char* tok = buf.data()+1 ;
1128 char* p = buf.data()+1 ;
1129
1130 // Processing look
1131 Int_t level(0) ;
1132 while(*p) {
1133
1134 // Track bracketing level
1135 if (*p=='{' || *p=='(' || *p=='[') level++ ;
1136 if (*p=='}' || *p==')' || *p==']') level-- ;
1137
1138
1139 // If we encounter a comma at zero bracket level
1140 // finalize the current token as a completed argument
1141 // and start the next token
1142 if (level==0 && ((*p)==',')) {
1143 *p = 0 ;
1144 args.push_back(tok) ;
1145 tok = p+1 ;
1146 }
1147
1148 p++ ;
1149 }
1150
1151 // Finalize token as last argument
1152 if (p>buf.data() && *(p-1)=='}') {
1153 *(p-1)=0 ;
1154 }
1155 args.push_back(tok) ;
1156
1157 // Process each argument in list and construct reduced
1158 // expression to be returned
1159 string ret("{") ;
1160 vector<string>::iterator iter = args.begin() ;
1161 Int_t i(0) ;
1162 while(iter!= args.end()) {
1163 if (strlen(ret.c_str())>1) ret += "," ;
1164 if (!_autoNamePrefix.empty()) {
1165 _autoNamePrefix.push(Form("%s%d",_autoNamePrefix.top().c_str(),i+1)) ;
1166 }
1167 ret += processSingleExpression(iter->c_str()) ;
1168 if (!_autoNamePrefix.empty()) {
1169 _autoNamePrefix.pop() ;
1170 }
1171 ++iter ;
1172 i++ ;
1173 }
1174 ret += "}" ;
1175
1176 return ret ;
1177}
1178
1179
1180
1181////////////////////////////////////////////////////////////////////////////////
1182/// Parse token
1183
1185{
1187 if (args.size()!=2) {
1188 coutE(ObjectHandling) << "RooFactorWSTool::processAliasExpression() ERROR $Alias() takes exactly two arguments, " << args.size() << " args found" << std::endl ;
1189 logError() ;
1190 return string() ;
1191 }
1192
1193 // Insert alias in table
1194 _typeAliases[args[1]] = args[0] ;
1195
1196 return string() ;
1197}
1198
1199
1200
1201
1202////////////////////////////////////////////////////////////////////////////////
1203
1205{
1206 // First do recursive alias expansion
1207 while (true) {
1208 map<string,string>::iterator item = _typeAliases.find(className) ;
1209
1210 // If an alias is found, recurse
1211 if (item != _typeAliases.end()) {
1212 className = item->second.c_str() ;
1213 } else {
1214 break ;
1215 }
1216 }
1217
1218 // Now find dealiased class in ROOT class table
1219 TClass* tc = TClass::GetClass(className,true,true) ;
1220
1221 // If its not there, try prefixing with Roo
1222 if (!tc) {
1223 tc = TClass::GetClass(Form("Roo%s",className)) ;
1224 if (!tc) {
1225 coutE(ObjectHandling) << "RooFactoryWSTool::createArg() ERROR class " << className << " not defined in ROOT class table" << std::endl ;
1226 logError() ;
1227 return nullptr ;
1228 }
1229 }
1230 return tc ;
1231}
1232
1233
1234
1235////////////////////////////////////////////////////////////////////////////////
1236
1237string RooFactoryWSTool::varTag(string& func, vector<string>& args)
1238{
1239 string ret ;
1240 ret += func ;
1241 ret += "[" ;
1242 for (vector<string>::iterator iter = args.begin() ; iter!=args.end() ; ++iter) {
1243 if (iter!=args.begin()) {
1244 ret += "," ;
1245 }
1246 ret += *iter ;
1247 }
1248 ret += "]" ;
1249 return ret ;
1250}
1251
1252
1253
1254
1255////////////////////////////////////////////////////////////////////////////////
1256/// Glue function between high-level syntax and low-level factory call to createVariable:
1257/// Process a parsed call to create a variable named `func`
1258///
1259/// If initial token is non-numeric, a RooCategory will be created, and the args are interpreted
1260/// as either state names or `name=id` assignments. Otherwise a RooRealvar is created and the
1261/// arg list is interpreted as follows:
1262/// - If list has two args, these are interpreted as `xmin,xmax`
1263/// - If list has three args, these are interpreted as `xinit,xmin,xmax`
1264/// - If list has one arg, this is interpreted as `xinit` and the variable is set as constant
1265
1267{
1268
1269 // Determine if first arg is numeric
1270 string first = *(args.begin()) ;
1271 if (isdigit(first[0]) || first[0]=='.' || first[0]=='+' || first[0]=='-') {
1272
1273 // Create a RooRealVar
1274 vector<string>::iterator ai = args.begin() ;
1275 if (args.size()==1) {
1276
1277 // One argument, create constant variable with given value
1278 double xinit = atof((ai)->c_str()) ;
1279 cxcoutD(ObjectHandling) << "CREATE variable " << func << " xinit = " << xinit << std::endl ;
1280 RooRealVar tmp(func.c_str(),func.c_str(),xinit) ;
1281 tmp.setStringAttribute("factory_tag",varTag(func,args).c_str()) ;
1282 if (_ws->import(tmp,Silence())) {
1283 logError() ;
1284 }
1285
1286 } else if (args.size()==2) {
1287
1288 // Two arguments, create variable with given range
1289 double xlo = atof((ai++)->c_str()) ;
1290 double xhi = atof(ai->c_str()) ;
1291 cxcoutD(ObjectHandling) << "CREATE variable " << func << " xlo = " << xlo << " xhi = " << xhi << std::endl ;
1292 RooRealVar tmp(func.c_str(),func.c_str(),xlo,xhi) ;
1293 tmp.setStringAttribute("factory_tag",varTag(func,args).c_str()) ;
1294 if (_ws->import(tmp,Silence())) {
1295 logError() ;
1296 }
1297
1298 } else if (args.size()==3) {
1299
1300 // Three arguments, create variable with given initial value and range
1301 double xinit = atof((ai++)->c_str()) ;
1302 double xlo = atof((ai++)->c_str()) ;
1303 double xhi = atof(ai->c_str()) ;
1304 cxcoutD(ObjectHandling) << "CREATE variable " << func << " xinit = " << xinit << " xlo = " << xlo << " xhi = " << xhi << std::endl ;
1305 RooRealVar tmp(func.c_str(),func.c_str(),xinit,xlo,xhi) ;
1306 tmp.setStringAttribute("factory_tag",varTag(func,args).c_str()) ;
1307 if (_ws->import(tmp,Silence())) {
1308 logError() ;
1309 }
1310 }
1311 } else {
1312
1313 // Create a RooAbsCategory
1314 string allStates ;
1315 for (vector<string>::iterator ai = args.begin() ; ai!=args.end() ; ++ai) {
1316 if (!allStates.empty()) {
1317 allStates += "," ;
1318 }
1319 allStates += *ai ;
1320 }
1321 createCategory(func.c_str(),allStates.c_str()) ;
1322
1323 }
1324 return func ;
1325}
1326
1327
1328////////////////////////////////////////////////////////////////////////////////
1329/// Glue function between high-level syntax and low-level factory call to createArg:
1330/// Process a parsed call to create a pdf named `func`
1331///
1332/// The func arg is interpreted as ClassName::ObjectName and the arglist is passed
1333/// verbatim to createArg. The received arglist is expected to be fully reduced (i.e.
1334/// all inline object creations must have been compiled)
1335
1337{
1338 // Allocate and fill work buffer
1339 char buf[BUFFER_SIZE] ;
1340 strlcpy(buf,func.c_str(),BUFFER_SIZE) ;
1341
1342 // Split function part in class name and instance name
1343 char* save ;
1344 const char *className = R__STRTOK_R(buf,":",&save) ;
1345 const char *instName = R__STRTOK_R(nullptr,":",&save) ;
1346 if (!className) className = "";
1347 if (!instName) instName = "" ;
1348
1349 // Concatenate list of args into comma separated string
1350 char pargs[BUFFER_SIZE] ;
1351 pargs[0] = 0 ;
1352 vector<string>::iterator iter = args.begin() ;
1354 Int_t iarg(0) ;
1355 while(iter!=args.end()) {
1356 if (strlen(pargs)>0) strlcat(pargs,",",BUFFER_SIZE) ;
1357 _autoNamePrefix.push(Form("%s_%d",instName,iarg+1)) ;
1358 string tmp = processExpression(iter->c_str()) ;
1359 _autoNamePrefix.pop() ;
1360 strlcat(pargs,tmp.c_str(),BUFFER_SIZE) ;
1361 pargv.push_back(tmp) ;
1362 ++iter ;
1363 iarg++ ;
1364 }
1365
1366 // Look up if func is a special
1367 for (map<string,IFace*>::iterator ii=hooks().begin() ; ii!=hooks().end() ; ++ii) {
1368 }
1369 if (hooks().find(className) != hooks().end()) {
1370 IFace* iface = hooks()[className] ;
1371 return iface->create(*this, className,instName,pargv) ;
1372 }
1373
1374 createArg(className,instName,pargs) ;
1375
1376 return string(instName) ;
1377}
1378
1379
1380
1381////////////////////////////////////////////////////////////////////////////////
1382/// Concatenate list of args into comma separated string
1383
1384std::string RooFactoryWSTool::processMetaArg(std::string& func, std::vector<std::string>& args)
1385{
1386 char pargs[BUFFER_SIZE] ;
1387 pargs[0] = 0 ;
1388 vector<string>::iterator iter = args.begin() ;
1390 while(iter!=args.end()) {
1391 if (strlen(pargs)>0) strlcat(pargs,",",BUFFER_SIZE) ;
1392 string tmp = processExpression(iter->c_str()) ;
1393 strlcat(pargs,tmp.c_str(),BUFFER_SIZE) ;
1394 pargv.push_back(tmp) ;
1395 ++iter ;
1396 }
1397
1398 string ret = func+"("+pargs+")" ;
1399 return ret ;
1400}
1401
1402
1403
1404
1405////////////////////////////////////////////////////////////////////////////////
1406/// Allocate and fill work buffer
1407
1409{
1410 const size_t bufSize = strlen(funcExpr)+1;
1411 std::vector<char> buf(bufSize);
1412 strlcpy(buf.data(),funcExpr,bufSize) ;
1413 char* bufptr = buf.data();
1414
1415 string func ;
1416 vector<string> args ;
1417
1418 // Process token into arguments
1419 char* save ;
1420 char* tmpx = R__STRTOK_R(buf.data(),"(",&save) ;
1421 func = tmpx ? tmpx : "" ;
1422 char* p = R__STRTOK_R(nullptr,"",&save) ;
1423
1424 // Return here if token is fundamental
1425 if (!p) {
1426 return args ;
1427 }
1428
1429 char* tok = p ;
1430 Int_t blevel=0 ;
1431 bool litmode(false) ;
1432 while(*p) {
1433
1434 // Keep track of opening and closing brackets
1435 if (*p=='{' || *p=='(' || *p=='[') blevel++ ;
1436 if (*p=='}' || *p==')' || *p==']') blevel-- ;
1437
1438 // Keep track of string literals
1439 if (*p=='"' || *p=='\'') litmode = !litmode ;
1440
1441
1442 // If we encounter a comma at zero bracket level
1443 // finalize the current token as a completed argument
1444 // and start the next token
1445 if (!litmode && blevel==0 && ((*p)==',')) {
1446 *p = 0 ;
1447 args.push_back(tok) ;
1448 tok = p+1 ;
1449 }
1450
1451 p++ ;
1452 }
1453
1454 // If the last character was a closing bracket, kill
1455 // it in the buffer
1456 if (p>bufptr && *(p-1)==')') {
1457 *(p-1)=0 ;
1458 }
1459
1460 // Finalize last token as argument
1461 string tmp = tok ;
1462
1463 // If there is a suffix left in the work buffer attach it to
1464 // this argument
1465 p = R__STRTOK_R(nullptr,"",&save) ;
1466 if (p) tmp += p ;
1467 args.push_back(tmp) ;
1468
1469 return args ;
1470}
1471
1472
1473
1474
1475
1476////////////////////////////////////////////////////////////////////////////////
1477/// Perform basic syntax on given factory expression. If function returns
1478/// true syntax errors are found.
1479
1481{
1482 // Count parentheses
1484 Int_t nBracket(0);
1485 Int_t nAccolade(0);
1486 const char* ptr = arg ;
1487 while(*ptr) {
1488 if (*ptr=='(') nParentheses++ ;
1489 if (*ptr==')') nParentheses-- ;
1490 if (*ptr=='[') nBracket++ ;
1491 if (*ptr==']') nBracket-- ;
1492 if (*ptr=='{') nAccolade++ ;
1493 if (*ptr=='}') nAccolade-- ;
1494 ptr++ ;
1495 }
1496 if (nParentheses!=0) {
1497 coutE(ObjectHandling) << "RooFactoryWSTool::checkSyntax ERROR non-matching '" << (nParentheses>0?"(":")") << "' in expression" << std::endl ;
1498 return true ;
1499 }
1500 if (nBracket!=0) {
1501 coutE(ObjectHandling) << "RooFactoryWSTool::checkSyntax ERROR non-matching '" << (nBracket>0?"[":"]") << "' in expression" << std::endl ;
1502 return true ;
1503 }
1504 if (nAccolade!=0) {
1505 coutE(ObjectHandling) << "RooFactoryWSTool::checkSyntax ERROR non-matching '" << (nAccolade>0?"{":"}") << "' in expression" << std::endl ;
1506 return true ;
1507 }
1508 return false ;
1509}
1510
1511
1512
1513////////////////////////////////////////////////////////////////////////////////
1514
1516{
1517 if (idx>_of->_args.size()-1) {
1518 throw string(Form("Need argument number %d, but only %d args are provided",idx,(Int_t)_of->_args.size())) ;
1519 }
1520}
1521
1522
1523
1524////////////////////////////////////////////////////////////////////////////////
1525/// CINT constructor interface, return constructor string argument `#idx` as RooAbsArg reference found in workspace
1526
1528 {
1529 // If arg is a numeric string, make a RooConst() of it here
1530 if (arg[0]=='.' || arg[0]=='+' || arg[0] == '-' || isdigit(arg[0])) {
1531 return RooConst(atof(arg)) ;
1532 }
1533
1534 // Otherwise look it up by name in the workspace
1535 RooAbsArg* rarg = ws().arg(arg) ;
1536 if (!rarg) {
1537 throw string(Form("RooAbsArg named %s not found",arg)) ;
1538 }
1539 return *rarg ;
1540}
1541
1542
1543
1544////////////////////////////////////////////////////////////////////////////////
1545/// CINT constructor interface, return constructor string argument `#idx` as RooAbsReal reference found in workspace
1546
1548{
1549 // If arg is a numeric string, make a RooConst() of it here
1550 if (arg[0]=='.' || arg[0]=='+' || arg[0] == '-' || isdigit(arg[0])) {
1551 return RooConst(atof(arg)) ;
1552 }
1553
1554 RooAbsArg* rarg = ws().arg(arg) ;
1555 if (!rarg) {
1556 throw string(Form("RooAbsReal named %s not found",arg)) ;
1557 }
1558 RooAbsReal* real = dynamic_cast<RooAbsReal*>(rarg) ;
1559 if (!real) {
1560 throw string(Form("Object named %s is not of type RooAbsReal",arg)) ;
1561 }
1562 return *real ;
1563}
1564
1565
1566
1567////////////////////////////////////////////////////////////////////////////////
1568/// CINT constructor interface, return constructor string argument `#idx` as RooAbsRealLValue reference found in workspace
1569
1571{
1572 // If arg is a numeric string, throw error as lvalue is required
1573 if (arg[0]=='.' || arg[0]=='+' || arg[0] == '-' || isdigit(arg[0])) {
1574 throw string(Form("Numeric literal provided for argument (%s), but lvalue is required",arg)) ;
1575 }
1576
1577 RooAbsArg* rarg = ws().arg(arg) ;
1578 if (!rarg) {
1579 throw string(Form("RooAbsRealLValue named %s not found",arg)) ;
1580 }
1581 RooAbsRealLValue* reallv = dynamic_cast<RooAbsRealLValue*>(rarg) ;
1582 if (!reallv) {
1583 throw string(Form("Object named %s is not of type RooAbsRealLValue",arg)) ;
1584 }
1585 return *reallv ;
1586}
1587
1588
1589
1590////////////////////////////////////////////////////////////////////////////////
1591/// CINT constructor interface, return constructor string argument `#idx` as RooRealVar reference found in workspace
1592
1594{
1595 RooRealVar* var = ws().var(arg) ;
1596 if (!var) {
1597 throw string(Form("RooRealVar named %s not found",arg)) ;
1598 }
1599 return *var ;
1600}
1601
1602
1603
1604
1605////////////////////////////////////////////////////////////////////////////////
1606/// CINT constructor interface, return constructor string argument `#idx` as RooAbsPdf reference found in workspace
1607
1609{
1610 RooAbsPdf* pdf = ws().pdf(arg) ;
1611 if (!pdf) {
1612 throw string(Form("RooAbsPdf named %s not found",arg)) ;
1613 }
1614 return *pdf ;
1615}
1616
1617
1618
1619
1620////////////////////////////////////////////////////////////////////////////////
1621/// CINT constructor interface, return constructor string argument `#idx` as RooResolutionModel reference found in workspace
1622
1624{
1625 RooAbsArg* rarg = ws().arg(arg) ;
1626 if (!rarg) {
1627 throw string(Form("RooResolutionModel named %s not found",arg)) ;
1628 }
1629 RooResolutionModel * rmodel = dynamic_cast<RooResolutionModel*>(rarg) ;
1630 if (!rmodel) {
1631 throw string(Form("Object named %s is not of type RooResolutionModel",arg)) ;
1632 }
1633 return *rmodel ;
1634}
1635
1636
1637
1638
1639////////////////////////////////////////////////////////////////////////////////
1640/// CINT constructor interface, return constructor string argument `#idx` as RooAbsCategory reference found in workspace
1641
1643{
1644 RooAbsArg* rarg = ws().arg(arg) ;
1645 if (!rarg) {
1646 throw string(Form("RooAbsCategory named %s not found",arg)) ;
1647 }
1648 RooAbsCategory* catf = dynamic_cast<RooAbsCategory*>(rarg) ;
1649 if (!catf) {
1650 throw string(Form("Object named %s is not of type RooAbsCategory",arg)) ;
1651 }
1652 return *catf ;
1653}
1654
1655
1656
1657////////////////////////////////////////////////////////////////////////////////
1658/// CINT constructor interface, return constructor string argument `#idx` as RooAbsCategoryLValue reference found in workspace
1659
1661{
1662 RooAbsArg* rarg = ws().arg(arg) ;
1663 if (!rarg) {
1664 throw string(Form("RooAbsCategoryLValue named %s not found",arg)) ;
1665 }
1666
1668 if (!catlv) {
1669 throw string(Form("Object named %s is not of type RooAbsCategoryLValue",arg)) ;
1670 }
1671 return *catlv ;
1672}
1673
1674
1675
1676////////////////////////////////////////////////////////////////////////////////
1677/// CINT constructor interface, return constructor string argument `#idx` as RooCategory reference found in workspace
1678
1680{
1681 RooCategory* cat = ws().cat(arg) ;
1682 if (!cat) {
1683 throw string(Form("RooCategory named %s not found",arg)) ;
1684 }
1685 return *cat ;
1686}
1687
1688
1689
1690
1691
1692////////////////////////////////////////////////////////////////////////////////
1693/// CINT constructor interface, return constructor string argument `#idx` as RooArgSet of objects found in workspace
1694
1696{
1697 char tmp[BUFFER_SIZE] ;
1698 strlcpy(tmp,arg,BUFFER_SIZE) ;
1699
1700 RooArgSet s ;
1701
1702 // If given object is not of {,,,} form, interpret given string as name of defined set
1703 if (arg[0]!='{') {
1704 // std::cout << "asSet(arg='" << arg << "') parsing as defined set" << std::endl ;
1705 const RooArgSet* defSet = ws().set(arg) ;
1706 if (defSet) {
1707 // std::cout << "found defined set: " << *defSet << std::endl ;
1708 s.add(*defSet) ;
1709 return s ;
1710 }
1711 }
1712
1713 char* save ;
1714 char* tok = R__STRTOK_R(tmp,",{}",&save) ;
1715 int i(0);
1716 while(tok) {
1717
1718 // If arg is a numeric string, make a RooConst() of it here
1719 if (tok[0]=='.' || tok[0]=='+' || tok[0] == '-' || isdigit(tok[0])) {
1720 s.add(RooConst(atof(tok))) ;
1721 } else if (tok[0] == '\'') {
1722 tok[strlen(tok) - 1] = 0;
1723 RooStringVar *sv = new RooStringVar(Form("string_set_item%03d", i++), "string_set_item", tok + 1);
1724 s.add(*sv);
1725 } else {
1726 RooAbsArg* aarg = ws().arg(tok) ;
1727 if (aarg) {
1728 s.add(*aarg) ;
1729 } else {
1730 throw string(Form("RooAbsArg named %s not found",tok)) ;
1731 }
1732 }
1733 tok = R__STRTOK_R(nullptr,",{}",&save) ;
1734 }
1735
1736 return s ;
1737}
1738
1739
1740
1741////////////////////////////////////////////////////////////////////////////////
1742/// CINT constructor interface, return constructor string argument `#idx` as RooArgList of objects found in workspace
1743
1745{
1746 char tmp[BUFFER_SIZE] ;
1747 strlcpy(tmp,arg,BUFFER_SIZE) ;
1748
1749 RooArgList l ;
1750 char* save ;
1751 char* tok = R__STRTOK_R(tmp,",{}",&save) ;
1752 while(tok) {
1753
1754 // If arg is a numeric string, make a RooConst() of it here
1755 if (tok[0]=='.' || tok[0]=='+' || tok[0] == '-' || isdigit(tok[0])) {
1756 l.add(RooConst(atof(tok))) ;
1757 } else if (tok[0] == '\'') {
1758 tok[strlen(tok) - 1] = 0;
1759 RooStringVar *sv = new RooStringVar("listarg", "listarg", tok + 1);
1760 l.add(*sv);
1761 } else {
1762 RooAbsArg* aarg = ws().arg(tok) ;
1763 if (aarg) {
1764 l.add(*aarg) ;
1765 } else {
1766 throw string(Form("RooAbsArg named %s not found",tok)) ;
1767 }
1768 }
1769 tok = R__STRTOK_R(nullptr,",{}",&save) ;
1770 }
1771
1772 return l ;
1773}
1774
1775
1776
1777////////////////////////////////////////////////////////////////////////////////
1778/// CINT constructor interface, return constructor string argument `#idx` as RooAbsData object found in workspace
1779
1781{
1782 RooAbsData* data = ws().data(arg) ;
1783 if (!data) {
1784 throw string(Form("RooAbsData named %s not found",arg)) ;
1785 }
1786 return *data ;
1787}
1788
1789
1790
1791////////////////////////////////////////////////////////////////////////////////
1792/// CINT constructor interface, return constructor string argument `#idx` as RooDataHist object found in workspace
1793
1795{
1796 RooAbsData* data = ws().data(arg) ;
1797 if (!data) {
1798 throw string(Form("RooAbsData named %s not found",arg)) ;
1799 }
1800 RooDataHist* hist = dynamic_cast<RooDataHist*>(data) ;
1801 if (!hist) {
1802 throw string(Form("Dataset named %s is not of type RooDataHist",arg)) ;
1803 }
1804 return *hist ;
1805}
1806
1807
1808////////////////////////////////////////////////////////////////////////////////
1809/// CINT constructor interface, return constructor string argument `#idx` as RooDataSet object found in workspace
1810
1812{
1813 RooAbsData* data = ws().data(arg) ;
1814 if (!data) {
1815 throw string(Form("RooAbsData named %s not found",arg)) ;
1816 }
1817 RooDataSet* dset = dynamic_cast<RooDataSet*>(data) ;
1818 if (!dset) {
1819 throw string(Form("Dataset named %s is not of type RooDataSet",arg)) ;
1820 }
1821 return *dset ;
1822}
1823
1824
1825
1826////////////////////////////////////////////////////////////////////////////////
1827
1829{
1830 TObject* obj = ws().obj(arg) ;
1831 if (!obj) {
1832 throw string(Form("Object named %s not found",arg)) ;
1833 }
1834 return *obj ;
1835}
1836
1837
1838
1839////////////////////////////////////////////////////////////////////////////////
1840/// CINT constructor interface, return constructor string argument `#idx` as const char*
1841
1842const char* RooFactoryWSTool::asSTRING(const char* arg)
1843{
1844 static vector<string> cbuf(10) ;
1845 static unsigned int cbuf_idx = 0 ;
1846
1847 // Handle empty string case: return null pointer
1848 if (arg==nullptr || strlen(arg)==0) {
1849 return nullptr ;
1850 }
1851
1852 // Fill cyclical buffer entry with quotation marked stripped version of string literal
1853 // and return pointer to stripped buffer
1854 cbuf[cbuf_idx].clear() ;
1855 const char* p = arg+1 ;
1856 while(*p && (*p) != '"' && (*p) !='\'' ) {
1857 cbuf[cbuf_idx] += *(p++) ;
1858 }
1859 const char* ret = cbuf[cbuf_idx].c_str() ;
1860
1861 // Increment buffer pointer by one
1862 cbuf_idx++ ;
1863 if (cbuf_idx==cbuf.size()) cbuf_idx=0 ;
1864
1865 return ret ;
1866}
1867
1868
1869////////////////////////////////////////////////////////////////////////////////
1870/// CINT constructor interface, return constructor string argument `#idx` as Int_t
1871
1873{
1874 return atoi(arg) ;
1875}
1876
1877
1878////////////////////////////////////////////////////////////////////////////////
1879/// CINT constructor interface, return constructor string argument `#idx` as double
1880
1881double RooFactoryWSTool::asDOUBLE(const char* arg)
1882{
1883 return atof(arg) ;
1884}
1885
1886
1887////////////////////////////////////////////////////////////////////////////////
1888/// Register foreign special objects in factory
1889
1891{
1892 hooks()[typeName] = iface ;
1893}
1894
1895
1896
1897////////////////////////////////////////////////////////////////////////////////
1898
1899std::map<std::string,RooFactoryWSTool::IFace*>& RooFactoryWSTool::hooks()
1900{
1901 if (_hooks) return *_hooks ;
1903 return *_hooks ;
1904}
1905
1906
1907
1908////////////////////////////////////////////////////////////////////////////////
1909/// Concatenate list of args into comma separated string
1910
1911std::string RooFactoryWSTool::SpecialsIFace::create(RooFactoryWSTool& ft, const char* typeName, const char* instName, std::vector<std::string> args)
1912{
1913 char pargs[BUFFER_SIZE] ;
1914 pargs[0] = 0 ;
1915 vector<string>::iterator iter = args.begin() ;
1917 while(iter!=args.end()) {
1918 if (strlen(pargs)>0) strlcat(pargs,",",BUFFER_SIZE) ;
1919 string tmp = ft.processExpression(iter->c_str()) ;
1920 strlcat(pargs,tmp.c_str(),BUFFER_SIZE) ;
1921 pargv.push_back(tmp) ;
1922 ++iter ;
1923 }
1924
1925 // Handling of special operator pdf class names
1926 string cl(typeName) ;
1927 if (cl=="SUM") {
1928
1929 // SUM::name[a*A,b*B,C]
1930 ft.add(instName,pargs,false) ;
1931
1932 } else if (cl=="RSUM") {
1933
1934 // RSUM::name[a*A,b*B,C]
1935 ft.add(instName,pargs,true) ;
1936
1937 } else if (cl=="ASUM") {
1938
1939 // ASUM::name[a*A,b*B,C]
1940 ft.amplAdd(instName,pargs) ;
1941
1942 } else if (cl=="PROD") {
1943
1944 // PROD::name[A,B,C]
1945 ft.prod(instName,pargs) ;
1946
1947 } else if (cl=="SIMUL") {
1948
1949 // PROD::name[cat,state=Pdf,...]
1950 if (pargv.size()>1) {
1951 ft.simul(instName,pargv[0].c_str(),strchr(pargs,',')+1) ;
1952 } else {
1953 throw string(Form("Need at least two arguments in call to SIMUL::%s, have %d: %s",instName,(Int_t)pargv.size(),pargs)) ;
1954 }
1955
1956 } else if (cl=="EXPR") {
1957
1958 // EXPR::name['expr',var,var,...]
1959 if (args.size()<=2) {
1960 ft.createArg("RooGenericPdf",instName,pargs) ;
1961 } else {
1962 char genargs[BUFFER_SIZE] ;
1963 strlcpy(genargs,args[0].c_str(),BUFFER_SIZE) ;
1965 for (UInt_t i=1 ; i<args.size() ; i++) {
1966 if (i!=1) strlcat(genargs,",",BUFFER_SIZE) ;
1967 strlcat(genargs,args[i].c_str(),BUFFER_SIZE) ;
1968 }
1970 ft.createArg("RooGenericPdf",instName,genargs) ;
1971 }
1972
1973 } else if (cl=="FCONV") {
1974
1975 // FCONV::name[var,pdf1,pdf2]
1976 ft.createArg("RooFFTConvPdf",instName,pargs) ;
1977
1978 } else if (cl=="NCONV") {
1979
1980 // NCONV::name[var,pdf1,pdf2]
1981 ft.createArg("RooNumConvPdf",instName,pargs) ;
1982
1983 } else if (cl=="sum") {
1984
1985 // sum::name[a,b,c]
1986 ft.addfunc(instName,pargs) ;
1987
1988 } else if (cl=="prod") {
1989
1990 // prod::name[a,b,c]
1991 ft.prodfunc(instName,pargs) ;
1992
1993 } else if (cl=="expr") {
1994
1995 // expr::name['expr',var,var,...]
1996 if (args.size()<=2) {
1997 ft.createArg("RooFormulaVar",instName,pargs) ;
1998 } else {
1999 char genargs[BUFFER_SIZE] ;
2000 strlcpy(genargs,args[0].c_str(),BUFFER_SIZE) ;
2002 for (UInt_t i=1 ; i<args.size() ; i++) {
2003 if (i!=1) strlcat(genargs,",",BUFFER_SIZE) ;
2004 strlcat(genargs,args[i].c_str(),BUFFER_SIZE) ;
2005 }
2007 ft.createArg("RooFormulaVar",instName,genargs) ;
2008 }
2009
2010 } else if (cl == "taylorexpand") {
2011
2012 // taylorexpand::name[func,{var,var,..},val,order]
2013 int order(1);
2014 double eps1(1e-6);
2015 double eps2(1e-3);
2016 double observablesValue(0.0);
2017
2018 if (pargv.size() < 2)
2019 throw string(Form("taylorexpand::%s, requires atleast 2 arguments (function, observables) atleast, has %d arguments", instName, (Int_t)pargv.size()));
2020
2021 RooAbsReal &func = ft.asFUNC(pargv[0].c_str());
2022 RooArgList observables = ft.asLIST(pargv[1].c_str());
2023
2024 if (pargv.size() > 3)
2025 order = atoi(pargv[3].c_str());
2026 if (pargv.size() > 2) {
2027 if (pargv[2].find(',') != string::npos) {
2028 throw string(
2029 Form("taylorexpand::%s, factory syntax supports expansion only around same value for all observables", instName));
2030 } else {
2031 observablesValue = atof(pargv[2].c_str());
2032 }
2033 }
2034
2035 if (pargv.size() > 3)
2036 order = atoi(pargv[3].c_str());
2037 if (pargv.size() > 4)
2038 eps1 = atof(pargv[4].c_str());
2039 if (pargv.size() > 5)
2040 eps2 = atof(pargv[5].c_str());
2041
2042 if (pargv.size() > 6) {
2043 throw string(
2044 Form("taylorexpand::%s, requires max. 6 arguments, has %d arguments", instName, (Int_t)pargv.size()));
2045 }
2046
2047 auto taylor = RooPolyFunc::taylorExpand(instName, instName, func, observables, order, {observablesValue}, eps1, eps2);
2048 if (ft.ws().import(*taylor, Silence())) ft.logError();
2049
2050 } else if (cl=="nconv") {
2051
2052 // nconv::name[var,pdf1,pdf2]
2053 ft.createArg("RooNumConvolution",instName,pargs) ;
2054
2055#ifdef ROOFIT_LEGACY_EVAL_BACKEND
2056 } else if (cl=="nll") {
2057
2058 // nll::name[pdf,data]
2059 RooNLLVar nll(instName,instName,ft.asPDF(pargv[0].c_str()),ft.asDATA(pargv[1].c_str()), /*extended=*/false) ;
2060 if (ft.ws().import(nll,Silence())) ft.logError() ;
2061
2062 } else if (cl=="chi2") {
2063
2064 // chi2::name[pdf,data]
2065 RooChi2Var nll(instName,instName,ft.asPDF(pargv[0].c_str()),ft.asDHIST(pargv[1].c_str()), /*extended=*/false, /*etype=*/RooAbsData::Auto);
2066 if (ft.ws().import(nll,Silence())) ft.logError() ;
2067
2068#endif
2069 } else if (cl=="profile") {
2070
2071 // profile::name[func,vars]
2072 ft.createArg("RooProfileLL",instName,pargs) ;
2073
2074 } else if (cl=="dataobs") {
2075
2076 // dataobs::name[dset,func]
2077 std::unique_ptr<RooAbsArg> funcClone{static_cast<RooAbsArg*>(ft.asARG(pargv[1].c_str()).clone(instName))};
2078 RooAbsArg* arg = ft.asDSET(pargv[0].c_str()).addColumn(*funcClone) ;
2079 if (!ft.ws().fundArg(arg->GetName())) {
2080 if (ft.ws().import(*arg,Silence())) ft.logError() ;
2081 }
2082
2083 } else if (cl=="int") {
2084
2085 // int::name[func,intobs]
2086 // int::name[func,intobs|range]
2087 // int::name[func,intobs,normobs]
2088 // int::name[func,intobs|range,normobs]
2089
2090 if (pargv.size()<2 || pargv.size()>3) {
2091 throw string(Form("int::%s, requires 2 or 3 arguments, have %d arguments",instName,(Int_t)pargv.size())) ;
2092 }
2093
2094 RooAbsReal& func = ft.asFUNC(pargv[0].c_str()) ;
2095
2096 char buf[256] ;
2097 strlcpy(buf,pargv[1].c_str(),256) ;
2098 char* save ;
2099 const char* intobs = R__STRTOK_R(buf,"|",&save) ;
2100 if (!intobs) intobs="" ;
2101
2102 const char* range = R__STRTOK_R(nullptr,"",&save) ;
2103 if (!range) range="" ;
2104
2105 std::unique_ptr<RooAbsReal> integral;
2106 if (pargv.size()==2) {
2107 if (range && strlen(range)) {
2108 integral = std::unique_ptr<RooAbsReal>{func.createIntegral(ft.asSET(intobs),Range(range))};
2109 } else {
2110 integral = std::unique_ptr<RooAbsReal>{func.createIntegral(ft.asSET(intobs))};
2111 }
2112 } else {
2113 if (range && strlen(range)) {
2114 integral = std::unique_ptr<RooAbsReal>{func.createIntegral(ft.asSET(intobs),Range(range),NormSet(ft.asSET(pargv[2].c_str())))};
2115 } else {
2116 integral = std::unique_ptr<RooAbsReal>{func.createIntegral(ft.asSET(intobs),NormSet(ft.asSET(pargv[2].c_str())))};
2117 }
2118 }
2119
2120 integral->SetName(instName) ;
2121 if (ft.ws().import(*integral,Silence())) ft.logError() ;
2122
2123 } else if (cl=="deriv") {
2124
2125 // derive::name[func,obs,order]
2126
2127 if (pargv.size()<2 || pargv.size()>3) {
2128 throw string(Form("deriv::%s, requires 2 or 3 arguments, have %d arguments",instName,(Int_t)pargv.size())) ;
2129 }
2130
2131 RooAbsReal& func = ft.asFUNC(pargv[0].c_str()) ;
2132
2133 std::unique_ptr<RooAbsReal> derivative;
2134 if (pargv.size()==2) {
2135 derivative.reset(func.derivative(ft.asVAR(pargv[1].c_str()),1));
2136 } else {
2137 derivative.reset(func.derivative(ft.asVAR(pargv[1].c_str()),ft.asINT(pargv[2].c_str())));
2138 }
2139
2140 derivative->SetName(instName) ;
2141 if (ft.ws().import(*derivative,Silence())) ft.logError() ;
2142
2143 } else if (cl=="cdf") {
2144
2145 // cdf::name[pdf,obs,extranormobs]
2146
2147 if (pargv.size()<2 || pargv.size()>3) {
2148 throw string(Form("cdf::%s, requires 2 or 3 arguments, have %d arguments",instName,(Int_t)pargv.size())) ;
2149 }
2150
2151 RooAbsPdf& pdf = ft.asPDF(pargv[0].c_str()) ;
2152
2153 std::unique_ptr<RooAbsReal> cdf;
2154 if (pargv.size()==2) {
2155 cdf = std::unique_ptr<RooAbsReal>{pdf.createCdf(ft.asSET(pargv[1].c_str()))};
2156 } else {
2157 cdf = std::unique_ptr<RooAbsReal>{pdf.createCdf(ft.asSET(pargv[1].c_str()),ft.asSET(pargv[2].c_str()))};
2158 }
2159
2160 cdf->SetName(instName) ;
2161 if (ft.ws().import(*cdf,Silence())) ft.logError() ;
2162
2163
2164 } else if (cl=="PROJ") {
2165
2166 // PROJ::name(pdf,intobs)
2167 if (pargv.size()!=2) {
2168 throw string(Form("PROJ::%s, requires 2 arguments, have %d arguments",instName,(Int_t)pargv.size())) ;
2169 }
2170
2171 RooAbsPdf& pdf = ft.asPDF(pargv[0].c_str()) ;
2172 std::unique_ptr<RooAbsPdf> projection{pdf.createProjection(ft.asSET(pargv[1].c_str()))};
2173 projection->SetName(instName) ;
2174
2175 if (ft.ws().import(*projection,Silence())) ft.logError() ;
2176
2177 } else if (cl=="set") {
2178
2179 // set::name(arg,arg,...)
2180 if (ft.ws().defineSet(instName,pargs)) {
2181 ft.logError() ;
2182 return string(instName) ;
2183 }
2184
2185 } else {
2186
2187 throw string(Form("RooFactoryWSTool::SpecialsIFace::create() ERROR: Unknown meta-type %s",typeName)) ;
2188
2189 }
2190 return string(instName) ;
2191}
2192
2193
2195{
2196 return _of ;
2197}
2198
#define e(i)
Definition RSha256.hxx:103
#define BUFFER_SIZE
#define cxcoutD(a)
#define coutE(a)
int Int_t
Definition RtypesCore.h:45
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
@ kIsPublic
Definition TDictionary.h:75
@ kIsEnum
Definition TDictionary.h:68
@ kIsConstPointer
Definition TDictionary.h:90
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void data
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t property
char name[80]
Definition TGX11.cxx:110
float xmin
float xmax
#define gInterpreter
#define gROOT
Definition TROOT.h:406
char * Form(const char *fmt,...)
Formats a string in a circular formatting buffer.
Definition TString.cxx:2489
const_iterator begin() const
const_iterator end() const
Common abstract base class for objects that represent a value and a "shape" in RooFit.
Definition RooAbsArg.h:77
void setStringAttribute(const Text_t *key, const Text_t *value)
Associate string 'value' to this object under key 'key'.
Abstract base class for objects that represent a discrete value that can be set from the outside,...
A space to attach TBranches.
virtual bool add(const RooAbsArg &var, bool silent=false)
Add the specified argument to list.
Storage_t::size_type size() const
Abstract base class for binned and unbinned datasets.
Definition RooAbsData.h:57
Abstract interface for all probability density functions.
Definition RooAbsPdf.h:40
RooFit::OwningPtr< RooAbsReal > createCdf(const RooArgSet &iset, const RooArgSet &nset=RooArgSet())
Create a cumulative distribution function of this p.d.f in terms of the observables listed in iset.
virtual RooAbsPdf * createProjection(const RooArgSet &iset)
Return a p.d.f that represent a projection of this p.d.f integrated over given observables.
Abstract base class for objects that represent a real value that may appear on the left hand side of ...
Abstract base class for objects that represent a real value and implements functionality common to al...
Definition RooAbsReal.h:59
RooDerivative * derivative(RooRealVar &obs, Int_t order=1, double eps=0.001)
Return function representing first, second or third order derivative of this function.
RooFit::OwningPtr< RooAbsReal > createIntegral(const RooArgSet &iset, const RooCmdArg &arg1, const RooCmdArg &arg2={}, const RooCmdArg &arg3={}, const RooCmdArg &arg4={}, const RooCmdArg &arg5={}, const RooCmdArg &arg6={}, const RooCmdArg &arg7={}, const RooCmdArg &arg8={}) const
Create an object that represents the integral of the function over one or more observables listed in ...
Efficient implementation of a sum of PDFs of the form.
Definition RooAddPdf.h:33
Calculates the sum of a set of RooAbsReal terms, or when constructed with two sets,...
Definition RooAddition.h:27
RooArgList is a container object that can hold multiple RooAbsArg objects.
Definition RooArgList.h:22
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Definition RooArgSet.h:24
Object to represent discrete states.
Definition RooCategory.h:28
bool defineType(const std::string &label)
Define a state with given name.
Simple calculation from a binned dataset and a PDF.
Definition RooChi2Var.h:19
Container class to hold N-dimensional binned data.
Definition RooDataHist.h:40
Container class to hold unbinned data.
Definition RooDataSet.h:34
std::string create(RooFactoryWSTool &ft, const char *typeName, const char *instanceName, std::vector< std::string > args) override
Concatenate list of args into comma separated string.
Implementation detail of the RooWorkspace.
RooWorkspace & ws()
static RooAbsReal & as_FUNC(UInt_t idx)
RooWorkspace * _ws
RooAddPdf * add(const char *objName, const char *specList, bool recursiveCoefs=false)
RooAbsArg & asARG(const char *)
CINT constructor interface, return constructor string argument #idx as RooAbsArg reference found in w...
RooAbsArg * process(const char *expr)
Create a RooFit object from the given expression.
RooCategory & asCAT(const char *)
CINT constructor interface, return constructor string argument #idx as RooCategory reference found in...
static void checkIndex(UInt_t index)
static RooFactoryWSTool * of()
static RooAbsArg & as_ARG(UInt_t idx)
static RooAbsRealLValue & as_VARLV(UInt_t idx)
RooAbsPdf & asPDF(const char *)
CINT constructor interface, return constructor string argument #idx as RooAbsPdf reference found in w...
RooDataSet & asDSET(const char *)
CINT constructor interface, return constructor string argument #idx as RooDataSet object found in wor...
std::string processListExpression(const char *arg)
Process a list of high-level expression.
RooRealVar & asVAR(const char *)
CINT constructor interface, return constructor string argument #idx as RooRealVar reference found in ...
static void registerSpecial(const char *typeName, RooFactoryWSTool::IFace *iface)
Register foreign special objects in factory.
std::string processExpression(const char *expr)
Process a single high-level expression or list of expressions.
static RooFactoryWSTool * _of
static TObject & as_OBJ(UInt_t idx)
std::string processAliasExpression(const char *arg)
Parse token.
RooAbsRealLValue & asVARLV(const char *)
CINT constructor interface, return constructor string argument #idx as RooAbsRealLValue reference fou...
static RooAbsCategoryLValue & as_CATLV(UInt_t idx)
Int_t asINT(const char *)
CINT constructor interface, return constructor string argument #idx as Int_t.
RooAddition * addfunc(const char *objName, const char *specList)
static RooDataHist & as_DHIST(UInt_t idx)
RooAbsData & asDATA(const char *)
CINT constructor interface, return constructor string argument #idx as RooAbsData object found in wor...
RooAbsArg * createArg(const char *className, const char *objName, const char *varList)
Low-level factory interface for creating a RooAbsPdf of a given class with a given list of input vari...
std::string processCreateArg(std::string &func, std::vector< std::string > &args)
Glue function between high-level syntax and low-level factory call to createArg: Process a parsed cal...
static RooResolutionModel & as_RMODEL(UInt_t idx)
static const char * as_STRING(UInt_t idx)
static RooAbsData & as_DATA(UInt_t idx)
static std::map< std::string, IFace * > & hooks()
void clearError()
Associated workspace.
std::string varTag(std::string &func, std::vector< std::string > &args)
static RooArgList as_LIST(UInt_t idx)
RooCategory * createCategory(const char *name, const char *stateNameList=nullptr)
Low-level factory interface for creating a RooCategory with a given list of state names.
static RooDataSet & as_DSET(UInt_t idx)
RooRealVar * createVariable(const char *name, double xmin, double xmax)
Low-level factory interface for creating a RooRealVar with a given range and initial value.
RooResolutionModel & asRMODEL(const char *)
CINT constructor interface, return constructor string argument #idx as RooResolutionModel reference f...
std::string processMetaArg(std::string &func, std::vector< std::string > &args)
Concatenate list of args into comma separated string.
static std::map< std::string, IFace * > * _hooks
TObject & asOBJ(const char *)
RooArgList asLIST(const char *)
CINT constructor interface, return constructor string argument #idx as RooArgList of objects found in...
RooSimultaneous * simul(const char *objName, const char *indexCat, const char *pdfMap)
static RooArgSet as_SET(UInt_t idx)
static RooAbsCategory & as_CATFUNC(UInt_t idx)
std::string processCompositeExpression(const char *arg)
Process a single composite expression.
TClass * resolveClassName(const char *className)
RooAbsCategory & asCATFUNC(const char *)
CINT constructor interface, return constructor string argument #idx as RooAbsCategory reference found...
static double as_DOUBLE(UInt_t idx)
const char * asSTRING(const char *)
CINT constructor interface, return constructor string argument #idx as const char*.
static RooAbsPdf & as_PDF(UInt_t idx)
RooProdPdf * prod(const char *objName, const char *pdfList)
std::vector< std::string > _args
RooRealSumPdf * amplAdd(const char *objName, const char *specList)
std::stack< std::string > _autoNamePrefix
RooDataHist & asDHIST(const char *)
CINT constructor interface, return constructor string argument #idx as RooDataHist object found in wo...
RooProduct * prodfunc(const char *objName, const char *pdfList)
RooAbsReal & asFUNC(const char *)
CINT constructor interface, return constructor string argument #idx as RooAbsReal reference found in ...
RooAbsCategoryLValue & asCATLV(const char *)
CINT constructor interface, return constructor string argument #idx as RooAbsCategoryLValue reference...
static RooCategory & as_CAT(UInt_t idx)
static Int_t as_INT(UInt_t idx)
std::string processSingleExpression(const char *arg)
Process a single high-level expression.
std::vector< std::string > splitFunctionArgs(const char *funcExpr)
Allocate and fill work buffer.
static RooRealVar & as_VAR(UInt_t idx)
double asDOUBLE(const char *)
CINT constructor interface, return constructor string argument #idx as double.
std::map< std::string, std::string > _typeAliases
RooArgSet asSET(const char *)
CINT constructor interface, return constructor string argument #idx as RooArgSet of objects found in ...
bool checkSyntax(const char *arg)
Perform basic syntax on given factory expression.
std::string processCreateVar(std::string &func, std::vector< std::string > &args)
Glue function between high-level syntax and low-level factory call to createVariable: Process a parse...
Collection class for internal use, storing a collection of RooAbsArg pointers in a doubly linked list...
Implements a -log(likelihood) calculation from a dataset and a PDF.
Definition RooNLLVar.h:20
static std::unique_ptr< RooPolyFunc > taylorExpand(const char *name, const char *title, RooAbsReal &func, const RooArgList &observables, int order=1, std::vector< double > const &observableValues={}, double eps1=1e-6, double eps2=1e-3)
Taylor expanding given function in terms of observables around observableValues.
Efficient implementation of a product of PDFs of the form.
Definition RooProdPdf.h:36
Represents the product of a given set of RooAbsReal objects.
Definition RooProduct.h:29
Implements a PDF constructed from a sum of functions:
Variable that can be changed from the outside.
Definition RooRealVar.h:37
RooResolutionModel is the base class for PDFs that represent a resolution model that can be convolute...
Facilitates simultaneous fitting of multiple PDFs to subsets of a given dataset.
A RooAbsArg implementing string values.
TObject * obj(RooStringView name) const
Return any type of object (RooAbsArg, RooAbsData or generic object) with given name)
RooAbsPdf * pdf(RooStringView name) const
Retrieve p.d.f (RooAbsPdf) with given name. A null pointer is returned if not found.
RooCategory * cat(RooStringView name) const
Retrieve discrete variable (RooCategory) with given name. A null pointer is returned if not found.
const RooArgSet * set(RooStringView name)
Return pointer to previously defined named set with given nmame If no such set is found a null pointe...
bool commitTransaction()
bool cancelTransaction()
Cancel an ongoing import transaction.
bool startTransaction()
Open an import transaction operations.
RooAbsReal * function(RooStringView name) const
Retrieve function (RooAbsReal) with given name. Note that all RooAbsPdfs are also RooAbsReals....
RooAbsArg * arg(RooStringView name) const
Return RooAbsArg with given name. A null pointer is returned if none is found.
RooRealVar * var(RooStringView name) const
Retrieve real-valued variable (RooRealVar) with given name. A null pointer is returned if not found.
RooAbsData * data(RooStringView name) const
Retrieve dataset (binned or unbinned) with given name. A null pointer is returned if not found.
bool import(const RooAbsArg &arg, const RooCmdArg &arg1={}, const RooCmdArg &arg2={}, const RooCmdArg &arg3={}, const RooCmdArg &arg4={}, const RooCmdArg &arg5={}, const RooCmdArg &arg6={}, const RooCmdArg &arg7={}, const RooCmdArg &arg8={}, const RooCmdArg &arg9={})
Import a RooAbsArg object, e.g.
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition TClass.h:84
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:3069
static TEnum * GetEnum(const std::type_info &ti, ESearchAction sa=kALoadAndInterpLookup)
Definition TEnum.cxx:182
TObject * Clone(const char *newname="") const override
Make a clone of an object using the Streamer facility.
Definition TNamed.cxx:74
const char * GetName() const override
Returns name of object.
Definition TNamed.h:47
static TClass * Class()
Mother of all ROOT objects.
Definition TObject.h:41
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition TObject.cxx:542
RooCmdArg Conditional(const RooArgSet &pdfSet, const RooArgSet &depSet, bool depsAreCond=false)
RooConstVar & RooConst(double val)
RooCmdArg Silence(bool flag=true)
RooCmdArg NormSet(Args_t &&... argsOrArgSet)
The namespace RooFit contains mostly switches that change the behaviour of functions of PDFs (or othe...
Definition CodegenImpl.h:64
@ ObjectHandling
Ta Range(0, 0, 1, 1)
TLine l
Definition textangle.C:4
static uint64_t sum(uint64_t i)
Definition Factory.cxx:2345