|
YODA - Yet more Objects for Data Analysis 2.0.0
|
Go to the documentation of this file.
42 Estimate( double v, std::map<std::string,std::pair<double,double>>& errors)
43 : _value(v), _error(errors) { }
47 Estimate( const double v, const std::pair<double,double>& e, const std::string& source = "")
48 : _value(v) { setErr(e, source); }
54 _value = toCopy._value;
55 _error = toCopy._error;
62 _value = std::move(toMove._value);
63 _error = std::move(toMove._error);
70 if ( this != &toCopy) {
71 _value = toCopy._value;
72 _error = toCopy._error;
81 if ( this != &toMove) {
82 _value = std::move(toMove._value);
83 _error = std::move(toMove._error);
98 const std::regex re(pat_uncorr);
99 for ( const std::string& src : toAdd. sources()) {
101 else if (std::regex_search(src, match, re)) {
105 const auto [r_dn,r_up] = toAdd. errDownUp(src);
106 const double new_dn = std::sqrt(l_dn*l_dn + r_dn*r_dn);
107 const double new_up = std::sqrt(l_up*l_up + r_up*r_up);
108 setErr({-new_dn,new_up}, src);
113 const auto [r_dn,r_up] = toAdd. errDownUp(src);
114 setErr({l_dn+r_dn, l_up+r_up}, src);
128 const std::regex re(pat_uncorr);
129 for ( const std::string& src : toSubtract. sources()) {
131 else if (std::regex_search(src, match, re)) {
134 const auto [r_dn,r_up] = toSubtract. errDownUp(src);
135 const double new_dn = std::sqrt(l_dn*l_dn + r_dn*r_dn);
136 const double new_up = std::sqrt(l_up*l_up + r_up*r_up);
137 setErr({-new_dn,new_up}, src);;
142 const auto [r_dn,r_up] = toSubtract. errDownUp(src);
143 setErr({l_dn+r_dn, l_up+r_up}, src);
159 void setValue( const double value) noexcept { _value = value; }
165 void setErr( const std::pair<double, double> & err, const std::string& source = "") {
166 const std::string& s = Utils::toUpper(source);
168 throw UserError( "Use empty string for the total uncertainty!");
169 _error[source] = err;
176 void setErr( const double err, const std::string& source = "") {
181 void set( const double val, const std::pair<double, double> & err, const std::string source = "") {
188 void set( const double val, const double err, const std::string& source = "") {
195 _value = std::numeric_limits<double>::quiet_NaN();
201 void scale( const double scalefactor) noexcept {
202 _value *= scalefactor;
203 for ( auto& item : _error) {
204 item.second = { item.second.first * scalefactor, item.second.second * scalefactor };
219 void renameSource( const std::string& old_label, const std::string& new_label) {
221 throw UserError( "Error map has no such key: "+old_label);
223 auto entry = _error.extract(old_label);
224 entry.key() = new_label;
225 _error.insert(std::move(entry));
238 double val() const noexcept { return _value; }
244 std::pair<double,double> errDownUp( const std::string& source = "") const {
245 const size_t count = _error.count(source);
247 throw RangeError( "Error map has no such key: "+source);
248 return _error.at(source);
252 std::pair<double,double> err( const std::string& source = "") const {
257 std::pair<double,double> errNegPos(std::string source = "") const {
258 return _downUp2NegPos( errDownUp(source) );
262 double errNeg( const std::string& source = "") const {
267 double errPos( const std::string& source = "") const {
272 double errDown( const std::string& source = "") const {
277 double errUp( const std::string& source = "") const {
282 double errAvg( const std::string& source = "") const {
287 std::pair<double,double> relErrDownUp( const std::string& source = "") const {
289 dn = _value != 0 ? dn/fabs(_value) : std::numeric_limits<double>::quiet_NaN();
290 up = _value != 0 ? up/fabs(_value) : std::numeric_limits<double>::quiet_NaN();
295 std::pair<double,double> relErr( const std::string& source = "") const {
301 return relErr(source).first;
305 double relErrUp( const std::string& source = "") const {
306 return relErr(source).second;
310 double relErrAvg( const std::string& source = "") const {
316 double valMax( const std::string& source = "") const {
322 double valMin( const std::string& source = "") const {
330 std::pair<double,double> quadSum() const noexcept {
332 std::pair<double, double> ret = { 0., 0. };
333 for ( const auto& item : _error) {
334 const auto [dn,up] = _downUp2NegPos(item.second);
338 return { - std::sqrt(ret.first), std::sqrt(ret.second) };
358 std::pair<double,double> totalErr() const noexcept {
360 if (_error.count( "")) return _downUp2NegPos(_error.at( ""));
388 neg = _value != 0 ? neg/fabs(_value) : std::numeric_limits<double>::quiet_NaN();
389 pos = _value != 0 ? pos/fabs(_value) : std::numeric_limits<double>::quiet_NaN();
408 std::vector<std::string> sources() const noexcept {
409 std::vector<std::string> keys;
410 for ( const auto& item : _error) keys.push_back(item.first);
415 return _error.count(key);
419 return _error.size();
427 size_t _lengthContent( bool fixed_length = false) const noexcept {
428 const size_t nErrs = fixed_length? 1 : numErrs();
429 return 2*(nErrs + 1);
432 std::vector<double> _serializeContent( bool fixed_length = false) const noexcept {
433 std::vector<double> rtn;
434 const size_t nErrs = fixed_length? 1 : numErrs();
435 rtn.reserve(2*(nErrs + 1));
436 rtn.push_back(_value);
443 rtn.push_back(( double)_error.size());
444 for ( const auto& item : _error) {
445 rtn.push_back(item.second.first);
446 rtn.push_back(item.second.second);
451 void _deserializeContent( const std::vector<double>& data, bool fixed_length = false) {
454 throw UserError( "Length of serialized data should be at least 2!");
456 if (2*(fixed_length? 1 : data[1]) != (data.size() - 2))
457 throw UserError( "Expected "+std::to_string(data[1])+ " error pairs!");
461 auto itr = data.cbegin();
462 const auto itrEnd = data.cend();
463 while (itr != itrEnd) {
465 _value = *itr; ++itr; ++itr;
468 std::string name( "source" + std::to_string(idx));
469 const double dn = *itr; ++itr;
470 const double up = *itr; ++itr;
484 const size_t nErrs = numErrs();
485 if (data.size() != nErrs)
486 throw UserError( "Expected " + std::to_string(nErrs) + " error source labels!");
488 for ( size_t i = 0; i < data.size(); ++i) {
489 const std::string name( "source" + std::to_string(i+1));
490 if (!_error.count(name))
491 throw UserError( "Key names have already been updated!");
507 std::pair<double,double> _downUp2NegPos( const std::pair<double,double> &e) const noexcept {
508 const auto [dn,up] = e;
509 if (dn < 0. && up < 0.) {
511 const double env = std::min(dn, up);
523 const double env = std::max(dn, up);
528 double _average( const std::pair<double,double> & err) const noexcept {
529 return 0.5*(fabs( err.first) + fabs( err.second));
547 std::map<std::string, std::pair<double,double>> _error;
556 std::string _toString() const noexcept {
558 res += ( "value="+ std::to_string(_value));
559 for ( const auto& item : _error) {
560 const std::string name = item.first == ""? "user-supplied total " : "";
561 res += ( ", " + name + "error("+ item.first);
562 res += ( ")={ "+ std::to_string(item.second.first));
563 res += ( ", "+ std::to_string(item.second.second)+ " }");
583 lhs += std::move(rhs);
595 lhs -= std::move(rhs);
601 const std::string& pat_uncorr= "^stat|^uncor") {
605 const double newVal = rtn. val();
608 std::vector<std::string> sources = numer. sources();
609 std::vector<std::string> tmp = denom. sources();
610 sources.insert(std::end(sources),
611 std::make_move_iterator(std::begin(tmp)),
612 std::make_move_iterator(std::end(tmp)));
613 sources.erase( std::unique(sources.begin(), sources.end()), sources.end() );
616 const std::regex re(pat_uncorr);
617 for ( const std::string& src : sources) {
618 if (std::regex_search(src, match, re)) {
621 double n_dn = 0.0, n_up = 0.0;
626 double d_dn = 0.0, d_up = 0.0;
631 const double new_dn = fabs(newVal) * std::sqrt(n_dn*n_dn + d_dn*d_dn);
632 const double new_up = fabs(newVal) * std::sqrt(n_up*n_up + d_up*d_up);
633 rtn. setErr({-new_dn,new_up}, src);
638 double n_dn = numer. val(), n_up = numer. val();
641 n_up += numer. errUp(src);
643 double d_dn = denom. val(), d_up = denom. val();
646 d_up += denom. errUp(src);
648 double new_dn = std::numeric_limits<double>::quiet_NaN();
649 double new_up = std::numeric_limits<double>::quiet_NaN();
650 if (d_dn) new_dn = n_dn / d_dn - newVal;
651 if (d_up) new_up = n_up / d_up - newVal;
652 rtn. setErr({new_dn, new_up}, src);
661 return divide(numer, denom);
666 return divide(std::move(numer), denom);
671 return divide(numer, std::move(denom));
676 return divide(std::move(numer), std::move(denom));
681 const std::string& pat_uncorr= "^stat|^uncor") {
686 const double acc_val = accepted. val();
687 const double tot_val = total. val();
688 if (acc_val > tot_val)
689 throw UserError( "Attempt to calculate an efficiency when the numerator is not a subset of the denominator: "
690 + Utils::toStr(acc_val) + " / " + Utils::toStr(tot_val));
695 std::vector<std::string> sources = accepted. sources();
696 std::vector<std::string> tmp = total. sources();
697 sources.insert(std::end(sources),
698 std::make_move_iterator(std::begin(tmp)),
699 std::make_move_iterator(std::end(tmp)));
700 sources.erase( std::unique(sources.begin(), sources.end()), sources.end() );
704 const double eff = rtn. val();
705 const std::regex re(pat_uncorr);
706 for ( const std::string& src : sources) {
707 double err = std::numeric_limits<double>::quiet_NaN();
709 rtn. setErr({-err,err}, src);
712 else if (std::regex_search(src, match, re)) {
715 err = sqrt(std::abs( ((1-2*eff)* sqr(acc_err) + sqr(eff)* sqr(tot_err)) / sqr(tot_val) ));
716 rtn. setErr({-err,err}, src);
A point estimate (base class for the Estimate)
void scale(const double scalefactor) noexcept Rescale as if value and uncertainty had been different by factor scalefactor.
std::pair< double, double > relTotalErr() const noexcept The relative negative/positive total uncertainty on the central value.
Estimate & add(const Estimate &toAdd, const std::string &pat_uncorr="^stat|^uncor") Add two Estimates.
size_t numErrs() const noexcept
std::pair< double, double > relErrDownUp(const std::string &source="") const The relative error on the central value.
std::pair< double, double > totalErr() const noexcept The total uncertainty.
std::pair< double, double > errNegPos(std::string source="") const The signed negative and positive uncertainty component.
void setErr(const double err, const std::string &source="") Set a symmetric uncertainty component.
Estimate(double v, std::map< std::string, std::pair< double, double > > &errors) Constructor to set an Estimate with a pre-filled state.
double relTotalErrNeg() const noexcept The relative negative total uncertainty on the central value.
double quadSumAvg() const noexcept The average uncertainty component.
void setErr(const std::pair< double, double > &err, const std::string &source="") Set a signed uncertainty component.
Estimate & operator+=(const Estimate &toAdd)
double totalErrNeg() const noexcept The negative total uncertainty.
std::pair< double, double > relErr(const std::string &source="") const Convenience alias for relErrDownUp.
std::vector< std::string > sources() const noexcept
void transform(const Trf< 1 > &trf) Generalised transformations with functors.
void setValue(const double value) noexcept Set the central value of this estimator.
double errDown(const std::string &source="") const The signed error due to the systematic downward variation.
Estimate & operator=(Estimate &&toMove) noexcept
double errPos(const std::string &source="") const The signed positive uncertainty component.
void deserializeSources(const std::vector< std::string > &data)
double errAvg(const std::string &source="") const The average uncertainty component.
double relErrUp(const std::string &source="") const The relative positive on the central value.
Estimate & operator=(const Estimate &toCopy) noexcept
Estimate & operator-=(const Estimate &toSubtract)
double quadSumPos() const noexcept
void scale(const Trf< 1 > &trf) Generalised transformations with functors.
double relErrAvg(const std::string &source="") const The average uncertainty component.
double errUp(const std::string &source="") const The signed error due to the systematic upward variation.
double val() const noexcept The central value.
Estimate(Estimate &&toMove)
double totalErrAvg() const The average total uncertainty.
double totalErrPos() const noexcept The positive total uncertainty.
Estimate() Default constructor of a new distribution.
double relTotalErrAvg() const noexcept The average uncertainty component.
void set(const double val, const std::pair< double, double > &err, const std::string source="") Set both central value and uncertainty component.
void setVal(const double val) noexcept Alias for setValue.
std::vector< std::string > serializeSources() const noexcept
void set(const double val, const double err, const std::string &source="") Set both central value and uncertainty component.
void renameSource(const std::string &old_label, const std::string &new_label) Replace a source label in the error breakdown.
double valMax(const std::string &source="") const
double valueErr() const The unsigned average total uncertainty.
double errNeg(const std::string &source="") const The signed negative uncertainty component.
std::pair< double, double > err(const std::string &source="") const Convenience alias for errorDownUp(source)
double relTotalErrPos() const noexcept The relative positive total uncertainty on the central value.
Estimate & subtract(const Estimate &toSubtract, const std::string &pat_uncorr="^stat|^uncor") Subtract one Estimate from another.
std::pair< double, double > quadSum() const noexcept Get the quadrature sum of uncertainty components.
double quadSumNeg() const noexcept
Estimate(const Estimate &toCopy)
double valMin(const std::string &source="") const
std::pair< double, double > errDownUp(const std::string &source="") const The signed absolute error on the central value.
double relErrDown(const std::string &source="") const The relative negative on the central value.
Estimate(const double v, const std::pair< double, double > &e, const std::string &source="") Alternative constructor to set an Estimate with value and uncertainty.
bool hasSource(const std::string &key) const noexcept
void reset() noexcept Reset the internal values.
Error for e.g. use of invalid bin ranges.
Error for problems introduced outside YODA, to put it nicely.
Anonymous namespace to limit visibility.
BinnedDbn< DbnN, AxisT... > operator+(BinnedDbn< DbnN, AxisT... > first, BinnedDbn< DbnN, AxisT... > &&second) Add two BinnedDbn objects.
BinnedEstimate< AxisT... > operator/(const BinnedDbn< DbnN, AxisT... > &numer, const BinnedDbn< DbnN, AxisT... > &denom)
NUM sqr(NUM a) Named number-type squaring operation.
BinnedEstimate< AxisT... > efficiency(const BinnedDbn< DbnN, AxisT... > &accepted, const BinnedDbn< DbnN, AxisT... > &total) Calculate a binned efficiency ratio of two BinnedDbn objects.
BinnedDbn< DbnN, AxisT... > operator-(BinnedDbn< DbnN, AxisT... > first, BinnedDbn< DbnN, AxisT... > &&second) Subtract one BinnedDbn object from another.
BinnedEstimate< AxisT... > divide(const BinnedDbn< DbnN, AxisT... > &numer, const BinnedDbn< DbnN, AxisT... > &denom) Divide two BinnedDbn objects.
|