ComPWA
Common Partial-Wave-Analysis Framework
FitParameter.cpp
Go to the documentation of this file.
1 // Copyright (c) 2017 The ComPWA Team.
2 // This file is part of the ComPWA framework, check
3 // https://github.com/ComPWA/ComPWA/license.txt for details.
4 
5 #include <iomanip>
6 
7 #include "Core/Utils.hpp"
8 
9 #include "FitParameter.hpp"
10 
11 namespace ComPWA {
12 namespace FunctionTree {
13 
14 FitParameter::FitParameter(std::string inName)
15  : Parameter(inName, ParType::DOUBLE), HasBounds(false), IsFixed(true),
16  Value(0), Bounds(std::pair<double, double>(0, 0)),
17  ErrType(ErrorType::NOTDEF), Error(std::pair<double, double>(0, 0)) {}
18 
19 FitParameter::FitParameter(const boost::property_tree::ptree &pt)
20  : Parameter("", ParType::DOUBLE), HasBounds(false), IsFixed(true), Value(0),
21  Bounds(std::pair<double, double>(0, 0)), ErrType(ErrorType::NOTDEF),
22  Error(std::pair<double, double>(0, 0)) {
23  load(pt);
24 }
25 
26 FitParameter::FitParameter(std::string inName, const double value)
27  : Parameter(inName, ParType::DOUBLE), HasBounds(false), IsFixed(true),
28  Value(value), Bounds(std::pair<double, double>(0, 0)),
29  ErrType(ErrorType::NOTDEF), Error(std::pair<double, double>(0, 0)) {}
30 
31 FitParameter::FitParameter(std::string inName, const double value,
32  const double error)
33  : Parameter(inName, ParType::DOUBLE), HasBounds(false), IsFixed(true),
34  Value(value), Bounds(std::pair<double, double>(0, 0)),
35  ErrType(ErrorType::SYM), Error(std::pair<double, double>(error, error)) {}
36 
37 FitParameter::FitParameter(std::string inName, const double value,
38  const double min, const double max)
39  : Parameter(inName, ParType::DOUBLE), HasBounds(false), IsFixed(false),
40  Value(value), Bounds(std::pair<double, double>(0, 0)),
41  ErrType(ErrorType::NOTDEF), Error(std::pair<double, double>(0, 0)) {
42  setBounds(min, max);
43 }
44 
45 FitParameter::FitParameter(std::string inName, const double value,
46  const double min, const double max,
47  const double error)
48  : Parameter(inName, ParType::DOUBLE), HasBounds(false), IsFixed(false),
49  Value(value), Bounds(std::pair<double, double>(0, 0)),
50  ErrType(ErrorType::NOTDEF), Error(std::pair<double, double>(0, 0)) {
51  setError(error);
52  setBounds(min, max);
53 }
54 
56  : Parameter(par.Name, ParType::DOUBLE), Value(par.Value) {
57 
58  if (par.HasBounds)
59  setBounds(par.Bounds);
60  setError(par.Error);
61  HasBounds = par.HasBounds;
62  IsFixed = par.IsFixed;
63 };
64 
65 void FitParameter::updateParameter(std::shared_ptr<FitParameter> newPar) {
66 
67  // Copy bounds
68  if (newPar->hasBounds()) {
69  HasBounds = true;
70  setBounds(newPar->bounds());
71  } else
72  HasBounds = false;
73 
74  bool isFix = newPar->isFixed();
75  fixParameter(0); // we ignore here if parameter is fixed
76 
77  // Copy value
78  setValue(newPar->value());
79 
80  // Copy uncertainty
81  if (newPar->errorType() == ErrorType::SYM)
82  setError(newPar->error().first);
83  else if (newPar->errorType() == ErrorType::ASYM)
84  setError(newPar->error());
85  else
87 
88  // Copy fix parameter
89  fixParameter(isFix);
90  return;
91 }
92 
93 void FitParameter::setValue(const double inVal) {
94  if (IsFixed)
95  throw ParameterFixed("FunctionTree::FitParameter::setValue() | Parameter " +
96  name() + " is fixed!");
97  // Call notify only if value has changed! Otherwise tree is
98  // recalculated also in case where current parameter is not changed
99  if (Value == inVal)
100  return;
101 
102  if (HasBounds && (inVal < bounds().first || inVal > bounds().second))
103  throw ParameterOutOfBound(
104  "FitParameter::setValue() | Parameter " + name() +
105  " not within bounds: val=" + std::to_string(inVal) + " [" +
106  std::to_string(bounds().first) + ";" + std::to_string(bounds().second) +
107  "]");
108 
109  Value = inVal;
110  notify();
111 }
112 
113 std::pair<double, double> FitParameter::bounds() const { return Bounds; }
114 
115 void FitParameter::setBounds(const double min, const double max) {
116  if (!check_bounds(std::pair<double, double>(min, max)))
117  throw BadParameter("FitParameter::setBounds() | Bounds not valid: [" +
118  std::to_string(min) + ", " + std::to_string(max) + "]");
119  Bounds.first = min;
120  Bounds.second = max;
121  HasBounds = true;
122 }
123 
124 void FitParameter::setBounds(const std::pair<double, double> r) {
125  if (!check_bounds(r))
126  throw BadParameter("FitParameter::setBounds() | Bounds not valid: [" +
127  std::to_string(r.first) + ", " +
128  std::to_string(r.second) + "]");
129  Bounds = r;
130  HasBounds = true;
131 }
132 
134  if (ErrType != ErrorType::NOTDEF)
135  return true;
136  return false;
137 }
138 
139 std::pair<double, double> FitParameter::error() const {
140  if (!hasError())
141  throw std::runtime_error("FitParameter::error() | "
142  "Parameter " +
143  Name + " has no errors defined!");
144  return Error;
145 }
146 
147 void FitParameter::setError(double errLow, double errHigh) {
148  Error.first = errLow;
149  Error.second = errHigh;
150  if (Error.first == 0.0 && Error.second == 0.0)
152  else
154 }
155 
156 void FitParameter::setError(std::pair<double, double> err) {
157  Error = err;
158  if (Error.first == 0.0 && Error.second == 0.0)
160  else
162 }
163 
164 void FitParameter::setError(double err) {
165  Error.first = err;
166  Error.second = err;
167  if (Error.first == 0.0 && Error.second == 0.0)
169  else
171 }
172 
173 bool FitParameter::operator==(const FitParameter otherPar) const {
174  if (this->type() != otherPar.type())
175  return false;
176  if (this->name() != otherPar.name())
177  return false;
178  if (this->value() != otherPar.value())
179  return false;
180 
181  // We assume that if name and value are the same both parameters match. In
182  // case that other properties of the parameterts differ we throw an
183  // exception since we assume that this is a user mistake.
184  if (HasBounds != otherPar.HasBounds || this->bounds() != otherPar.bounds())
185  throw std::runtime_error("FitParameter::operator==() | Parameters "
186  "match by name (" +
187  name() + ") and value (" +
188  std::to_string(value()) +
189  ") but differs in "
190  "parameter bounds. We assume that there is a "
191  "mistake. Check your input files!");
192 
193  if (IsFixed != otherPar.IsFixed)
194  throw std::runtime_error(
195  "FitParameter::operator==() | Parameters "
196  "match by name (" +
197  name() + ") and value (" + std::to_string(value()) +
198  ") but one is fixed the other not. "
199  "We assume that there is a mistake. Check your input files!");
200 
201  if (ErrType != otherPar.ErrType || Error != otherPar.Error)
202  throw std::runtime_error("FitParameter::operator==() | Parameters "
203  "match by name (" +
204  name() + ") and value (" +
205  std::to_string(value()) +
206  ") but differs in "
207  "parameter error. We assume that there is a "
208  "mistake. Check your input files!");
209 
210  return true;
211 }
212 
213 bool FitParameter::check_bounds(const std::pair<double, double> bounds) const {
214  if ((bounds.second > bounds.first) && (bounds.second >= Value) &&
215  (bounds.first <= Value))
216  return true;
217  return false;
218 }
219 
220 std::string FitParameter::to_str() const {
221  std::stringstream oss;
222  oss << std::setw(20) << Name;
223  oss << "\t Value = " << std::left << Value;
224  if (ErrType == ErrorType::SYM) {
225  oss << " (+-" << Error.first << ")";
226  } else if (ErrType == ErrorType::ASYM) {
227  oss << " (+" << Error.second << " -" << Error.first << ")";
228  }
229 
230  if (HasBounds)
231  oss << " [" << Bounds.first << " ; " << Bounds.second << "]";
232  if (IsFixed)
233  oss << " fixed ";
234  return oss.str();
235 }
236 
237 std::string FitParameter::val_to_str() const {
238  std::stringstream ovs;
239  ovs << Value;
240  return ovs.str();
241 }
242 
243 void FitParameter::load(const boost::property_tree::ptree &pt) {
244 
245  // Class attribute is not required. But if it is specified we expect 'Double'
246  // here.
247  auto c = pt.get_optional<std::string>("<xmlattr>.Class");
248  if (c && c.get() != "Double")
249  throw BadConfig("CoherentIntensity::Factory() | Property tree seems to "
250  "not containt a configuration for an CoherentIntensity!");
251 
252  // Require that name and value are provided
253  Name = pt.get<std::string>("<xmlattr>.Name");
254  Value = pt.get<double>("Value");
255 
256  // Optional settings
257  if (pt.get_optional<double>("Error")) {
258  this->setError(pt.get<double>("Error"));
259  }
260  if (pt.get_optional<double>("ErrorLow")) {
261  if (pt.get_optional<double>("ErrorHigh"))
262  this->setError(std::pair<double, double>(pt.get<double>("ErrorLow"),
263  pt.get<double>("ErrorHigh")));
264  else
265  throw std::runtime_error("FitParameterFactory() | Parameter asymmetic "
266  "error not properly set!");
267  } else if (pt.get_optional<double>("ErrorHigh")) {
268  throw std::runtime_error("FitParameterFactory() | Parameter asymmetic "
269  "error not properly set!");
270  } else { // Do not set a asymmetric errors
271  }
272 
273  auto fix = pt.get_optional<bool>("Fix");
274  if (fix)
275  this->fixParameter(fix.get());
276  else
277  this->fixParameter(true);
278 
279  auto min = pt.get_optional<double>("Min");
280  auto max = pt.get_optional<double>("Max");
281  if (min && max) {
282  this->setBounds(min.get(), max.get());
283  } else if (min || max) { // Bounds not completely specified
284  throw std::runtime_error(
285  "FitParameterFactory() | Parameter bounds not properly set!");
286  } else { // No bounds specified
287  }
288 }
289 
290 boost::property_tree::ptree FitParameter::save() const {
291  boost::property_tree::ptree pt;
292 
293  // Require that name and value are provided
294  pt.put("<xmlattr>.Class", "Double");
295  pt.put("<xmlattr>.Name", name());
296  pt.put("Value", value());
297  pt.put("Fix", isFixed());
298  if (hasBounds()) {
299  pt.put("Min", bounds().first);
300  pt.put("Max", bounds().second);
301  }
302  if (ErrType == ErrorType::SYM) {
303  pt.put("Error", error().first);
304  } else if (ErrType == ErrorType::ASYM) {
305  pt.put("ErrorLow", error().first);
306  pt.put("ErrorHigh", error().second);
307  }
308  return pt;
309 }
310 
311 } // namespace FunctionTree
312 } // namespace ComPWA
virtual void setValue(const double inVal)
Setter for value of parameter.
Parameter not existing.
Definition: Exceptions.hpp:62
std::pair< T, T > Error
virtual std::pair< double, double > error() const
Parameter error.
boost::property_tree::ptree save() const
Save parameter to a ptree.
Implementations of Parameter for various data types.
bool operator==(const FitParameter otherPar) const
Base class for internal parameter.
Definition: Parameter.hpp:79
virtual void SetErrorType(ErrorType t)
virtual void updateParameter(std::shared_ptr< FitParameter > newPar)
Update member variables from other FitParameter.
std::pair< double, double > Bounds
Parameter bounds.
virtual std::pair< double, double > bounds() const
Bounds of parameter.
virtual std::string name() const
Getter for name of object.
Definition: Parameter.hpp:88
bool HasBounds
Are valid bounds defined for this parameter?
void load(const boost::property_tree::ptree &pt)
Load parameters from a ptree.
std::string Name
Name of parameter.
Definition: Parameter.hpp:145
virtual std::string val_to_str() const
String with detailed information about the parameter.
Parameter out of bound.
Definition: Exceptions.hpp:149
bool IsFixed
Do you want to keep parameter fixed?
ErrorType ErrType
No error / symmetric error / asymmetric error.
Config is not complete.
Definition: Exceptions.hpp:50
FitParameter(std::string inName="")
Standard constructor with no information provided.
virtual void fixParameter(const bool fixed)
virtual double value() const
Getter for value of parameter.
virtual ParType type() const
Getter for type of object.
Definition: Parameter.hpp:94
Parameter cannot be changed.
Definition: Exceptions.hpp:98
virtual void setError(double errLow, double errHigh)
Set parameter error and assume that this parameter has asymmetric errors.
double Value
Parameter value.
virtual std::string to_str() const
String with detailed information about the parameter.
std::pair< T, T > Bounds
virtual void setBounds(const double min, const double max)
Bounds of parameter.
virtual bool hasError() const
Is an error set?
void notify()
Notify all observing TreeNodes that parameter changed.
Definition: Parameter.hpp:117
std::pair< double, double > Error
Lower parameter error.
ParType
Enums for the type of the parameter, should be extended if an new parameter type is added...
Definition: Parameter.hpp:34
bool check_bounds(const std::pair< double, double > bounds) const
Check if min and max are valid bounds.