TkN 2.7.1
Toolkit for Nuclei
Loading...
Searching...
No Matches
tkmeasure.h
1/********************************************************************************
2 * Copyright (c) : Université de Lyon 1, CNRS/IN2P3, UMR5822, *
3 * IP2I, F-69622 Villeurbanne Cedex, France *
4 * Normandie Université, ENSICAEN, UNICAEN, CNRS/IN2P3, *
5 * LPC Caen, F-14000 Caen, France *
6 * Contibutor(s) : *
7 * Jérémie Dudouet jeremie.dudouet@cnrs.fr [2020] *
8 * Diego Gruyer diego.gruyer@cnrs.fr [2020] *
9 * *
10 * Licensed under the MIT License <http://opensource.org/licenses/MIT>. *
11 * SPDX-License-Identifier: MIT *
12 ********************************************************************************/
13
14#ifndef tkmeasure_H
15#define tkmeasure_H
16
17#include <cmath>
18#include <iomanip>
19
20#include "tkn_config.h"
21#include "tklog.h"
22#include "tkproperty.h"
23#include "tkunit.h"
24
25#ifdef HAS_ROOT
26#include "TClass.h"
27#endif
28
29using namespace std;
30
31namespace tkn {
32
33typedef std::map<tkstring, pair<tkstring, tkstring>> properties; // map properties, value, unit
34
56class tkmeasure : public tkproperty {
57protected:
58 tkunit fValue{}; // the value of the measure
59 tkunit fError{}; // the error on this measure
60 tkunit fErrorLow{}; // if define, assym low error value
61 tkunit fErrorHigh{}; // if define, assym high error value
62
63 tkstring ftype = ""; // type of measured data
64
65 bool fAsymError = false;
66
67 tkstring finfo_tag{}; // LT(<), GT(>), LE(<=), GE(>=), AP(~), CA (calculated), SY (from systematics), ? (uncertain, see comments), STABLE
68
69public:
70 tkmeasure() { ; }
71 tkmeasure(double _value, const tkstring &_unit_name, double _err = 0) : tkmeasure(_value, gunits->get_key(_unit_name), _err) {}
72 tkmeasure(double _value, const tkstring &_unit_name, double _errlow, double _errhigh) : tkmeasure(_value, gunits->get_key(_unit_name), _errlow, _errhigh) {}
73 tkmeasure(double _value, const tkunit_manager::units_keys &_unit, double _err = 0);
74 tkmeasure(double _value, const tkunit_manager::units_keys &_unit, double _errlow, double _errhigh);
75 virtual ~tkmeasure() override = default;
76
78 bool is_asym_errors() const { return fAsymError; }
79
81 void set_info_tag(const tkstring &_tag);
83 const tkstring &get_info_tag() const { return finfo_tag; }
84 const tkstring &get_info_tag_const() const { return finfo_tag; }
85
87 bool has_alternative() const { return finfo_tag.contains(";ALT="); }
90 {
91 const tkstring marker = ";ALT=";
92 const auto position = finfo_tag.find(marker);
93 if (position == tkstring::npos) return "";
94 const auto begin = position + marker.size();
95 const auto end = finfo_tag.find(';', begin);
96 return finfo_tag.substr(begin, end == tkstring::npos ? tkstring::npos : end - begin);
97 }
98
100 { return finfo_tag.contains(";ALT_INCOMPATIBLE=1"); }
101
103 void set_type(const tkstring &_type) { ftype = _type; }
105 const tkstring &get_type() const { return ftype; }
106
108 double get_value() const { return fValue.get_value(); }
110 double get_value(const tkunit_manager::units_keys &_unit) const;
112 double get_value(const tkstring &_unit_name) const { return get_value(gunits->get_key(_unit_name)); }
113
115 void set(const double &_val, const tkstring &_unit = "");
117 void set(const double &_val, const tkunit_manager::units_keys &_unit);
118
120 virtual void set_error(const double &_err)
121 {
122 fError.set_value(_err);
123 fErrorLow.clear();
124 fErrorHigh.clear();
125 fAsymError = false;
126 }
127
128 virtual void set_error(const double &_err_low, const double &_err_high)
129 {
130 fErrorLow.set_value(_err_low);
131 fErrorHigh.set_value(_err_high);
132 fError.clear();
133 fAsymError = true;
134 }
135
137 double get_error() const;
139 double get_error(const tkunit_manager::units_keys &_unit) const;
141 double get_error(const tkstring &_unit_name) const { return get_error(gunits->get_key(_unit_name)); }
142
144 double get_error_low() const;
146 double get_error_low(const tkunit_manager::units_keys &_unit) const;
148 double get_error_low(const tkstring &_unit_name) const { return get_error_low(gunits->get_key(_unit_name)); }
149
151 double get_error_high() const;
153 double get_error_high(const tkunit_manager::units_keys &_unit) const;
155 double get_error_high(const tkstring &_unit_name) const { return get_error_high(gunits->get_key(_unit_name)); }
156
158 tkstring get_unit() const { return fValue.get_unit_name(); }
160 tkunit_manager::units_keys get_unit_key() const { return fValue.get_unit_key(); }
161
163 bool set_unit(const tkstring &_unit_name) { return set_unit(gunits->get_key(_unit_name)); }
165 bool set_unit(const tkunit_manager::units_keys &_unit);
166
168 friend std::ostream &operator<<(std::ostream &os, const tkmeasure *_measure)
169 {
170
171 int save_precision = os.precision();
172 os << left << _measure->get_type();
173
174 // check energy offset
175 tkstring offset = "";
176 if (_measure->get_info_tag_const().contains(";OFF=")) {
177 int idx = _measure->get_info_tag_const().index(";OFF=");
178 offset = _measure->get_info_tag_const().substr(idx + 5, 1) + "+";
179 }
180
181 if (_measure->is_info(kLimit)) {
182 if (_measure->get_info_tag_const().contains(";ERR=LT"))
183 os << " < ";
184 else if (_measure->get_info_tag_const().contains(";ERR=LE"))
185 os << " <= ";
186 else if (_measure->get_info_tag_const().contains(";ERR=GT"))
187 os << " > ";
188 else if (_measure->get_info_tag_const().contains(";ERR=GE"))
189 os << " >= ";
190 } else if (_measure->is_info(kAbout))
191 os << " ~ ";
192 else
193 os << " = ";
194
195 if (!_measure->get_info_tag_const().empty() && _measure->get_info_tag_const().contains("STABLE")) {
196 os << left << std::setw(7) << "STABLE" << std::setw(9) << "";
197 } else {
198 if (_measure->is_asym_errors() && _measure->get_error_low() > 0 && _measure->get_error_high() > 0) {
199 int exp_error_low = _measure->get_exp_error_precision(_measure->get_error_low());
200 int exp_error_high = _measure->get_exp_error_precision(_measure->get_error_high());
201 int exp_error = max(max(exp_error_low, exp_error_high), _measure->get_exp_error_precision(_measure->get_value()));
202
203 if (_measure->get_value() != 0 && (_measure->get_value() > 1e5 || _measure->get_value() < 1e-5))
204 os << scientific;
205 else
206 os << fixed;
207
208 os << left << setprecision(exp_error) << offset << std::setw(7) << _measure->get_value();
209 os << " (-" << std::setw(5) << _measure->get_error_low() << " ; +" << std::setw(5) << _measure->get_error_high() << ") " << _measure->get_unit();
210 } else {
211 int exp_error = max(_measure->get_exp_error_precision(_measure->get_value()), _measure->get_exp_error_precision(_measure->get_error()));
212 if (_measure->get_value() != 0 && (abs(_measure->get_value()) > 1e5 || abs(_measure->get_value()) < 1e-5))
213 os << scientific;
214 else
215 os << fixed;
216
217 if (_measure->get_error() > 0.) {
218 os << left << setprecision(exp_error) << offset << std::setw(7) << _measure->get_value();
219 os << " (" << std::setw(5) << _measure->get_error() << ") " << _measure->get_unit();
220 } else if (_measure->get_error() == 0.) {
221 os << left << setprecision(_measure->get_exp_error_precision(_measure->get_value())) << offset << std::setw(7) << _measure->get_value();
222 os << _measure->get_unit();
223 } else {
224 os << left << setprecision(_measure->get_exp_error_precision(_measure->get_value())) << offset << std::setw(7) << _measure->get_value();
225 if (_measure->get_value() == 0.)
226 os << " " << std::setw(5) << " " << " " << _measure->get_unit();
227 else
228 os << fixed << left << setprecision(exp_error) << " (" << std::setw(5) << " ? " << ") " << _measure->get_unit();
229 }
230 }
231 }
232
233 if (!_measure->is_info(kKnown) || _measure->is_converted()) {
234 os << " [" << _measure->get_info_str(false) << "]";
235 }
236
237 os.precision(save_precision);
238
239 return os;
240 }
241
243 void print(bool with_return = true)
244 {
245 cout << (this);
246 if (with_return) cout << endl;
247 }
248
249 tkmeasure operator+(const tkmeasure &_measure) const
250 {
251 tkmeasure result = *this;
252 tkmeasure measure_to_add = _measure;
253 if (this->get_unit() != measure_to_add.get_unit()) {
254 if (!measure_to_add.set_unit(get_unit())) {
255 glog << warning_o << "trying to add two different types of units... ignored" << do_endl;
256 return result;
257 }
258 }
259 result.set(this->get_value() + measure_to_add.get_value());
260 double low_e1, high_e1, low_e2, high_e2;
261 if (is_asym_errors()) {
262 low_e1 = get_error_low();
263 high_e1 = get_error_high();
264 } else {
265 low_e1 = get_error();
266 high_e1 = get_error();
267 }
268 if (measure_to_add.is_asym_errors()) {
269 low_e2 = measure_to_add.get_error_low();
270 high_e2 = measure_to_add.get_error_high();
271 } else {
272 low_e2 = measure_to_add.get_error();
273 high_e2 = measure_to_add.get_error();
274 }
275 if (low_e1 < 0. || high_e1 < 0. || low_e2 < 0. || high_e2 < 0.) {
276 // Unknown uncertainty is not a numeric standard deviation.
277 result.set_error(-1.);
278 } else if (is_asym_errors() || measure_to_add.is_asym_errors()) {
279 result.set_error(sqrt(low_e1 * low_e1 + low_e2 * low_e2), sqrt(high_e1 * high_e1 + high_e2 * high_e2));
280 } else
281 result.set_error(sqrt(low_e1 * low_e1 + low_e2 * low_e2));
282
283 if (get_info_const() != kKnown || measure_to_add.get_info() != kKnown) {
284 if (get_info_const() == kKnown && measure_to_add.get_info() != kKnown)
285 result.set_info(measure_to_add.get_info());
286 else if (get_info_const() != kKnown && measure_to_add.get_info() == kKnown)
287 result.set_info(get_info_const());
288 if (get_info_const() != kKnown && measure_to_add.get_info() != kKnown) result.set_info(kUncertain);
289
290 result.set_info_tag(get_info_tag_const() + measure_to_add.get_info_tag());
291 if (measure_to_add.is_converted()) result.set_converted();
292 }
293 return result;
294 }
295 tkmeasure operator*(double _multiplier) const
296 {
297 tkmeasure result = *this;
298 result.set(get_value() * _multiplier);
299 double low_e1, high_e1;
300 const double scale = std::abs(_multiplier);
301 if (is_asym_errors()) {
302 if (_multiplier < 0) {
303 low_e1 = get_error_high() * scale;
304 high_e1 = get_error_low() * scale;
305 } else {
306 low_e1 = get_error_low() * scale;
307 high_e1 = get_error_high() * scale;
308 }
309 } else {
310 low_e1 = get_error() * scale;
311 high_e1 = get_error() * scale;
312 }
313 if (is_asym_errors())
314 result.set_error(low_e1, high_e1);
315 else
316 result.set_error(low_e1);
317
318 if (_multiplier < 0) {
319 const tkstring tag = result.get_info_tag();
320 if (tag.contains(";ERR=LT"))
321 result.set_info_tag(tag.copy().replace_all(";ERR=LT", ";ERR=GT"));
322 else if (tag.contains(";ERR=LE"))
323 result.set_info_tag(tag.copy().replace_all(";ERR=LE", ";ERR=GE"));
324 else if (tag.contains(";ERR=GT"))
325 result.set_info_tag(tag.copy().replace_all(";ERR=GT", ";ERR=LT"));
326 else if (tag.contains(";ERR=GE"))
327 result.set_info_tag(tag.copy().replace_all(";ERR=GE", ";ERR=LE"));
328 }
329 return result;
330 }
331 friend tkmeasure operator*(double _multiplier, const tkmeasure &obj) { return obj * _multiplier; }
333 {
334 tkmeasure result = *this * -1.;
335 return result;
336 }
337 tkmeasure operator-(const tkmeasure &_measure) const
338 {
339 tkmeasure measure_to_add = -_measure;
340 tkmeasure result = *this + measure_to_add;
341 return result;
342 }
343
345 int get_exp_error_precision(const double &_err) const
346 {
347 double precision_float_error = tkstring::get_precision(tkstring::Form("%g", _err));
348 if (_err < 0.) precision_float_error = tkstring::get_precision(tkstring::Form("%g", get_value()));
349 int precision_int_err = (int)precision_float_error;
350 if (precision_float_error < 1) precision_int_err = (int)(-(1. / precision_float_error + 0.5));
351
352 int exp_error = (int)std::floor(std::log10(std::fabs(precision_int_err)));
353 if (precision_int_err >= 0) exp_error = 0;
354 return exp_error;
355 }
356
357#ifdef HAS_ROOT
359 ClassDefOverride(tkmeasure, 0);
360#endif
361};
362} // namespace tkn
363
364#endif
Stores a physical measurement with its value, unit, and uncertainty.
Definition tkmeasure.h:56
tkmeasure operator-() const
Definition tkmeasure.h:332
void print(bool with_return=true)
print the measured properties
Definition tkmeasure.h:243
const tkstring & get_type() const
returns the measured data type (energy, lifetime...)
Definition tkmeasure.h:105
double get_value(const tkstring &_unit_name) const
returns the measure value in the required string unit
Definition tkmeasure.h:112
double get_error() const
returns the error on the measured value
double get_error_high() const
returns the high assymetric error on the measured value
friend std::ostream & operator<<(std::ostream &os, const tkmeasure *_measure)
redefinition of the << operator to take precision into account
Definition tkmeasure.h:168
const tkstring & get_info_tag() const
returns the info tag (calculation, systematic, approx value...)
Definition tkmeasure.h:83
tkstring get_unit() const
returns the unit name
Definition tkmeasure.h:158
void set_type(const tkstring &_type)
set the measured data type (energy, lifetime...)
Definition tkmeasure.h:103
virtual ~tkmeasure() override=default
tkunit_manager::units_keys get_unit_key() const
returns the unit key
Definition tkmeasure.h:160
double get_error_high(const tkstring &_unit_name) const
returns the high assymetric error on the measured value in the required string unit
Definition tkmeasure.h:155
bool has_alternative() const
Returns true when this scalar is the retained member of alternative solutions.
Definition tkmeasure.h:87
tkmeasure(double _value, const tkstring &_unit_name, double _errlow, double _errhigh)
Definition tkmeasure.h:72
bool is_asym_errors() const
test is the measure uncertainty is asymmetric
Definition tkmeasure.h:78
virtual void set_error(const double &_err)
set the error of this measured data
Definition tkmeasure.h:120
friend tkmeasure operator*(double _multiplier, const tkmeasure &obj)
Definition tkmeasure.h:331
const tkstring & get_info_tag_const() const
Definition tkmeasure.h:84
tkmeasure(double _value, const tkstring &_unit_name, double _err=0)
Definition tkmeasure.h:71
tkmeasure operator+(const tkmeasure &_measure) const
Definition tkmeasure.h:249
double get_value() const
returns the measure value
Definition tkmeasure.h:108
double get_error(const tkstring &_unit_name) const
returns the error on the measured value in the required string unit
Definition tkmeasure.h:141
bool has_incompatible_alternative() const
Returns true when the alternatives have opposite signs or differ by more than 3 sigma.
Definition tkmeasure.h:99
bool set_unit(const tkstring &_unit_name)
set the measured data unit (value and errors)
Definition tkmeasure.h:163
double get_error_low() const
returns the low assymetric error on the measured value
virtual void set_error(const double &_err_low, const double &_err_high)
set the asymmetric error of this value
Definition tkmeasure.h:128
int get_exp_error_precision(const double &_err) const
calculate the needed precision for printouts
Definition tkmeasure.h:345
void set(const double &_val, const tkstring &_unit="")
set the measured value and unit. No given units keeps the current one
Definition tkmeasure.cpp:83
tkmeasure operator*(double _multiplier) const
Definition tkmeasure.h:295
double get_error_low(const tkstring &_unit_name) const
returns the low assymetric error on the measured value in the required string unit
Definition tkmeasure.h:148
tkmeasure operator-(const tkmeasure &_measure) const
Definition tkmeasure.h:337
void set_info_tag(const tkstring &_tag)
define the info tag (calculation, systematic, approx value...)
Definition tkmeasure.cpp:49
tkstring get_alternative() const
Returns the source representation of the alternative solution, or an empty string.
Definition tkmeasure.h:89
bool is_converted() const
to know if the value has been converted
Definition tkproperty.h:52
void set_info(tkproperty::data_info _info)
to set some information about this data
Definition tkproperty.h:55
void set_converted(bool _val=true)
to define the value as a converted one
Definition tkproperty.h:49
data_info get_info_const() const
Definition tkproperty.h:59
tkstring get_info_str(bool _showknown=true) const
to print in string the data_info
data_info get_info()
to get information about this data
Definition tkproperty.h:58
bool is_info(data_info _info) const
to get some information about this data
Definition tkproperty.h:65
std::string with usefull tricks from TString (ROOT) and KVString (KaliVeda) and more....
Definition tkstring.h:33
tkstring copy() const
Returns a copy of this string.
Definition tkstring.cpp:377
static tkstring Form(const char *_format,...)
Definition tkstring.cpp:368
tkstring substr(size_type __pos=0, size_type __n=npos) const
Inlines.
Definition tkstring.h:160
size_t index(const char *_s, size_t _pos=0, ECaseCompare _cmp=kExact) const
Returns the index of the substring _s.
Definition tkstring.cpp:237
bool contains(const char *_pat, ECaseCompare _cmp=kExact) const
Definition tkstring.h:184
static double get_precision(tkstring _st)
Extract the precision for a given ENSDF data.
Definition tkstring.cpp:642
tkstring & replace_all(const tkstring &_s1, const tkstring &_s2)
Definition tkstring.h:196
units_keys
units identifiers
Definition tkunit.h:48
A measured value associated to its unit.
Definition tkunit.h:144
Definition tklog.cpp:16
tklog & warning_o(tklog &log)
Definition tklog.h:325
std::map< tkstring, pair< tkstring, tkstring > > properties
Definition tkmeasure.h:33
tklog & do_endl(tklog &log)
Definition tklog.h:212