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