TkN 2.5
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() { return finfo_tag; }
84 const tkstring &get_info_tag_const() const { return finfo_tag; }
85
87 void set_type(const tkstring &_type) { ftype = _type; }
89 const tkstring &get_type() const { return ftype; }
90
92 double get_value() const { return fValue.get_value(); }
94 double get_value(const tkunit_manager::units_keys &_unit);
96 double get_value(const tkstring &_unit_name) { return get_value(gunits->get_key(_unit_name)); }
97
99 void set(const double &_val, const tkstring &_unit = "");
101 void set(const double &_val, const tkunit_manager::units_keys &_unit);
102
104 virtual void set_error(const double &_err)
105 {
106 fError.set_value(_err);
107 fErrorLow.clear();
108 fErrorHigh.clear();
109 fAsymError = false;
110 }
111
112 virtual void set_error(const double &_err_low, const double &_err_high)
113 {
114 fErrorLow.set_value(_err_low);
115 fErrorHigh.set_value(_err_high);
116 fError.clear();
117 fAsymError = true;
118 }
119
121 double get_error() const;
123 double get_error(const tkunit_manager::units_keys &_unit);
125 double get_error(const tkstring &_unit_name) { return get_error(gunits->get_key(_unit_name)); }
126
128 double get_error_low() const;
130 double get_error_low(const tkunit_manager::units_keys &_unit);
132 double get_error_low(const tkstring &_unit_name) { return get_error_low(gunits->get_key(_unit_name)); }
133
135 double get_error_high() const;
137 double get_error_high(const tkunit_manager::units_keys &_unit);
139 double get_error_high(const tkstring &_unit_name) { return get_error_high(gunits->get_key(_unit_name)); }
140
142 tkstring get_unit() const { return fValue.get_unit_name(); }
144 tkunit_manager::units_keys get_unit_key() const { return fValue.get_unit_key(); }
145
147 bool set_unit(const tkstring &_unit_name) { return set_unit(gunits->get_key(_unit_name)); }
149 bool set_unit(const tkunit_manager::units_keys &_unit);
150
152 friend std::ostream &operator<<(std::ostream &os, const tkmeasure *_measure)
153 {
154
155 int save_precision = os.precision();
156 os << left << _measure->get_type();
157
158 // check energy offset
159 tkstring offset = "";
160 if (_measure->get_info_tag_const().contains(";OFF=")) {
161 int idx = _measure->get_info_tag_const().index(";OFF=");
162 offset = _measure->get_info_tag_const().substr(idx + 5, 1) + "+";
163 }
164
165 if (_measure->is_info(kLimit)) {
166 if (_measure->get_info_tag_const().contains(";ERR=LT"))
167 os << " < ";
168 else if (_measure->get_info_tag_const().contains(";ERR=LE"))
169 os << " <= ";
170 else if (_measure->get_info_tag_const().contains(";ERR=GT"))
171 os << " > ";
172 else if (_measure->get_info_tag_const().contains(";ERR=GE"))
173 os << " >= ";
174 } else if (_measure->is_info(kAbout))
175 os << " ~ ";
176 else
177 os << " = ";
178
179 if (!_measure->get_info_tag_const().empty() && _measure->get_info_tag_const().contains("STABLE")) {
180 os << left << std::setw(7) << "STABLE" << std::setw(9) << "";
181 } else {
182 if (_measure->is_asym_errors() && _measure->get_error_low() > 0 && _measure->get_error_high() > 0) {
183 int exp_error_low = _measure->get_exp_error_precision(_measure->get_error_low());
184 int exp_error_high = _measure->get_exp_error_precision(_measure->get_error_high());
185 int exp_error = max(max(exp_error_low, exp_error_high), _measure->get_exp_error_precision(_measure->get_value()));
186
187 if (_measure->get_value() != 0 && (_measure->get_value() > 1e5 || _measure->get_value() < 1e-5))
188 os << scientific;
189 else
190 os << fixed;
191
192 os << left << setprecision(exp_error) << offset << std::setw(7) << _measure->get_value();
193 os << " (-" << std::setw(5) << _measure->get_error_low() << " ; +" << std::setw(5) << _measure->get_error_high() << ") " << _measure->get_unit();
194 } else {
195 int exp_error = max(_measure->get_exp_error_precision(_measure->get_value()), _measure->get_exp_error_precision(_measure->get_error()));
196 if (_measure->get_value() != 0 && (abs(_measure->get_value()) > 1e5 || abs(_measure->get_value()) < 1e-5))
197 os << scientific;
198 else
199 os << fixed;
200
201 if (_measure->get_error() > 0.) {
202 os << left << setprecision(exp_error) << offset << std::setw(7) << _measure->get_value();
203 os << " (" << std::setw(5) << _measure->get_error() << ") " << _measure->get_unit();
204 } else if (_measure->get_error() == 0.) {
205 os << left << setprecision(_measure->get_exp_error_precision(_measure->get_value())) << offset << std::setw(7) << _measure->get_value();
206 os << _measure->get_unit();
207 } else {
208 os << left << setprecision(_measure->get_exp_error_precision(_measure->get_value())) << offset << std::setw(7) << _measure->get_value();
209 if (_measure->get_value() == 0.)
210 os << " " << std::setw(5) << " " << " " << _measure->get_unit();
211 else
212 os << fixed << left << setprecision(exp_error) << " (" << std::setw(5) << " ? " << ") " << _measure->get_unit();
213 }
214 }
215 }
216
217 if (!_measure->is_info(kKnown) || _measure->is_converted()) {
218 os << " [" << _measure->get_info_str(false) << "]";
219 }
220
221 os.precision(save_precision);
222
223 return os;
224 }
225
227 void print(bool with_return = true)
228 {
229 cout << (this);
230 if (with_return) cout << endl;
231 }
232
233 tkmeasure operator+(const tkmeasure &_measure) const
234 {
235 tkmeasure result = *this;
236 tkmeasure measure_to_add = _measure;
237 if (this->get_unit() != measure_to_add.get_unit()) {
238 if (!measure_to_add.set_unit(get_unit())) {
239 glog << warning_o << "trying to add two different types of units... ignored" << do_endl;
240 return result;
241 }
242 }
243 result.set(this->get_value() + measure_to_add.get_value());
244 double low_e1, high_e1, low_e2, high_e2;
245 if (is_asym_errors()) {
246 low_e1 = get_error_low();
247 high_e1 = get_error_high();
248 } else {
249 low_e1 = get_error();
250 high_e1 = get_error();
251 }
252 if (measure_to_add.is_asym_errors()) {
253 low_e2 = measure_to_add.get_error_low();
254 high_e2 = measure_to_add.get_error_high();
255 } else {
256 low_e2 = measure_to_add.get_error();
257 high_e2 = measure_to_add.get_error();
258 }
259 if (is_asym_errors() || measure_to_add.is_asym_errors()) {
260 result.set_error(sqrt(low_e1 * low_e1 + low_e2 * low_e2), sqrt(high_e1 * high_e1 + high_e2 * high_e2));
261 } else
262 result.set_error(sqrt(low_e1 * low_e1 + low_e2 * low_e2));
263
264 if (get_info_const() != kKnown || measure_to_add.get_info() != kKnown) {
265 if (get_info_const() == kKnown && measure_to_add.get_info() != kKnown)
266 result.set_info(measure_to_add.get_info());
267 else if (get_info_const() != kKnown && measure_to_add.get_info() == kKnown)
268 result.set_info(get_info_const());
269 if (get_info_const() != kKnown && measure_to_add.get_info() != kKnown) result.set_info(kUncertain);
270
271 result.set_info_tag(get_info_tag_const() + measure_to_add.get_info_tag());
272 if (measure_to_add.is_converted()) result.set_converted();
273 }
274 return result;
275 }
276 tkmeasure operator*(double _multiplier) const
277 {
278 tkmeasure result = *this;
279 result.set(get_value() * _multiplier);
280 double low_e1, high_e1;
281 if (is_asym_errors()) {
282 if (_multiplier < 0) {
283 low_e1 = get_error_high() * _multiplier;
284 high_e1 = get_error_low() * _multiplier;
285 } else {
286 low_e1 = get_error_low() * _multiplier;
287 high_e1 = get_error_high() * _multiplier;
288 }
289 } else {
290 low_e1 = get_error() * _multiplier;
291 high_e1 = get_error() * _multiplier;
292 }
293 if (is_asym_errors())
294 result.set_error(low_e1, high_e1);
295 else
296 result.set_error(low_e1);
297
298 if (_multiplier < 0) {
299 if (result.get_info_tag().contains("LT")) result.set_info_tag(result.get_info_tag().copy().replace_all("LT", "GT"));
300 if (result.get_info_tag().contains("LE")) result.set_info_tag(result.get_info_tag().copy().replace_all("LE", "GE"));
301 if (result.get_info_tag().contains("GT")) result.set_info_tag(result.get_info_tag().copy().replace_all("GT", "LT"));
302 }
303 return result;
304 }
305 friend tkmeasure operator*(double _multiplier, const tkmeasure &obj) { return obj * _multiplier; }
307 {
308 tkmeasure result = *this * -1.;
309 return result;
310 }
311 tkmeasure operator-(const tkmeasure &_measure) const
312 {
313 tkmeasure measure_to_add = -_measure;
314 tkmeasure result = *this + measure_to_add;
315 return result;
316 }
317
319 int get_exp_error_precision(const double &_err) const
320 {
321 double precision_float_error = tkstring::get_precision(tkstring::Form("%g", _err));
322 if (_err < 0.) precision_float_error = tkstring::get_precision(tkstring::Form("%g", get_value()));
323 int precision_int_err = (int)precision_float_error;
324 if (precision_float_error < 1) precision_int_err = (int)(-(1. / precision_float_error + 0.5));
325
326 int exp_error = (int)std::floor(std::log10(std::fabs(precision_int_err)));
327 if (precision_int_err >= 0) exp_error = 0;
328 return exp_error;
329 }
330
331#ifdef HAS_ROOT
333 ClassDefOverride(tkmeasure, 0);
334#endif
335};
336} // namespace tkn
337
338#endif
Stores a physical measurement with its value, unit, and uncertainty.
Definition tkmeasure.h:56
const tkstring & get_info_tag()
returns the info tag (calculation, systematic, approx value...)
Definition tkmeasure.h:83
tkmeasure operator-() const
Definition tkmeasure.h:306
void print(bool with_return=true)
print the measured properties
Definition tkmeasure.h:227
const tkstring & get_type() const
returns the measured data type (energy, lifetime...)
Definition tkmeasure.h:89
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:152
double get_error_high(const tkstring &_unit_name)
returns the high assymetric error on the measured value in the required string unit
Definition tkmeasure.h:139
tkstring get_unit() const
returns the unit name
Definition tkmeasure.h:142
void set_type(const tkstring &_type)
set the measured data type (energy, lifetime...)
Definition tkmeasure.h:87
virtual ~tkmeasure() override=default
tkunit_manager::units_keys get_unit_key() const
returns the unit key
Definition tkmeasure.h:144
double get_value(const tkstring &_unit_name)
returns the measure value in the required string unit
Definition tkmeasure.h:96
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:104
friend tkmeasure operator*(double _multiplier, const tkmeasure &obj)
Definition tkmeasure.h:305
const tkstring & get_info_tag_const() const
Definition tkmeasure.h:84
double get_error(const tkstring &_unit_name)
returns the error on the measured value in the required string unit
Definition tkmeasure.h:125
tkmeasure(double _value, const tkstring &_unit_name, double _err=0)
Definition tkmeasure.h:71
tkmeasure operator+(const tkmeasure &_measure) const
Definition tkmeasure.h:233
double get_value() const
returns the measure value
Definition tkmeasure.h:92
double get_error_low(const tkstring &_unit_name)
returns the low assymetric error on the measured value in the required string unit
Definition tkmeasure.h:132
bool set_unit(const tkstring &_unit_name)
set the measured data unit (value and errors)
Definition tkmeasure.h:147
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:112
int get_exp_error_precision(const double &_err) const
calculate the needed precision for printouts
Definition tkmeasure.h:319
void set(const double &_val, const tkstring &_unit="")
set the measured value and unit. No given units keeps the current one
tkmeasure operator*(double _multiplier) const
Definition tkmeasure.h:276
tkmeasure operator-(const tkmeasure &_measure) const
Definition tkmeasure.h:311
void set_info_tag(const tkstring &_tag)
define the info tag (calculation, systematic, approx value...)
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:32
tkstring copy() const
Returns a copy of this string.
Definition tkstring.cpp:391
static tkstring Form(const char *_format,...)
Definition tkstring.cpp:366
tkstring substr(size_type __pos=0, size_type __n=npos) const
Inlines.
Definition tkstring.h:157
size_t index(const char *_s, size_t _pos=0, ECaseCompare _cmp=kExact) const
Returns the index of the substring _s.
Definition tkstring.cpp:239
bool contains(const char *_pat, ECaseCompare _cmp=kExact) const
Definition tkstring.h:175
static double get_precision(tkstring _st)
Extract the precision for a given ENSDF data.
Definition tkstring.cpp:670
tkstring & replace_all(const tkstring &_s1, const tkstring &_s2)
Definition tkstring.h:181
units_keys
units identifiers
Definition tkunit.h:46
A measured value associated to its unit.
Definition tkunit.h:120
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