Logo ROOT  
Reference Guide
 
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
Loading...
Searching...
No Matches
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
23Singleton class that organizes messages generated in RooFit.
24Each message has a message level RooFit::MsgLevel (DEBUG,INFO,PROGRESS,WARNING,ERROR or FATAL),
25an source object, and a RooFit::MsgTopic.
26RooMsgService allows to filter and redirect messages into streams
27according to message level, topic, (base) class of originating object, name of originating
28object and based on attribute labels attached to individual objects.
29The current default configuration creates streams for all messages at WARNING level
30or higher (e.g. ERROR and FATAL) and for all INFO message on topics Generation,Plotting,
31Integration and Minimization and redirects them to stdout. Users can create additional streams
32for logging of e.g. DEBUG messages on particular topics or objects and/or redirect streams to
33C++ streams or files.
34
35The singleton instance is accessible through RooMsgService::instance().
36
37### Temporarily change the message level
38There is a helper, RooHelpers::LocalChangeMsgLevel, that overrides the default message levels as
39long as it is alive. To suppress everything below WARNING:
40~~~{.cpp}
41RooHelpers::LocalChangeMessageLevel changeMsgLvl(RooFit::WARNING);
42[ statements that normally generate a lot of output ]
43~~~
44
45#### Temporarily capture a message stream
46RooHelpers::HijackMessageStream allows to fully capture a message stream in a std::stringstream. With this,
47RooFit messages can be evaluated or suppressed.
48**/
49
50
51#include "RooMsgService.h"
52
53#include <sys/types.h>
54#include "RooAbsArg.h"
55#include "RooCmdArg.h"
56#include "RooCmdConfig.h"
57#include "RooGlobalFunc.h"
58#include "RooWorkspace.h"
59#include "RooHelpers.h"
60
61#include "TClass.h"
62#include "TSystem.h"
63
64#include <fstream>
65#include <iomanip>
66
67using std::ofstream, std::ostream, std::string, std::vector, std::map;
68using namespace RooFit;
69
70
72
73
74////////////////////////////////////////////////////////////////////////////////
75/// Constructor. Defines names of message levels
76/// and mapping of topic codes to topic names
77/// Install default message streams.
78
80{
81 _devnull = std::make_unique<ofstream>("/dev/null") ;
82
83 _levelNames[DEBUG]="DEBUG" ;
84 _levelNames[INFO]="INFO" ;
85 _levelNames[PROGRESS]="PROGRESS" ;
86 _levelNames[WARNING]="WARNING" ;
87 _levelNames[ERROR]="ERROR" ;
88 _levelNames[FATAL]="FATAL" ;
89
90 _topicNames[Generation]="Generation" ;
91 _topicNames[Minimization]="Minimization" ;
92 _topicNames[Plotting]="Plotting" ;
93 _topicNames[Fitting]="Fitting" ;
94 _topicNames[Integration]="Integration" ;
95 _topicNames[LinkStateMgmt]="LinkStateMgmt" ;
96 _topicNames[Eval]="Eval" ;
97 _topicNames[Caching]="Caching" ;
98 _topicNames[Optimization]="Optimization" ;
99 _topicNames[ObjectHandling]="ObjectHandling" ;
100 _topicNames[InputArguments]="InputArguments" ;
101 _topicNames[Tracing]="Tracing" ;
102 _topicNames[Contents]="Contents" ;
103 _topicNames[DataHandling]="DataHandling" ;
104 _topicNames[NumIntegration]="NumericIntegration" ;
105 _topicNames[FastEvaluations] = "FastEvaluations";
106 _topicNames[HistFactory]="HistFactory";
107
108 reset();
109}
110
111
129
130
132
133
134////////////////////////////////////////////////////////////////////////////////
135/// Returns true if any debug level stream is active
136
138{
139 return instance()._debugCount>0 ;
140}
141
142
143
144////////////////////////////////////////////////////////////////////////////////
145
147{
148 if (!_debugWorkspace) {
149 _debugWorkspace = std::make_unique<RooWorkspace>("wdebug") ;
150 }
151 return _debugWorkspace.get();
152}
153
154
155
156////////////////////////////////////////////////////////////////////////////////
157/// Add a message logging stream for message with given RooFit::MsgLevel or higher.
158/// Higher means that messages with higher priority/severity are issued.
159///
160/// This method accepts the following arguments to configure the stream:
161/// <table>
162/// <tr><th> Output Style options <th>
163/// <tr><td> Prefix(bool flag=true) <td> Prefix all messages in this stream with Topic/Originator information
164/// <tr><th> Filtering options <th>
165/// <tr><td> Topic() <td> Restrict stream to messages on given topic
166/// <tr><td> ObjectName(const char*) <td> Restrict stream to messages from object with given name
167/// <tr><td> ClassName(const char*) <td> Restrict stream to messages from objects with given class name
168/// <tr><td> BaseClassName(const char*)<td> Restrict stream to messages from objects with given base class name
169/// <tr><td> LabelName(const chat*) <td> Restrict stream to messages from objects setAttribute(const char*) tag with given name
170/// <tr><th> Output redirection options <th>
171/// <tr><td> OutputFile(const char*) <td> Send output to file with given name. Multiple streams can write to same file.
172/// <tr><td> OutputStream(ostream&) <td> Send output to given C++ stream. Multiple message streams can write to same c++ stream
173/// </table>
174/// The return value is the unique ID of the defined stream.
175
177 const RooCmdArg& arg4, const RooCmdArg& arg5, const RooCmdArg& arg6)
178{
179
180 // Aggregate all arguments in a list
182 l.Add((TObject*)&arg1) ; l.Add((TObject*)&arg2) ;
183 l.Add((TObject*)&arg3) ; l.Add((TObject*)&arg4) ;
184 l.Add((TObject*)&arg5) ; l.Add((TObject*)&arg6) ;
185
186 // Define configuration for this method
187 RooCmdConfig pc("RooMsgService::addReportingStream(" + std::string(GetName()) + ")") ;
188 pc.defineInt("prefix","Prefix",0,true) ;
189 pc.defineInt("color","Color",0,static_cast<Int_t>(kBlack)) ;
190 pc.defineInt("topic","Topic",0,0xFFFFF) ;
191 pc.defineString("objName","ObjectName",0,"") ;
192 pc.defineString("className","ClassName",0,"") ;
193 pc.defineString("baseClassName","BaseClassName",0,"") ;
194 pc.defineString("tagName","LabelName",0,"") ;
195 pc.defineString("outFile","OutputFile",0,"") ;
196 pc.defineObject("outStream","OutputStream",0,nullptr) ;
197 pc.defineMutex("OutputFile","OutputStream") ;
198
199 // Process & check varargs
200 pc.process(l) ;
201 if (!pc.ok(true)) {
202 return -1 ;
203 }
204
205 // Extract values from named arguments
206 RooFit::MsgTopic topic = (RooFit::MsgTopic) pc.getInt("topic") ;
207 const char* objName = pc.getString("objName") ;
208 const char* className = pc.getString("className") ;
209 const char* baseClassName = pc.getString("baseClassName") ;
210 const char* tagName = pc.getString("tagName") ;
211 const char* outFile = pc.getString("outFile") ;
212 bool prefix = pc.getInt("prefix") ;
213 Color_t color = static_cast<Color_t>(pc.getInt("color")) ;
214 auto wrapper = static_cast<RooHelpers::WrapIntoTObject<ostream>*>(pc.getObject("outStream"));
215 ostream* os = nullptr;
216 if (wrapper) {
217 os = wrapper->_payload;
218 delete wrapper;
219 wrapper = nullptr;
220 }
221
222 // Create new stream object
224
225 // Store configuration info
226 newStream.active = true ;
227 newStream.minLevel = level ;
228 newStream.topic = topic ;
229 newStream.objectName = (objName ? objName : "" ) ;
230 newStream.className = (className ? className : "" ) ;
231 newStream.baseClassName = (baseClassName ? baseClassName : "" ) ;
232 newStream.tagName = (tagName ? tagName : "" ) ;
233 newStream.color = color ;
234 newStream.prefix = prefix ;
235 newStream.universal = (newStream.objectName.empty() && newStream.className.empty() && newStream.baseClassName.empty() && newStream.tagName.empty()) ;
236
237 // Update debug stream count
238 if (level==DEBUG) {
239 _debugCount++ ;
240 }
241
242 // Configure output
243 if (os) {
244
245 // To given non-owned stream
246 newStream.os = os ;
247
248 } else if (!string(outFile).empty()) {
249
250 // See if we already opened the file
251 ostream* os2 = _files["outFile"].get();
252
253 if (!os2) {
254
255 // To given file name, create owned stream for it
256 os2 = new ofstream(outFile) ;
257
258 if (!*os2) {
259 std::cout << "RooMsgService::addReportingStream ERROR: cannot open output log file " << outFile << " reverting stream to stdout" << std::endl ;
260 delete os2 ;
261 newStream.os = &std::cout ;
262 } else {
263 newStream.os = os2 ;
264 }
265
266 } else {
267 newStream.os = os2 ;
268 _files["outFile"] = std::unique_ptr<std::ostream>{os2};
269 }
270
271
272 } else {
273
274 // To stdout
275 newStream.os = &std::cout ;
276
277 }
278
279
280 // Add it to list of active streams ;
281 _streams.push_back(newStream) ;
282
283 // Return stream identifier
284 return _streams.size()-1 ;
285}
286
287
288
289////////////////////////////////////////////////////////////////////////////////
290/// Delete stream with given unique ID code
291
293{
294 vector<StreamConfig>::iterator iter = _streams.begin() ;
295 iter += id ;
296
297 // Update debug stream count
298 if (iter->minLevel==DEBUG) {
299 _debugCount-- ;
300 }
301
302 _streams.erase(iter) ;
303}
304
305
306
307////////////////////////////////////////////////////////////////////////////////
308/// (De)Activate stream with given unique ID
309
311{
312 if (id<0 || id>=static_cast<Int_t>(_streams.size())) {
313 std::cout << "RooMsgService::setStreamStatus() ERROR: invalid stream ID " << id << std::endl ;
314 return ;
315 }
316
317 // Update debug stream count
318 if (_streams[id].minLevel==DEBUG) {
319 _debugCount += flag ? 1 : -1 ;
320 }
321
322 _streams[id].active = flag ;
323}
324
325
326
327////////////////////////////////////////////////////////////////////////////////
328/// Get activation status of stream with given unique ID
329
331{
332 if (id<0 || id>= static_cast<Int_t>(_streams.size())) {
333 std::cout << "RooMsgService::getStreamStatus() ERROR: invalid stream ID " << id << std::endl ;
334 return false ;
335 }
336 return _streams[id].active ;
337}
338
339
340
341////////////////////////////////////////////////////////////////////////////////
342/// Return reference to singleton instance
343
349
350
351
352////////////////////////////////////////////////////////////////////////////////
353/// Save current state of message service
354
359
360
361
362////////////////////////////////////////////////////////////////////////////////
363/// Restore last saved state of message service
364
366{
367 _streams = _streamsSaved.top() ;
368 _streamsSaved.pop() ;
369}
370
371
372////////////////////////////////////////////////////////////////////////////////
373/// Determine if message from given object at given level on given topic is logged
374
376{
377 if (!active) return false ;
378 if (level<minLevel) return false ;
379 if (!(topic&top)) return false ;
380
381 if (universal) return true ;
382
383 if (!obj) return false;
384 if (!objectName.empty() && objectName != obj->GetName()) return false ;
385 if (!className.empty() && className != obj->ClassName()) return false ;
386 if (!baseClassName.empty() && !obj->IsA()->InheritsFrom(baseClassName.c_str())) return false ;
387 if (!tagName.empty() && !obj->getAttribute(tagName.c_str())) return false ;
388
389 return true ;
390}
391
392
393////////////////////////////////////////////////////////////////////////////////
394/// Determine if message from given object at given level on given topic is logged
395
397{
398 if (!active) return false ;
399 if (level<minLevel) return false ;
400 if (!(topic&top)) return false ;
401
402 if (universal) return true ;
403
404 if (!obj) return false;
405 if (!objectName.empty() && objectName != obj->GetName()) return false ;
406 if (!className.empty() && className != obj->ClassName()) return false ;
407 if (!baseClassName.empty() && !obj->IsA()->InheritsFrom(baseClassName.c_str())) return false ;
408
409 return true ;
410}
411
412
413
414////////////////////////////////////////////////////////////////////////////////
415/// Log error message associated with RooAbsArg object self at given level and topic. If skipPrefix
416/// is true the standard RooMsgService prefix is not added.
417
419{
420 if (level>=ERROR) {
421 _errorCount++ ;
422 }
423
424 // Return C++ ostream associated with given message configuration
425 Int_t as = activeStream(self,topic,level) ;
426
427 if (as==-1) {
428 return *_devnull ;
429 }
430
431 // Flush any previous messages
432 (*_streams[as].os).flush() ;
433
434 // Insert an std::endl if we switch from progress to another level
435 if (_lastMsgLevel==PROGRESS && level!=PROGRESS) {
436 (*_streams[as].os) << std::endl ;
437 }
438 _lastMsgLevel=level ;
439
440 if (_streams[as].prefix && !skipPrefix) {
441 if (_showPid) {
442 (*_streams[as].os) << "pid" << gSystem->GetPid() << " " ;
443 }
444 (*_streams[as].os) << "[#" << as << "] " << _levelNames[level] << ":" << _topicNames[topic] << " -- " ;
445 }
446 return (*_streams[as].os) ;
447}
448
449
450
451////////////////////////////////////////////////////////////////////////////////
452/// Log error message associated with TObject object self at given level and topic. If skipPrefix
453/// is true the standard RooMsgService prefix is not added.
454
456{
457 if (level>=ERROR) {
458 _errorCount++ ;
459 }
460
461 // Return C++ ostream associated with given message configuration
462 Int_t as = activeStream(self,topic,level) ;
463 if (as==-1) {
464 return *_devnull ;
465 }
466
467 // Flush any previous messages
468 (*_streams[as].os).flush() ;
469
470 if (_streams[as].prefix && !skipPrefix) {
471 if (_showPid) {
472 (*_streams[as].os) << "pid" << gSystem->GetPid() << " " ;
473 }
474 (*_streams[as].os) << "[#" << as << "] " << _levelNames[level] << ":" << _topicNames[topic] << " -- " ;
475 }
476 return (*_streams[as].os) ;
477}
478
479
480
481////////////////////////////////////////////////////////////////////////////////
482/// Print configuration of message service. If "v" option is given also
483/// inactive streams are listed
484
485void RooMsgService::Print(Option_t *options) const
486{
487 bool activeOnly = true ;
488 if (TString(options).Contains("V") || TString(options).Contains("v")) {
489 activeOnly = false ;
490 }
491
492 std::cout << (activeOnly?"Active Message streams":"All Message streams") << std::endl ;
493 for (UInt_t i=0 ; i<_streams.size() ; i++) {
494
495 // Skip passive streams in active only mode
496 if (activeOnly && !_streams[i].active) {
497 continue ;
498 }
499
500
501 map<int,string>::const_iterator is = _levelNames.find(_streams[i].minLevel) ;
502 std::cout << "[" << i << "] MinLevel = " << is->second ;
503
504 std::cout << " Topic = " ;
505 if (_streams[i].topic != 0xFFFFF) {
506 map<int,string>::const_iterator iter = _topicNames.begin() ;
507 while(iter!=_topicNames.end()) {
508 if (iter->first & _streams[i].topic) {
509 std::cout << iter->second << " " ;
510 }
511 ++iter ;
512 }
513 } else {
514 std::cout << " Any " ;
515 }
516
517
518 if (!_streams[i].objectName.empty()) {
519 std::cout << " ObjectName = " << _streams[i].objectName ;
520 }
521 if (!_streams[i].className.empty()) {
522 std::cout << " ClassName = " << _streams[i].className ;
523 }
524 if (!_streams[i].baseClassName.empty()) {
525 std::cout << " BaseClassName = " << _streams[i].baseClassName ;
526 }
527 if (!_streams[i].tagName.empty()) {
528 std::cout << " TagLabel = " << _streams[i].tagName ;
529 }
530
531 // Postfix status when printing all
532 if (!activeOnly && !_streams[i].active) {
533 std::cout << " (NOT ACTIVE)" ;
534 }
535
536 std::cout << std::endl ;
537 }
538
539}
#define DEBUG
int Int_t
Definition RtypesCore.h:45
short Color_t
Definition RtypesCore.h:85
const char Option_t
Definition RtypesCore.h:66
@ kBlack
Definition Rtypes.h:65
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize id
R__EXTERN TSystem * gSystem
Definition TSystem.h:572
Common abstract base class for objects that represent a value and a "shape" in RooFit.
Definition RooAbsArg.h:77
bool getAttribute(const Text_t *name) const
Check if a named attribute is set. By default, all attributes are unset.
Named container for two doubles, two integers two object points and three string pointers that can be...
Definition RooCmdArg.h:26
Configurable parser for RooCmdArg named arguments.
void defineMutex(const char *head, Args_t &&... tail)
Define arguments where any pair is mutually exclusive.
bool process(const RooCmdArg &arg)
Process given RooCmdArg.
bool ok(bool verbose) const
Return true of parsing was successful.
bool defineObject(const char *name, const char *argName, int setNum, const TObject *obj=nullptr, bool isArray=false)
Define TObject property name 'name' mapped to object in slot 'setNum' in RooCmdArg with name argName ...
const char * getString(const char *name, const char *defaultValue="", bool convEmptyToNull=false) const
Return string property registered with name 'name'.
bool defineString(const char *name, const char *argName, int stringNum, const char *defValue="", bool appendMode=false)
Define double property name 'name' mapped to double in slot 'stringNum' in RooCmdArg with name argNam...
bool defineInt(const char *name, const char *argName, int intNum, int defValue=0)
Define integer property name 'name' mapped to integer in slot 'intNum' in RooCmdArg with name argName...
int getInt(const char *name, int defaultValue=0) const
Return integer property registered with name 'name'.
TObject * getObject(const char *name, TObject *obj=nullptr) const
Return TObject property registered with name 'name'.
Collection class for internal use, storing a collection of RooAbsArg pointers in a doubly linked list...
Singleton class that organizes messages generated in RooFit.
std::vector< StreamConfig > _streams
void restoreState()
Restore last saved state of message service.
std::ostream & log(const RooAbsArg *self, RooFit::MsgLevel level, RooFit::MsgTopic facility, bool forceSkipPrefix=false)
Log error message associated with RooAbsArg object self at given level and topic.
Int_t activeStream(T self, RooFit::MsgTopic topic, RooFit::MsgLevel level)
Find appropriate logging stream for message from given object with given topic and message level.
static RooMsgService & instance()
Return reference to singleton instance.
static Int_t _debugCount
std::unique_ptr< RooWorkspace > _debugWorkspace
static bool anyDebug()
Returns true if any debug level stream is active.
RooFit::MsgLevel _globMinLevel
std::stack< std::vector< StreamConfig > > _streamsSaved
RooMsgService()
Constructor.
RooWorkspace * debugWorkspace()
void Print(Option_t *options=nullptr) const override
Print configuration of message service.
void setStreamStatus(Int_t id, bool active)
(De)Activate stream with given unique ID
void saveState()
Save current state of message service.
std::map< int, std::string > _topicNames
~RooMsgService() override
Int_t addStream(RooFit::MsgLevel level, const RooCmdArg &arg1={}, const RooCmdArg &arg2={}, const RooCmdArg &arg3={}, const RooCmdArg &arg4={}, const RooCmdArg &arg5={}, const RooCmdArg &arg6={})
Add a message logging stream for message with given RooFit::MsgLevel or higher.
std::map< std::string, std::unique_ptr< std::ostream > > _files
bool getStreamStatus(Int_t id) const
Get activation status of stream with given unique ID.
void deleteStream(Int_t id)
Delete stream with given unique ID code.
std::unique_ptr< std::ofstream > _devnull
std::map< int, std::string > _levelNames
RooFit::MsgLevel _lastMsgLevel
Persistable container for RooFit projects.
Bool_t InheritsFrom(const char *cl) const override
Return kTRUE if this class inherits from a class with name "classname".
Definition TClass.cxx:4971
const char * GetName() const override
Returns name of object.
Definition TNamed.h:47
TClass * IsA() const override
Definition TNamed.h:58
Mother of all ROOT objects.
Definition TObject.h:41
virtual const char * GetName() const
Returns name of object.
Definition TObject.cxx:456
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition TObject.cxx:225
virtual TClass * IsA() const
Definition TObject.h:243
Basic string class.
Definition TString.h:139
virtual int GetPid()
Get process id.
Definition TSystem.cxx:707
RooCmdArg Topic(Int_t topic)
The namespace RooFit contains mostly switches that change the behaviour of functions of PDFs (or othe...
Definition CodegenImpl.h:64
MsgLevel
Verbosity level for RooMsgService::StreamConfig in RooMsgService.
MsgTopic
Topics for a RooMsgService::StreamConfig in RooMsgService.
@ FastEvaluations
@ NumIntegration
@ InputArguments
@ ObjectHandling
@ LinkStateMgmt
Wrap an object into a TObject. Sometimes needed to avoid reinterpret_cast or enable RTTI.
Definition RooHelpers.h:57
bool match(RooFit::MsgLevel level, RooFit::MsgTopic facility, const RooAbsArg *obj)
Determine if message from given object at given level on given topic is logged.
TLine l
Definition textangle.C:4