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