Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
RooHelpers.h
Go to the documentation of this file.
1 // Author: Stephan Hageboeck, CERN 01/2019
2 
3 /*****************************************************************************
4  * RooFit
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-2019, 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 #ifndef ROOFIT_ROOFITCORE_INC_ROOHELPERS_H_
18 #define ROOFIT_ROOFITCORE_INC_ROOHELPERS_H_
19 
20 #include "RooMsgService.h"
21 #include "RooAbsArg.h"
22 #include "RooAbsReal.h"
23 
24 #include <sstream>
25 
26 namespace RooHelpers {
27 
28 /// Switches the message service to verbose while the instance alive.
29 class LocalChangeMsgLevel {
30  public:
31  /// Change message level (and topics) while this object is alive, reset when it goes out of scope.
32  /// \param[in] lvl The desired message level. Defaults to verbose.
33  /// \param[in] extraTopics Extra topics to be switched on.
34  LocalChangeMsgLevel(RooFit::MsgLevel lvl = RooFit::DEBUG,
35  RooFit::MsgTopic extraTopics = static_cast<RooFit::MsgTopic>(0u)) {
36  auto& msg = RooMsgService::instance();
37  fOldKillBelow = msg.globalKillBelow();
38  msg.setGlobalKillBelow(lvl);
39  fOldConf = msg.getStream(0);
40  msg.getStream(0).minLevel = lvl;
41  msg.getStream(0).addTopic(extraTopics);
42  msg.setStreamStatus(0, true);
43  }
44 
45  ~LocalChangeMsgLevel() {
46  auto& msg = RooMsgService::instance();
47  msg.setGlobalKillBelow(fOldKillBelow);
48  msg.getStream(0) = fOldConf;
49  }
50 
51  private:
52  RooFit::MsgLevel fOldKillBelow;
53  RooMsgService::StreamConfig fOldConf;
54 };
55 
56 
57 /// Hijacks all messages with given level and topic (and optionally object name) while alive.
58 /// Use this like an ostringstream afterwards. Useful for unit tests and debugging.
59 class HijackMessageStream : public std::ostringstream {
60  public:
61  HijackMessageStream(RooFit::MsgLevel level, RooFit::MsgTopic topics, const char* objectName = nullptr);
62 
63  virtual ~HijackMessageStream();
64 
65  private:
66  RooFit::MsgLevel _oldKillBelow;
67  std::vector<RooMsgService::StreamConfig> _oldConf;
68  Int_t _thisStream;
69 };
70 
71 
72 std::vector<std::string> tokenise(const std::string &str, const std::string &delims);
73 
74 
75 
76 class CachingError : public std::exception {
77  public:
78  CachingError(const std::string& newMessage) :
79  std::exception(),
80  _messages()
81  {
82  _messages.push_back(newMessage);
83  }
84 
85  CachingError(CachingError&& previous, const std::string& newMessage) :
86  std::exception(),
87  _messages{std::move(previous._messages)}
88  {
89  _messages.push_back(newMessage);
90  }
91 
92  const char* what() const noexcept override {
93  std::stringstream out;
94  out << "**Caching Error** in\n";
95 
96  std::string indent;
97  for (auto it = _messages.rbegin(); it != _messages.rend(); ++it) {
98  std::string message = *it;
99  auto pos = message.find('\n', 0);
100  while (pos != std::string::npos) {
101  message.insert(pos+1, indent);
102  pos = (message.find('\n', pos+1));
103  }
104 
105  out << indent << message << "\n";
106  indent += " ";
107  }
108 
109  out << std::endl;
110 
111  std::string* ret = new std::string(out.str()); //Make it survive this method
112 
113  return ret->c_str();
114  }
115 
116 
117  private:
118  std::vector<std::string> _messages;
119 };
120 
121 
122 class FormatPdfTree {
123  public:
124  template <class T,
125  typename std::enable_if<std::is_base_of<RooAbsArg, T>::value>::type* = nullptr >
126  FormatPdfTree& operator<<(const T& arg) {
127  _stream << arg.ClassName() << "::" << arg.GetName() << " " << &arg << " ";
128  arg.printArgs(_stream);
129  return *this;
130  }
131 
132  template <class T,
133  typename std::enable_if< ! std::is_base_of<RooAbsArg, T>::value>::type* = nullptr >
134  FormatPdfTree& operator<<(const T& arg) {
135  _stream << arg;
136  return *this;
137  }
138 
139  operator std::string() const {
140  return _stream.str();
141  }
142 
143  std::ostream& stream() {
144  return _stream;
145  }
146 
147  private:
148  std::ostringstream _stream;
149 };
150 
151 
152 /// Check if the parameters have a range, and warn if the range extends below / above the set limits.
153 void checkRangeOfParameters(const RooAbsReal* callingClass, std::initializer_list<const RooAbsReal*> pars,
154  double min = -std::numeric_limits<double>::max(), double max = std::numeric_limits<double>::max(),
155  bool limitsInAllowedRange = false, std::string extraMessage = "");
156 
157 
158 /// Helper class to access a batch-related part of RooAbsReal's interface, which should not leak to the outside world.
159 class BatchInterfaceAccessor {
160  public:
161  static void clearBatchMemory(RooAbsReal& theReal) {
162  theReal.clearBatchMemory();
163  }
164 
165  static void checkBatchComputation(const RooAbsReal& theReal, std::size_t evtNo,
166  const RooArgSet* normSet = nullptr, double relAccuracy = 1.E-13) {
167  theReal.checkBatchComputation(evtNo, normSet, relAccuracy);
168  }
169 };
170 
171 
172 }
173 
174 
175 #endif /* ROOFIT_ROOFITCORE_INC_ROOHELPERS_H_ */