Logo ROOT  
Reference Guide
 
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 INFO messages on most topics (among others
31Generation, Plotting, Minimization, and FastEvaluations) and redirects them to stdout.
32Users can create additional streams
33for logging of e.g. DEBUG messages on particular topics or objects and/or redirect streams to
34C++ streams or files.
35
36The singleton instance is accessible through RooMsgService::instance().
37
38### Temporarily change the message level
39There is a helper, RooHelpers::LocalChangeMsgLevel, that overrides the default message levels as
40long as it is alive. To suppress everything below WARNING:
41~~~{.cpp}
42RooHelpers::LocalChangeMessageLevel changeMsgLvl(RooFit::WARNING);
43[ statements that normally generate a lot of output ]
44~~~
45
46#### Temporarily capture a message stream
47RooHelpers::HijackMessageStream allows to fully capture a message stream in a std::stringstream. With this,
48RooFit messages can be evaluated or suppressed.
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[NumericIntegration]="NumericIntegration" ;
105 _topicNames[FastEvaluations] = "FastEvaluations";
106 _topicNames[HistFactory]="HistFactory";
107
108 reset();
109}
110
111
131
132
134
135
136////////////////////////////////////////////////////////////////////////////////
137/// Returns true if any debug level stream is active
138
140{
141 return instance()._debugCount>0 ;
142}
143
144
145
146////////////////////////////////////////////////////////////////////////////////
147
149{
150 if (!_debugWorkspace) {
151 _debugWorkspace = std::make_unique<RooWorkspace>("wdebug") ;
152 }
153 return _debugWorkspace.get();
154}
155
156
157
158////////////////////////////////////////////////////////////////////////////////
159/// Add a message logging stream for message with given RooFit::MsgLevel or higher.
160/// Higher means that messages with higher priority/severity are issued.
161///
162/// This method accepts the following arguments to configure the stream:
163/// <table>
164/// <tr><th> Output Style options <th>
165/// <tr><td> Prefix(bool flag=true) <td> Prefix all messages in this stream with Topic/Originator information
166/// <tr><th> Filtering options <th>
167/// <tr><td> Topic() <td> Restrict stream to messages on given topic
168/// <tr><td> ObjectName(const char*) <td> Restrict stream to messages from object with given name
169/// <tr><td> ClassName(const char*) <td> Restrict stream to messages from objects with given class name
170/// <tr><td> BaseClassName(const char*)<td> Restrict stream to messages from objects with given base class name
171/// <tr><td> LabelName(const chat*) <td> Restrict stream to messages from objects setAttribute(const char*) tag with given name
172/// <tr><th> Output redirection options <th>
173/// <tr><td> OutputFile(const char*) <td> Send output to file with given name. Multiple streams can write to same file.
174/// <tr><td> OutputStream(ostream&) <td> Send output to given C++ stream. Multiple message streams can write to same c++ stream
175/// </table>
176/// The return value is the unique ID of the defined stream.
177
179 const RooCmdArg& arg4, const RooCmdArg& arg5, const RooCmdArg& arg6)
180{
181
182 // Aggregate all arguments in a list
184 l.Add((TObject*)&arg1) ; l.Add((TObject*)&arg2) ;
185 l.Add((TObject*)&arg3) ; l.Add((TObject*)&arg4) ;
186 l.Add((TObject*)&arg5) ; l.Add((TObject*)&arg6) ;
187
188 // Define configuration for this method
189 RooCmdConfig pc("RooMsgService::addReportingStream(" + std::string(GetName()) + ")") ;
190 pc.defineInt("prefix","Prefix",0,true) ;
191 pc.defineInt("color","Color",0,static_cast<Int_t>(kBlack)) ;
192 pc.defineInt("topic","Topic",0,0xFFFFF) ;
193 pc.defineString("objName","ObjectName",0,"") ;
194 pc.defineString("className","ClassName",0,"") ;
195 pc.defineString("baseClassName","BaseClassName",0,"") ;
196 pc.defineString("tagName","LabelName",0,"") ;
197 pc.defineString("outFile","OutputFile",0,"") ;
198 pc.defineObject("outStream","OutputStream",0,nullptr) ;
199 pc.defineMutex("OutputFile","OutputStream") ;
200
201 // Process & check varargs
202 pc.process(l) ;
203 if (!pc.ok(true)) {
204 return -1 ;
205 }
206
207 // Extract values from named arguments
208 RooFit::MsgTopic topic = (RooFit::MsgTopic) pc.getInt("topic") ;
209 const char* objName = pc.getString("objName") ;
210 const char* className = pc.getString("className") ;
211 const char* baseClassName = pc.getString("baseClassName") ;
212 const char* tagName = pc.getString("tagName") ;
213 const char* outFile = pc.getString("outFile") ;
214 bool prefix = pc.getInt("prefix") ;
215 Color_t color = static_cast<Color_t>(pc.getInt("color")) ;
216 auto wrapper = static_cast<RooHelpers::WrapIntoTObject<ostream>*>(pc.getObject("outStream"));
217 ostream* os = nullptr;
218 if (wrapper) {
219 os = wrapper->_payload;
220 delete wrapper;
221 wrapper = nullptr;
222 }
223
224 // Create new stream object
226
227 // Store configuration info
228 newStream.active = true ;
229 newStream.minLevel = level ;
230 newStream.topic = topic ;
231 newStream.objectName = (objName ? objName : "" ) ;
232 newStream.className = (className ? className : "" ) ;
233 newStream.baseClassName = (baseClassName ? baseClassName : "" ) ;
234 newStream.tagName = (tagName ? tagName : "" ) ;
235 newStream.color = color ;
236 newStream.prefix = prefix ;
237 newStream.universal = (newStream.objectName.empty() && newStream.className.empty() && newStream.baseClassName.empty() && newStream.tagName.empty()) ;
238
239 // Update debug stream count
240 if (level==DEBUG) {
241 _debugCount++ ;
242 }
243
244 // Configure output
245 if (os) {
246
247 // To given non-owned stream
248 newStream.os = os ;
249
250 } else if (!string(outFile).empty()) {
251
252 // See if we already opened the file
253 ostream* os2 = _files["outFile"].get();
254
255 if (!os2) {
256
257 // To given file name, create owned stream for it
258 os2 = new ofstream(outFile) ;
259
260 if (!*os2) {
261 std::cout << "RooMsgService::addReportingStream ERROR: cannot open output log file " << outFile << " reverting stream to stdout" << std::endl ;
262 delete os2 ;
263 newStream.os = &std::cout ;
264 } else {
265 newStream.os = os2 ;
266 }
267
268 } else {
269 newStream.os = os2 ;
270 _files["outFile"] = std::unique_ptr<std::ostream>{os2};
271 }
272
273
274 } else {
275
276 // To stdout
277 newStream.os = &std::cout ;
278
279 }
280
281
282 // Add it to list of active streams ;
283 _streams.push_back(newStream) ;
284
285 // Return stream identifier
286 return _streams.size()-1 ;
287}
288
289
290
291////////////////////////////////////////////////////////////////////////////////
292/// Delete stream with given unique ID code
293
295{
296 vector<StreamConfig>::iterator iter = _streams.begin() ;
297 iter += id ;
298
299 // Update debug stream count
300 if (iter->minLevel==DEBUG) {
301 _debugCount-- ;
302 }
303
304 _streams.erase(iter) ;
305}
306
307
308
309////////////////////////////////////////////////////////////////////////////////
310/// (De)Activate stream with given unique ID
311
313{
314 if (id<0 || id>=static_cast<Int_t>(_streams.size())) {
315 std::cout << "RooMsgService::setStreamStatus() ERROR: invalid stream ID " << id << std::endl ;
316 return ;
317 }
318
319 // Update debug stream count
320 if (_streams[id].minLevel==DEBUG) {
321 _debugCount += flag ? 1 : -1 ;
322 }
323
324 _streams[id].active = flag ;
325}
326
327
328
329////////////////////////////////////////////////////////////////////////////////
330/// Get activation status of stream with given unique ID
331
333{
334 if (id<0 || id>= static_cast<Int_t>(_streams.size())) {
335 std::cout << "RooMsgService::getStreamStatus() ERROR: invalid stream ID " << id << std::endl ;
336 return false ;
337 }
338 return _streams[id].active ;
339}
340
341
342
343////////////////////////////////////////////////////////////////////////////////
344/// Return reference to singleton instance
345
351
352
353
354////////////////////////////////////////////////////////////////////////////////
355/// Save current state of message service
356
361
362
363
364////////////////////////////////////////////////////////////////////////////////
365/// Restore last saved state of message service
366
368{
369 _streams = _streamsSaved.top() ;
370 _streamsSaved.pop() ;
371}
372
373
374////////////////////////////////////////////////////////////////////////////////
375/// Determine if message from given object at given level on given topic is logged
376
378{
379 if (!active) return false ;
380 if (level<minLevel) return false ;
381 if (!(topic&top)) return false ;
382
383 if (universal) return true ;
384
385 if (!obj) return false;
386 if (!objectName.empty() && objectName != obj->GetName()) return false ;
387 if (!className.empty() && className != obj->ClassName()) return false ;
388 if (!baseClassName.empty() && !obj->IsA()->InheritsFrom(baseClassName.c_str())) return false ;
389 if (!tagName.empty() && !obj->getAttribute(tagName.c_str())) return false ;
390
391 return true ;
392}
393
394
395////////////////////////////////////////////////////////////////////////////////
396/// Determine if message from given object at given level on given topic is logged
397
399{
400 if (!active) return false ;
401 if (level<minLevel) return false ;
402 if (!(topic&top)) return false ;
403
404 if (universal) return true ;
405
406 if (!obj) return false;
407 if (!objectName.empty() && objectName != obj->GetName()) return false ;
408 if (!className.empty() && className != obj->ClassName()) return false ;
409 if (!baseClassName.empty() && !obj->IsA()->InheritsFrom(baseClassName.c_str())) return false ;
410
411 return true ;
412}
413
414
415
416////////////////////////////////////////////////////////////////////////////////
417/// Log error message associated with RooAbsArg object self at given level and topic. If skipPrefix
418/// is true the standard RooMsgService prefix is not added.
419
421{
422 if (level>=ERROR) {
423 _errorCount++ ;
424 }
425
426 // Return C++ ostream associated with given message configuration
427 Int_t as = activeStream(self,topic,level) ;
428
429 if (as==-1) {
430 return *_devnull ;
431 }
432
433 // Flush any previous messages
434 (*_streams[as].os).flush() ;
435
436 // Insert an std::endl if we switch from progress to another level
437 if (_lastMsgLevel==PROGRESS && level!=PROGRESS) {
438 (*_streams[as].os) << std::endl ;
439 }
440 _lastMsgLevel=level ;
441
442 if (_streams[as].prefix && !skipPrefix) {
443 if (_showPid) {
444 (*_streams[as].os) << "pid" << gSystem->GetPid() << " " ;
445 }
446 (*_streams[as].os) << "[#" << as << "] " << _levelNames[level] << ":" << _topicNames[topic] << " -- " ;
447 }
448 return (*_streams[as].os) ;
449}
450
451
452
453////////////////////////////////////////////////////////////////////////////////
454/// Log error message associated with TObject object self at given level and topic. If skipPrefix
455/// is true the standard RooMsgService prefix is not added.
456
458{
459 if (level>=ERROR) {
460 _errorCount++ ;
461 }
462
463 // Return C++ ostream associated with given message configuration
464 Int_t as = activeStream(self,topic,level) ;
465 if (as==-1) {
466 return *_devnull ;
467 }
468
469 // Flush any previous messages
470 (*_streams[as].os).flush() ;
471
472 if (_streams[as].prefix && !skipPrefix) {
473 if (_showPid) {
474 (*_streams[as].os) << "pid" << gSystem->GetPid() << " " ;
475 }
476 (*_streams[as].os) << "[#" << as << "] " << _levelNames[level] << ":" << _topicNames[topic] << " -- " ;
477 }
478 return (*_streams[as].os) ;
479}
480
481
482
483////////////////////////////////////////////////////////////////////////////////
484/// Print configuration of message service. If "v" option is given also
485/// inactive streams are listed
486
487void RooMsgService::Print(Option_t *options) const
488{
489 bool activeOnly = true ;
490 if (TString(options).Contains("V") || TString(options).Contains("v")) {
491 activeOnly = false ;
492 }
493
494 std::cout << (activeOnly?"Active Message streams":"All Message streams") << std::endl ;
495 for (UInt_t i=0 ; i<_streams.size() ; i++) {
496
497 // Skip passive streams in active only mode
498 if (activeOnly && !_streams[i].active) {
499 continue ;
500 }
501
502
503 map<int,string>::const_iterator is = _levelNames.find(_streams[i].minLevel) ;
504 std::cout << "[" << i << "] MinLevel = " << is->second ;
505
506 std::cout << " Topic = " ;
507 if (_streams[i].topic != 0xFFFFF) {
508 map<int,string>::const_iterator iter = _topicNames.begin() ;
509 while(iter!=_topicNames.end()) {
510 if (iter->first & _streams[i].topic) {
511 std::cout << iter->second << " " ;
512 }
513 ++iter ;
514 }
515 } else {
516 std::cout << " Any " ;
517 }
518
519
520 if (!_streams[i].objectName.empty()) {
521 std::cout << " ObjectName = " << _streams[i].objectName ;
522 }
523 if (!_streams[i].className.empty()) {
524 std::cout << " ClassName = " << _streams[i].className ;
525 }
526 if (!_streams[i].baseClassName.empty()) {
527 std::cout << " BaseClassName = " << _streams[i].baseClassName ;
528 }
529 if (!_streams[i].tagName.empty()) {
530 std::cout << " TagLabel = " << _streams[i].tagName ;
531 }
532
533 // Postfix status when printing all
534 if (!activeOnly && !_streams[i].active) {
535 std::cout << " (NOT ACTIVE)" ;
536 }
537
538 std::cout << std::endl ;
539 }
540
541}
#define DEBUG
int Int_t
Signed integer 4 bytes (int)
Definition RtypesCore.h:60
short Color_t
Color number (short)
Definition RtypesCore.h:100
const char Option_t
Option string (const char)
Definition RtypesCore.h:81
@ 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:582
Common abstract base class for objects that represent a value and a "shape" in RooFit.
Definition RooAbsArg.h:76
TClass * IsA() const override
Definition RooAbsArg.h:656
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:4995
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
Mother of all ROOT objects.
Definition TObject.h:42
virtual const char * GetName() const
Returns name of object.
Definition TObject.cxx:461
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition TObject.cxx:226
virtual TClass * IsA() const
Definition TObject.h:248
Basic string class.
Definition TString.h:137
virtual int GetPid()
Get process id.
Definition TSystem.cxx:721
RooCmdArg Topic(Int_t topic)
The namespace RooFit contains mostly switches that change the behaviour of functions of PDFs (or othe...
Definition CodegenImpl.h:73
MsgLevel
Verbosity level for RooMsgService::StreamConfig in RooMsgService.
MsgTopic
Topics for a RooMsgService::StreamConfig in RooMsgService.
@ NumericIntegration
@ FastEvaluations
@ 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