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