TkN 2.7.1
Toolkit for Nuclei
Loading...
Searching...
No Matches
tkmeasure.cpp
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#include "tkmeasure.h"
15
16#include <algorithm>
17#include <limits>
18
19namespace tkn {
27}
28
29using namespace tkn;
30
31tkmeasure::tkmeasure(double _value, const tkunit_manager::units_keys &_unit, double _err)
32{
33 fValue.set_value(_value, _unit);
34 fError.set_value(_err, _unit);
35 fErrorLow.set_unit(_unit);
36 fErrorHigh.set_unit(_unit);
37}
38
39tkmeasure::tkmeasure(double _value, const tkunit_manager::units_keys &_unit, double _errlow, double _errhigh)
40{
41 fValue.set_value(_value, _unit);
42 fError.set_unit(_unit);
43 fErrorLow.set_value(_errlow, _unit);
44 fErrorHigh.set_value(_errhigh, _unit);
45
46 fAsymError = true;
47}
48
50{
51 finfo_tag = _tag;
52
53 if(_tag.is_empty()) return;
54 if(_tag.contains(";ERR=?")) {
56 finfo_tag.remove_all(";ERR=?");
57 }
58 if(_tag.contains(";ERR=CA")) {
60 finfo_tag.remove_all(";ERR=CA");
61 }
62 if(_tag.contains(";ERR=AP")) {
64 finfo_tag.remove_all(";ERR=AP");
65 }
66 if(_tag.contains(";ERR=SY")) {
68 finfo_tag.remove_all(";ERR=SY");
69 }
70 if(_tag.contains(";VAL=()")) {
72 finfo_tag.remove_all(";VAL=()");
73 }
74 if(_tag.contains(";ERR=LT") || _tag.contains(";ERR=GT") || _tag.contains(";ERR=LE") || _tag.contains(";ERR=GE")) {
76 }
77 if(_tag.contains(";ERR=CONV")) {
79 finfo_tag.remove_all(";ERR=CONV");
80 }
81}
82
83void tkmeasure::set(const double &_val, const tkstring &_unit)
84{
85 if(_unit != "" ) set_unit(_unit);
86 fValue.set_value(_val);
87}
88
89void tkmeasure::set(const double &_val, const tkunit_manager::units_keys &_unit)
90{
91 set_unit(_unit);
92 fValue.set_value(_val,_unit);
93}
94
96{
97 const auto old_unit = fValue.get_unit_key();
98 if (old_unit == _unit) return true;
99
100 const auto old_type = gunits->get_type(old_unit);
101 const auto new_type = gunits->get_type(_unit);
102 const bool cross_type = old_type != gunits->kUndef_type && old_type != new_type;
103
104 if (!cross_type) {
105 if (!fValue.set_unit(_unit)) return false;
106 fError.set_unit(_unit);
107 fErrorLow.set_unit(_unit);
108 fErrorHigh.set_unit(_unit);
109 return true;
110 }
111
112 // Energy/width <-> lifetime conversion is reciprocal, so uncertainty
113 // endpoints must be converted independently. Work on local copies and
114 // commit only after every conversion has succeeded.
115 tkunit converted_value = fValue;
116 if (!converted_value.set_unit(_unit)) return false;
117
118 const double error_low = fAsymError ? fErrorLow.get_value() : fError.get_value();
119 const double error_high = fAsymError ? fErrorHigh.get_value() : fError.get_value();
120 auto reverse_limit = [this, new_type] {
121 if (ftype == "half-life" || ftype == "decay width")
122 ftype = new_type == gunits->kEnergy ? "decay width" : "half-life";
123 const auto tag = get_info_tag();
124 if (tag.contains(";ERR=LT")) set_info_tag(tag.copy().replace_all(";ERR=LT", ";ERR=GT"));
125 else if (tag.contains(";ERR=LE")) set_info_tag(tag.copy().replace_all(";ERR=LE", ";ERR=GE"));
126 else if (tag.contains(";ERR=GT")) set_info_tag(tag.copy().replace_all(";ERR=GT", ";ERR=LT"));
127 else if (tag.contains(";ERR=GE")) set_info_tag(tag.copy().replace_all(";ERR=GE", ";ERR=LE"));
128 };
129
130 if (error_low < 0. || error_high < 0.) {
131 fValue = converted_value;
132 fError.set_value(-1., _unit);
133 fErrorLow.set_value(-1., _unit);
134 fErrorHigh.set_value(-1., _unit);
135 fAsymError = false;
136 reverse_limit();
137 return true;
138 }
139
140 const double value = fValue.get_value();
141 tkunit endpoint_low(value - error_low, old_unit);
142 tkunit endpoint_high(value + error_high, old_unit);
143 if (!endpoint_low.set_unit(_unit) || !endpoint_high.set_unit(_unit)) return false;
144
145 const double converted = converted_value.get_value();
146 const double converted_min = std::min(endpoint_low.get_value(), endpoint_high.get_value());
147 const double converted_max = std::max(endpoint_low.get_value(), endpoint_high.get_value());
148 const double converted_error_low = converted - converted_min;
149 const double converted_error_high = converted_max - converted;
150
151 fValue = converted_value;
152 if (converted_error_low == converted_error_high) {
153 fError.set_value(converted_error_low, _unit);
154 fErrorLow.set_value(-1., _unit);
155 fErrorHigh.set_value(-1., _unit);
156 fAsymError = false;
157 } else {
158 fError.set_value(-1., _unit);
159 fErrorLow.set_value(converted_error_low, _unit);
160 fErrorHigh.set_value(converted_error_high, _unit);
161 fAsymError = true;
162 }
163 reverse_limit();
164 return true;
165}
166
168{
169 if (get_unit_key() == _unit) return get_value();
170 tkmeasure converted = *this;
171 return converted.set_unit(_unit) ? converted.get_value() : std::numeric_limits<double>::quiet_NaN();
172}
173
175{
176 if(fAsymError) {
177 glog << warning_o << "The measure contains assymetric errors, the return value is the largest one" << do_endl;
178 return std::max(fErrorLow.get_value(),fErrorHigh.get_value());
179 }
180 return fError.get_value();
181}
182
184{
185 if (get_unit_key() == _unit) return get_error();
186 tkmeasure converted = *this;
187 return converted.set_unit(_unit) ? converted.get_error() : std::numeric_limits<double>::quiet_NaN();
188}
189
191{
192 if(!fAsymError) {
193 return fError.get_value();
194 }
195 return fErrorLow.get_value();
196}
197
199{
200 if (get_unit_key() == _unit) return get_error_low();
201 tkmeasure converted = *this;
202 return converted.set_unit(_unit) ? converted.get_error_low() : std::numeric_limits<double>::quiet_NaN();
203}
204
206{
207 if(!fAsymError) {
208 return fError.get_value();
209 }
210 return fErrorHigh.get_value();
211}
212
214{
215 if (get_unit_key() == _unit) return get_error_high();
216 tkmeasure converted = *this;
217 return converted.set_unit(_unit) ? converted.get_error_high() : std::numeric_limits<double>::quiet_NaN();
218}
219
220#ifdef HAS_ROOT
221ClassImp(tkmeasure);
222#endif
Stores a physical measurement with its value, unit, and uncertainty.
Definition tkmeasure.h:56
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
const tkstring & get_info_tag() const
returns the info tag (calculation, systematic, approx value...)
Definition tkmeasure.h:83
tkunit_manager::units_keys get_unit_key() const
returns the unit key
Definition tkmeasure.h:160
double get_value() const
returns the measure value
Definition tkmeasure.h:108
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
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
void set_info_tag(const tkstring &_tag)
define the info tag (calculation, systematic, approx value...)
Definition tkmeasure.cpp:49
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
std::string with usefull tricks from TString (ROOT) and KVString (KaliVeda) and more....
Definition tkstring.h:33
bool is_empty() const
Definition tkstring.h:145
bool contains(const char *_pat, ECaseCompare _cmp=kExact) const
Definition tkstring.h:184
units_keys
units identifiers
Definition tkunit.h:48
A measured value associated to its unit.
Definition tkunit.h:144
double get_value() const
get the value in the current unit
Definition tkunit.h:158
void set_value(const double &_val, const tkstring &_unit="")
set the value and unit from string, if _unit not defined, let in the current unit
Definition tkunit.cpp:93
bool set_unit(const tkstring &_unit)
set the unit from a string
Definition tkunit.cpp:109
Definition tklog.cpp:16
tklog & warning_o(tklog &log)
Definition tklog.h:325
tklog & do_endl(tklog &log)
Definition tklog.h:212