Logo ROOT  
Reference Guide
RooMsgService.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 RooMsgService.cxx
19\class RooMsgService
20\ingroup Roofitcore
21
22
23The RooMsgService class is a singleton class that organizes informational, debugging,
24warning and errors messages generated by the RooFit core code.
25Each message generated by the core
26has a message level RooFit::MsgLevel (DEBUG,INFO,PROGRESS,WARNING,ERROR or FATAL), an originating object,
27and a 'topic'. Currently implemented topics are "Generation","Plotting",
28"Integration", "Minimization" and "Workspace" and "ChangeTracking".
29The RooMsgService class allows to filter and redirect messages into 'streams'
30according to message level, topic, (base) class of originating object, name of originating
31object and based on attribute labels attached to individual objects.
32The current default configuration creates streams for all messages at WARNING level
33or higher (e.g. ERROR and FATAL) and for all INFO message on topics Generation,Plotting,
34Integration and Minimization and redirects them to stdout. Users can create additional streams
35for logging of e.g. DEBUG messages on particular topics or objects and or redirect streams to
36C++ streams or files.
37The singleton instance is accessible through RooMsgService::instance() ;
38
39**/
40
41
42#include <sys/types.h>
43
44#include "RooFit.h"
45#include "RooAbsArg.h"
46#include "TClass.h"
47#include "TROOT.h"
48
49#include "RooMsgService.h"
50#include "RooCmdArg.h"
51#include "RooCmdConfig.h"
52#include "RooGlobalFunc.h"
53#include "RooWorkspace.h"
54
55#include "TSystem.h"
56#include "Riostream.h"
57#include <iomanip>
58using namespace std ;
59using namespace RooFit ;
60
62
64
65
66////////////////////////////////////////////////////////////////////////////////
67/// Constructor. Defines names of message levels
68/// and mapping of topic codes to topic names
69/// Install default message streams.
70
72{
73 _devnull = new ofstream("/dev/null") ;
74
75 _levelNames[DEBUG]="DEBUG" ;
76 _levelNames[INFO]="INFO" ;
77 _levelNames[PROGRESS]="PROGRESS" ;
78 _levelNames[WARNING]="WARNING" ;
79 _levelNames[ERROR]="ERROR" ;
80 _levelNames[FATAL]="FATAL" ;
81
82 _topicNames[Generation]="Generation" ;
83 _topicNames[Minimization]="Minization" ;
84 _topicNames[Plotting]="Plotting" ;
85 _topicNames[Fitting]="Fitting" ;
86 _topicNames[Integration]="Integration" ;
87 _topicNames[LinkStateMgmt]="LinkStateMgmt" ;
88 _topicNames[Eval]="Eval" ;
89 _topicNames[Caching]="Caching" ;
90 _topicNames[Optimization]="Optimization" ;
91 _topicNames[ObjectHandling]="ObjectHandling" ;
92 _topicNames[InputArguments]="InputArguments" ;
93 _topicNames[Tracing]="Tracing" ;
94 _topicNames[Contents]="Contents" ;
95 _topicNames[DataHandling]="DataHandling" ;
96 _topicNames[NumIntegration]="NumericIntegration" ;
97 _topicNames[HistFactory]="HistFactory";
98
99 reset();
100}
101
102
105 _showPid = kFALSE ;
108
109 delete _debugWorkspace;
110 _debugWorkspace = nullptr;
111 _debugCode = 0 ;
112
113 for (auto item : _files) {
114 delete item.second;
115 }
116 _files.clear();
117
118 // Old-style streams
119 _streams.clear();
120 addStream(RooFit::PROGRESS, Topic(RooFit::HistFactory - 1));//All before HistFactory
123}
124
125
126////////////////////////////////////////////////////////////////////////////////
127/// Destructor
128
130{
131 // Delete all ostreams we own ;
132 map<string,ostream*>::iterator iter = _files.begin() ;
133 for (; iter != _files.end() ; ++iter) {
134 delete iter->second ;
135 }
136
137 if (_debugWorkspace) {
138 delete _debugWorkspace ;
139 }
140
141 delete _devnull ;
142}
143
144
145
146////////////////////////////////////////////////////////////////////////////////
147/// Returns true if any debug level stream is active
148
150{
151 return instance()._debugCount>0 ;
152}
153
154
155
156////////////////////////////////////////////////////////////////////////////////
157
159{
160 if (!_debugWorkspace) {
161 _debugWorkspace = new RooWorkspace("wdebug") ;
162 }
163 return _debugWorkspace ;
164}
165
166
167
168////////////////////////////////////////////////////////////////////////////////
169/// Add a message logging stream for message with given RooFit::MsgLevel or higher (i.e. more severe)
170/// This method accepts the following arguments to configure the stream
171///
172/// Output Style options
173/// --------------------
174/// Prefix(Bool_t flag=kTRUE) -- Prefix all messages in this stream with Topic/Originator information
175///
176/// Filtering options
177/// -----------------
178/// Topic(const char*) -- Restrict stream to messages on given topic
179/// ObjectName(const char*) -- Restrict stream to messages from object with given name
180/// ClassName(const char*) -- Restrict stream to messages from objects with given class name
181/// BaseClassName(const char*)-- Restrict stream to messages from objects with given base class name
182/// LabelName(const chat*) -- Restrict stream to messages from objects setAtrribute(const char*) tag with given name
183///
184/// Output redirection options
185/// --------------------------
186/// OutputFile(const char*) -- Send output to file with given name. Multiple streams can write to same file.
187/// OutputStream(ostream&) -- Send output to given C++ stream. Multiple message streams can write to same c++ stream
188///
189/// The return value is the unique ID code of the defined stream
190
191Int_t RooMsgService::addStream(RooFit::MsgLevel level, const RooCmdArg& arg1, const RooCmdArg& arg2, const RooCmdArg& arg3,
192 const RooCmdArg& arg4, const RooCmdArg& arg5, const RooCmdArg& arg6)
193{
194
195 // Aggregate all arguments in a list
197 l.Add((TObject*)&arg1) ; l.Add((TObject*)&arg2) ;
198 l.Add((TObject*)&arg3) ; l.Add((TObject*)&arg4) ;
199 l.Add((TObject*)&arg5) ; l.Add((TObject*)&arg6) ;
200
201 // Define configuration for this method
202 RooCmdConfig pc(Form("RooMsgService::addReportingStream(%s)",GetName())) ;
203 pc.defineInt("prefix","Prefix",0,kTRUE) ;
204 pc.defineInt("color","Color",0,static_cast<Int_t>(kBlack)) ;
205 pc.defineInt("topic","Topic",0,0xFFFFF) ;
206 pc.defineString("objName","ObjectName",0,"") ;
207 pc.defineString("className","ClassName",0,"") ;
208 pc.defineString("baseClassName","BaseClassName",0,"") ;
209 pc.defineString("tagName","LabelName",0,"") ;
210 pc.defineString("outFile","OutputFile",0,"") ;
211 pc.defineObject("outStream","OutputStream",0,0) ;
212 pc.defineMutex("OutputFile","OutputStream") ;
213
214 // Process & check varargs
215 pc.process(l) ;
216 if (!pc.ok(kTRUE)) {
217 return -1 ;
218 }
219
220 // Extract values from named arguments
221 RooFit::MsgTopic topic = (RooFit::MsgTopic) pc.getInt("topic") ;
222 const char* objName = pc.getString("objName") ;
223 const char* className = pc.getString("className") ;
224 const char* baseClassName = pc.getString("baseClassName") ;
225 const char* tagName = pc.getString("tagName") ;
226 const char* outFile = pc.getString("outFile") ;
227 Bool_t prefix = pc.getInt("prefix") ;
228 Color_t color = static_cast<Color_t>(pc.getInt("color")) ;
229 ostream* os = reinterpret_cast<ostream*>(pc.getObject("outStream")) ;
230
231 // Create new stream object
232 StreamConfig newStream ;
233
234 // Store configuration info
235 newStream.active = kTRUE ;
236 newStream.minLevel = level ;
237 newStream.topic = topic ;
238 newStream.objectName = (objName ? objName : "" ) ;
239 newStream.className = (className ? className : "" ) ;
240 newStream.baseClassName = (baseClassName ? baseClassName : "" ) ;
241 newStream.tagName = (tagName ? tagName : "" ) ;
242 newStream.color = color ;
243 newStream.prefix = prefix ;
244 newStream.universal = (newStream.objectName=="" && newStream.className=="" && newStream.baseClassName=="" && newStream.tagName=="") ;
245
246 // Update debug stream count
247 if (level==DEBUG) {
248 _debugCount++ ;
249 }
250
251 // Configure output
252 if (os) {
253
254 // To given non-owned stream
255 newStream.os = os ;
256
257 } else if (string(outFile).size()>0) {
258
259 // See if we already opened the file
260 ostream* os2 = _files["outFile"] ;
261
262 if (!os2) {
263
264 // To given file name, create owned stream for it
265 os2 = new ofstream(outFile) ;
266
267 if (!*os2) {
268 cout << "RooMsgService::addReportingStream ERROR: cannot open output log file " << outFile << " reverting stream to stdout" << endl ;
269 delete os2 ;
270 newStream.os = &cout ;
271 } else {
272 newStream.os = os2 ;
273 }
274
275 } else {
276 _files["outFile"] = os2 ;
277 newStream.os = os2 ;
278 }
279
280
281 } else {
282
283 // To stdout
284 newStream.os = &cout ;
285
286 }
287
288
289 // Add it to list of active streams ;
290 _streams.push_back(newStream) ;
291
292 // Return stream identifier
293 return _streams.size()-1 ;
294}
295
296
297
298////////////////////////////////////////////////////////////////////////////////
299/// Delete stream with given unique ID code
300
302{
303 vector<StreamConfig>::iterator iter = _streams.begin() ;
304 iter += id ;
305
306 // Update debug stream count
307 if (iter->minLevel==DEBUG) {
308 _debugCount-- ;
309 }
310
311 _streams.erase(iter) ;
312}
313
314
315
316////////////////////////////////////////////////////////////////////////////////
317/// (De)Activate stream with given unique ID
318
320{
321 if (id<0 || id>=static_cast<Int_t>(_streams.size())) {
322 cout << "RooMsgService::setStreamStatus() ERROR: invalid stream ID " << id << endl ;
323 return ;
324 }
325
326 // Update debug stream count
327 if (_streams[id].minLevel==DEBUG) {
328 _debugCount += flag ? 1 : -1 ;
329 }
330
331 _streams[id].active = flag ;
332}
333
334
335
336////////////////////////////////////////////////////////////////////////////////
337/// Get activation status of stream with given unique ID
338
340{
341 if (id<0 || id>= static_cast<Int_t>(_streams.size())) {
342 cout << "RooMsgService::getStreamStatus() ERROR: invalid stream ID " << id << endl ;
343 return kFALSE ;
344 }
345 return _streams[id].active ;
346}
347
348
349
350////////////////////////////////////////////////////////////////////////////////
351/// Return reference to singleton instance
352
354{
355 static RooMsgService instance;
356 return instance;
357}
358
359
360
361////////////////////////////////////////////////////////////////////////////////
362/// Save current state of message service
363
365{
366 _streamsSaved.push(_streams) ;
367}
368
369
370
371////////////////////////////////////////////////////////////////////////////////
372/// Restore last saved state of message service
373
375{
376 _streams = _streamsSaved.top() ;
377 _streamsSaved.pop() ;
378}
379
380
381
382////////////////////////////////////////////////////////////////////////////////
383/// Check if logging is active for given object/topic/RooFit::MsgLevel combination
384
386{
387 return (activeStream(self,topic,level)>=0) ;
388}
389
390
391////////////////////////////////////////////////////////////////////////////////
392/// Check if logging is active for given object/topic/RooFit::MsgLevel combination
393
395{
396 return (activeStream(self,topic,level)>=0) ;
397}
398
399
400////////////////////////////////////////////////////////////////////////////////
401/// Find appropriate logging stream for message from given object with given topic and message level
402
404{
405 if (level<_globMinLevel) return -1 ;
406 for (UInt_t i=0 ; i<_streams.size() ; i++) {
407 if (_streams[i].match(level,topic,self)) {
408 return i ;
409 }
410 }
411 return -1 ;
412}
413
414
415////////////////////////////////////////////////////////////////////////////////
416/// Find appropriate logging stream for message from given object with given topic and message level
417
419{
420 if (level<_globMinLevel) return -1 ;
421 for (UInt_t i=0 ; i<_streams.size() ; i++) {
422 if (_streams[i].match(level,topic,self)) {
423 return i ;
424 }
425 }
426 return -1 ;
427}
428
429
430////////////////////////////////////////////////////////////////////////////////
431/// Determine if message from given object at given level on given topic is logged
432
434{
435 if (!active) return kFALSE ;
436 if (level<minLevel) return kFALSE ;
437 if (!(topic&top)) return kFALSE ;
438
439 if (universal) return kTRUE ;
440
441 if (objectName.size()>0 && objectName != obj->GetName()) return kFALSE ;
442 if (className.size()>0 && className != obj->IsA()->GetName()) return kFALSE ;
443 if (baseClassName.size()>0 && !obj->IsA()->InheritsFrom(baseClassName.c_str())) return kFALSE ;
444 if (tagName.size()>0 && !obj->getAttribute(tagName.c_str())) return kFALSE ;
445
446 return kTRUE ;
447}
448
449
450////////////////////////////////////////////////////////////////////////////////
451/// Determine if message from given object at given level on given topic is logged
452
454{
455 if (!active) return kFALSE ;
456 if (level<minLevel) return kFALSE ;
457 if (!(topic&top)) return kFALSE ;
458
459 if (universal) return kTRUE ;
460
461 if (objectName.size()>0 && objectName != obj->GetName()) return kFALSE ;
462 if (className.size()>0 && className != obj->IsA()->GetName()) return kFALSE ;
463 if (baseClassName.size()>0 && !obj->IsA()->InheritsFrom(baseClassName.c_str())) return kFALSE ;
464
465 return kTRUE ;
466}
467
468
469
470////////////////////////////////////////////////////////////////////////////////
471/// Log error message associated with RooAbsArg object self at given level and topic. If skipPrefix
472/// is true the standard RooMsgService prefix is not added.
473
474ostream& RooMsgService::log(const RooAbsArg* self, RooFit::MsgLevel level, RooFit::MsgTopic topic, Bool_t skipPrefix)
475{
476 if (level>=ERROR) {
477 _errorCount++ ;
478 }
479
480 // Return C++ ostream associated with given message configuration
481 Int_t as = activeStream(self,topic,level) ;
482
483 if (as==-1) {
484 return *_devnull ;
485 }
486
487 // Flush any previous messages
488 (*_streams[as].os).flush() ;
489
490 // Insert an endl if we switch from progress to another level
491 if (_lastMsgLevel==PROGRESS && level!=PROGRESS) {
492 (*_streams[as].os) << endl ;
493 }
494 _lastMsgLevel=level ;
495
496 if (_streams[as].prefix && !skipPrefix) {
497 if (_showPid) {
498 (*_streams[as].os) << "pid" << gSystem->GetPid() << " " ;
499 }
500 (*_streams[as].os) << "[#" << as << "] " << _levelNames[level] << ":" << _topicNames[topic] << " -- " ;
501 }
502 return (*_streams[as].os) ;
503}
504
505
506
507////////////////////////////////////////////////////////////////////////////////
508/// Log error message associated with TObject object self at given level and topic. If skipPrefix
509/// is true the standard RooMsgService prefix is not added.
510
511ostream& RooMsgService::log(const TObject* self, RooFit::MsgLevel level, RooFit::MsgTopic topic, Bool_t skipPrefix)
512{
513 if (level>=ERROR) {
514 _errorCount++ ;
515 }
516
517 // Return C++ ostream associated with given message configuration
518 Int_t as = activeStream(self,topic,level) ;
519 if (as==-1) {
520 return *_devnull ;
521 }
522
523 // Flush any previous messages
524 (*_streams[as].os).flush() ;
525
526 if (_streams[as].prefix && !skipPrefix) {
527 if (_showPid) {
528 (*_streams[as].os) << "pid" << gSystem->GetPid() << " " ;
529 }
530 (*_streams[as].os) << "[#" << as << "] " << _levelNames[level] << ":" << _topicNames[topic] << " -- " ;
531 }
532 return (*_streams[as].os) ;
533}
534
535
536
537////////////////////////////////////////////////////////////////////////////////
538/// Print configuration of message service. If "v" option is given also
539/// inactive streams are listed
540
541void RooMsgService::Print(Option_t *options) const
542{
543 Bool_t activeOnly = kTRUE ;
544 if (TString(options).Contains("V") || TString(options).Contains("v")) {
545 activeOnly = kFALSE ;
546 }
547
548 cout << (activeOnly?"Active Message streams":"All Message streams") << endl ;
549 for (UInt_t i=0 ; i<_streams.size() ; i++) {
550
551 // Skip passive streams in active only mode
552 if (activeOnly && !_streams[i].active) {
553 continue ;
554 }
555
556
557 map<int,string>::const_iterator is = _levelNames.find(_streams[i].minLevel) ;
558 cout << "[" << i << "] MinLevel = " << is->second ;
559
560 cout << " Topic = " ;
561 if (_streams[i].topic != 0xFFFFF) {
562 map<int,string>::const_iterator iter = _topicNames.begin() ;
563 while(iter!=_topicNames.end()) {
564 if (iter->first & _streams[i].topic) {
565 cout << iter->second << " " ;
566 }
567 ++iter ;
568 }
569 } else {
570 cout << " Any " ;
571 }
572
573
574 if (_streams[i].objectName.size()>0) {
575 cout << " ObjectName = " << _streams[i].objectName ;
576 }
577 if (_streams[i].className.size()>0) {
578 cout << " ClassName = " << _streams[i].className ;
579 }
580 if (_streams[i].baseClassName.size()>0) {
581 cout << " BaseClassName = " << _streams[i].baseClassName ;
582 }
583 if (_streams[i].tagName.size()>0) {
584 cout << " TagLabel = " << _streams[i].tagName ;
585 }
586
587 // Postfix status when printing all
588 if (!activeOnly && !_streams[i].active) {
589 cout << " (NOT ACTIVE)" ;
590 }
591
592 cout << endl ;
593 }
594
595}
#define DEBUG
Definition: Polynomial.cxx:40
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
short Color_t
Definition: RtypesCore.h:81
const Bool_t kTRUE
Definition: RtypesCore.h:89
const char Option_t
Definition: RtypesCore.h:64
#define ClassImp(name)
Definition: Rtypes.h:361
@ kBlack
Definition: Rtypes.h:63
XFontStruct * id
Definition: TGX11.cxx:108
char * Form(const char *fmt,...)
R__EXTERN TSystem * gSystem
Definition: TSystem.h:556
RooAbsArg is the common abstract base class for objects that represent a value (of arbitrary type) an...
Definition: RooAbsArg.h:73
Bool_t getAttribute(const Text_t *name) const
Check if a named attribute is set. By default, all attributes are unset.
Definition: RooAbsArg.cxx:280
RooCmdArg is a named container for two doubles, two integers two object points and three string point...
Definition: RooCmdArg.h:28
Class RooCmdConfig is a configurable parser for RooCmdArg named arguments.
Definition: RooCmdConfig.h:27
RooLinkedList is an collection class for internal use, storing a collection of RooAbsArg pointers in ...
Definition: RooLinkedList.h:35
The RooMsgService class is a singleton class that organizes informational, debugging,...
std::vector< StreamConfig > _streams
void restoreState()
Restore last saved state of message service.
std::ostream * _devnull
void setStreamStatus(Int_t id, Bool_t active)
(De)Activate stream with given unique ID
Bool_t getStreamStatus(Int_t id) const
Get activation status of stream with given unique ID.
static RooMsgService & instance()
Return reference to singleton instance.
static Int_t _debugCount
RooFit::MsgLevel _globMinLevel
Bool_t isActive(const RooAbsArg *self, RooFit::MsgTopic facility, RooFit::MsgLevel level)
Check if logging is active for given object/topic/RooFit::MsgLevel combination.
std::stack< std::vector< StreamConfig > > _streamsSaved
RooMsgService()
Constructor.
Bool_t _silentMode
RooWorkspace * debugWorkspace()
void saveState()
Save current state of message service.
std::map< int, std::string > _topicNames
std::ostream & log(const RooAbsArg *self, RooFit::MsgLevel level, RooFit::MsgTopic facility, Bool_t forceSkipPrefix=kFALSE)
Log error message associated with RooAbsArg object self at given level and topic.
Int_t addStream(RooFit::MsgLevel level, const RooCmdArg &arg1=RooCmdArg(), const RooCmdArg &arg2=RooCmdArg(), const RooCmdArg &arg3=RooCmdArg(), const RooCmdArg &arg4=RooCmdArg(), const RooCmdArg &arg5=RooCmdArg(), const RooCmdArg &arg6=RooCmdArg())
Add a message logging stream for message with given RooFit::MsgLevel or higher (i....
RooWorkspace * _debugWorkspace
static Bool_t anyDebug()
Returns true if any debug level stream is active.
Int_t activeStream(const RooAbsArg *self, RooFit::MsgTopic facility, RooFit::MsgLevel level)
Find appropriate logging stream for message from given object with given topic and message level.
virtual ~RooMsgService()
Destructor.
void deleteStream(Int_t id)
Delete stream with given unique ID code.
std::map< std::string, std::ostream * > _files
std::map< int, std::string > _levelNames
void Print(Option_t *options=0) const
Print configuration of message service.
RooFit::MsgLevel _lastMsgLevel
The RooWorkspace is a persistable container for RooFit projects.
Definition: RooWorkspace.h:43
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
Mother of all ROOT objects.
Definition: TObject.h:37
virtual const char * GetName() const
Returns name of object.
Definition: TObject.cxx:357
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition: TObject.cxx:443
Basic string class.
Definition: TString.h:131
virtual int GetPid()
Get process id.
Definition: TSystem.cxx:705
RooCmdArg Topic(Int_t topic)
TString as(SEXP s)
Definition: RExports.h:71
The namespace RooFit contains mostly switches that change the behaviour of functions of PDFs (or othe...
MsgLevel
Verbosity level for RooMsgService::StreamConfig in RooMsgService.
Definition: RooGlobalFunc.h:65
MsgTopic
Topics for a RooMsgService::StreamConfig in RooMsgService.
Definition: RooGlobalFunc.h:67
@ Minimization
Definition: RooGlobalFunc.h:67
@ Generation
Definition: RooGlobalFunc.h:67
@ NumIntegration
Definition: RooGlobalFunc.h:69
@ Optimization
Definition: RooGlobalFunc.h:68
@ DataHandling
Definition: RooGlobalFunc.h:69
@ HistFactory
Definition: RooGlobalFunc.h:69
@ InputArguments
Definition: RooGlobalFunc.h:68
@ ObjectHandling
Definition: RooGlobalFunc.h:68
@ Integration
Definition: RooGlobalFunc.h:67
@ LinkStateMgmt
Definition: RooGlobalFunc.h:67
static constexpr double pc
Bool_t match(RooFit::MsgLevel level, RooFit::MsgTopic facility, const RooAbsArg *obj)
Determine if message from given object at given level on given topic is logged.
auto * l
Definition: textangle.C:4