Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-04-19 09:13:40

0001 // -*- C++ -*-
0002 //
0003 // This file is part of YODA -- Yet more Objects for Data Analysis
0004 // Copyright (C) 2008-2024 The YODA collaboration (see AUTHORS for details)
0005 //
0006 #ifndef YODA_Estimate0D_h
0007 #define YODA_Estimate0D_h
0008 
0009 #include "YODA/AnalysisObject.h"
0010 #include "YODA/Exceptions.h"
0011 #include "YODA/Estimate.h"
0012 #include "YODA/Scatter.h"
0013 
0014 #include <string>
0015 
0016 namespace YODA {
0017 
0018   /// @brief An estimate in 0D
0019   ///
0020   /// This class linkes the Estimate class with
0021   /// AnalysisObject, so it can be used as a type
0022   /// reduction for the Counter type.
0023   class Estimate0D : public Estimate,
0024                      public AnalysisObject {
0025   public:
0026 
0027     using Ptr = std::shared_ptr<Estimate0D>;
0028     using BaseT = Estimate;
0029     using BaseT::operator =;
0030     using BaseT::operator +=;
0031     using BaseT::operator -=;
0032     using AnalysisObject::operator =;
0033 
0034     /// @name Constructors
0035     //@{
0036 
0037     /// @brief Nullary constructor for unique pointers etc.
0038     ///
0039     /// @note The setting of optional path/title is not possible here in order
0040     /// to avoid overload ambiguity for brace-initialised constructors.
0041     Estimate0D(const std::string& path = "", const std::string& title = "")
0042       : BaseT(), AnalysisObject("Estimate0D", path, title) { }
0043 
0044 
0045     /// @brief Constructor to set an Estimate0D with a pre-filled state.
0046     ///
0047     /// Principally designed for internal persistency use.
0048     Estimate0D(double v,
0049              std::map<std::string,std::pair<double,double>>& errors,
0050              const std::string& path = "", const std::string& title = "")
0051       : BaseT(v, errors), AnalysisObject("Estimate0D", path, title) { }
0052 
0053 
0054     /// @brief Alternative constructor to set an Estimate0D with value and uncertainty.
0055     Estimate0D(const double v, const std::pair<double,double>& e, const std::string& source = "",
0056              const std::string& path = "", const std::string& title = "")
0057       : BaseT(v, e, source), AnalysisObject("Estimate0D", path, title) { }
0058 
0059     /// @brief Copy constructor (needed for clone functions).
0060     ///
0061     /// @note Compiler won't generate this constructor automatically.
0062     Estimate0D(const Estimate0D& other) : Estimate(other),
0063          AnalysisObject(other.type(), other.path(), other, other.title()) { }
0064 
0065     /// @brief Move constructor
0066     Estimate0D(Estimate0D&& other) : BaseT(std::move(other)),
0067          AnalysisObject(other.type(), other.path(), other, other.title()) { }
0068 
0069     /// @brief Copy constructor using base class
0070     Estimate0D(const BaseT& other, const std::string& path = "", const std::string& title = "")
0071       : BaseT(other), AnalysisObject("Estimate0D", path, title) { }
0072 
0073     /// @brief Move constructor using base class
0074     Estimate0D(BaseT&& other, const std::string& path = "", const std::string& title = "")
0075       : BaseT(std::move(other)), AnalysisObject("Estimate0D", path, title) { }
0076 
0077     /// @brief Make a copy on the stack
0078     Estimate0D clone() const noexcept {
0079       return Estimate0D(*this);
0080     }
0081 
0082     /// @brief Make a copy on the heap
0083     Estimate0D* newclone() const noexcept {
0084       return new Estimate0D(*this);
0085     }
0086 
0087     //@}
0088 
0089 
0090     /// @name Operators
0091     //@{
0092 
0093     /// Copy assignment
0094     ///
0095     /// Sets all the parameters using the ones provided from an existing Estimate0D.
0096     Estimate0D& operator=(const Estimate0D& toCopy) noexcept {
0097       if (this != &toCopy) {
0098         AnalysisObject::operator = (toCopy);
0099         BaseT::operator = (toCopy);
0100       }
0101       return *this;
0102     }
0103 
0104     /// Move assignment
0105     Estimate0D& operator = (Estimate0D&& toMove) noexcept {
0106       if (this != &toMove) {
0107         AnalysisObject::operator = (toMove);
0108         BaseT::operator = (std::move(toMove));
0109       }
0110       return *this;
0111     }
0112 
0113     /// Add two Estimate0Ds
0114     Estimate0D& add(const Estimate0D& toAdd, const std::string& pat_uncorr="^stat|^uncor" ) {
0115       if (hasAnnotation("ScaledBy")) rmAnnotation("ScaledBy");
0116       BaseT::add(toAdd, pat_uncorr);
0117       return *this;
0118     }
0119     //
0120     Estimate0D& operator+=(const Estimate0D& toAdd) {
0121       return add(toAdd);
0122     }
0123 
0124     /// Add two (rvalue) Estimate0Ds
0125     Estimate0D& add(Estimate0D&& toAdd, const std::string& pat_uncorr="^stat|^uncor" ) {
0126       if (hasAnnotation("ScaledBy")) rmAnnotation("ScaledBy");
0127       BaseT::add(std::move(toAdd), pat_uncorr);
0128       return *this;
0129     }
0130     //
0131     Estimate0D& operator+=(Estimate0D&& toAdd) {
0132       return add(std::move(toAdd));
0133     }
0134 
0135     /// Subtract two Estimate0Ds
0136     Estimate0D& subtract(const Estimate0D& toSubtract, const std::string& pat_uncorr="^stat|^uncor" ) {
0137       if (hasAnnotation("ScaledBy")) rmAnnotation("ScaledBy");
0138       BaseT::subtract(toSubtract, pat_uncorr);
0139       return *this;
0140     }
0141     //
0142     Estimate0D& operator-=(const Estimate0D& toSubtract) {
0143       return subtract(toSubtract);
0144     }
0145 
0146     /// Subtract two (rvalue) Estimate0Ds
0147     Estimate0D& subtract(Estimate0D&& toSubtract, const std::string& pat_uncorr="^stat|^uncor" ) {
0148       if (hasAnnotation("ScaledBy")) rmAnnotation("ScaledBy");
0149       BaseT::subtract(std::move(toSubtract), pat_uncorr);
0150       return *this;
0151     }
0152     Estimate0D& operator-=(Estimate0D&& toSubtract) {
0153       return subtract(std::move(toSubtract));
0154     }
0155 
0156     //@}
0157 
0158     /// @name Dimensions
0159     /// @{
0160 
0161     /// @brief Total dimension of this data object
0162     size_t dim() const noexcept { return 1; }
0163 
0164     //@}
0165 
0166     /// @name Modifiers
0167     //@{
0168 
0169     /// Reset the internal values
0170     void reset() noexcept {
0171       BaseT::reset();
0172     }
0173 
0174     //@}
0175 
0176     // @brief Render information about this AO
0177     void _renderYODA(std::ostream& os, const int width = 13) const noexcept {
0178 
0179       // Render error sources
0180       const std::vector<std::string> labels = this->sources();
0181       if (labels.size()) {
0182         os << "ErrorLabels: [";
0183         for (size_t i = 0; i < labels.size(); ++i) {
0184           const std::string& src = labels[i];
0185           if (i)  os << ", ";
0186           os << std::quoted(src);
0187         }
0188         os << "]\n";
0189       }
0190 
0191       // column header: content types
0192       os << std::setw(width) << std::left << "# value" << "\t";
0193       const int errwidth = std::max(int(std::to_string(labels.size()).size()+7), width); // "errDn(" + src + ")"
0194       for (size_t i = 0; i < labels.size(); ++i) {
0195         const std::string& src = labels[i];
0196         if (src.empty()) {
0197           os << std::setw(errwidth) << std::left << "totalDn" << "\t";
0198           os << std::setw(errwidth) << std::left << "totalUp" << "\t";
0199         }
0200         else {
0201           os << std::setw(errwidth) << std::left << ("errDn(" + std::to_string(i+1) + ")") << "\t";
0202           os << std::setw(errwidth) << std::left << ("errUp(" + std::to_string(i+1) + ")") << "\t";
0203         }
0204       }
0205       os << "\n";
0206 
0207       os << std::setw(width) << std::left << val() << "\t"; // render value
0208       // render systs if available
0209       for (const std::string& src : labels) {
0210         if (!hasSource(src)) {
0211           os << std::setw(errwidth) << std::left << "---" << "\t"
0212              << std::setw(errwidth) << std::left << "---" << "\t";
0213           continue;
0214         }
0215         const auto& errs = err(src);
0216         os << std::setw(errwidth) << std::left << errs.first << "\t"
0217            << std::setw(errwidth) << std::left << errs.second << "\t";
0218       }
0219       os << "\n";
0220     }
0221 
0222     // @brief Render scatter-like information about this AO
0223     void _renderFLAT(std::ostream& os, const int width = 13) const noexcept {
0224       const Scatter1D tmp = mkScatter();
0225       tmp._renderYODA(os, width);
0226     }
0227 
0228     /// @}
0229 
0230     /// @name MPI (de-)serialisation
0231     ///@{
0232 
0233     size_t lengthContent(bool fixed_length = false) const noexcept {
0234       return BaseT::_lengthContent(fixed_length);
0235     }
0236 
0237     std::vector<double> serializeContent(bool fixed_length = false) const noexcept {
0238       return BaseT::_serializeContent(fixed_length);
0239     }
0240 
0241     void deserializeContent(const std::vector<double>& data) {
0242       BaseT::_deserializeContent(data, data.size() == 4);
0243     }
0244 
0245     /// @}
0246 
0247     /// @name Type reductions
0248     //@{
0249 
0250     inline Scatter1D mkScatter(const std::string& path = "",
0251                                const std::string& pat_match = "") const noexcept {
0252       Scatter1D rtn;
0253       for (const std::string& a : annotations()) {
0254         if (a != "Type")  rtn.setAnnotation(a, annotation(a));
0255       }
0256       rtn.setAnnotation("Path", path);
0257 
0258       // Add the PointND
0259       const double tot = fabs(totalErrPos(pat_match)); // use positive error component
0260       rtn.addPoint( Point1D(val(), {tot, tot}) );
0261 
0262       return rtn;
0263     }
0264 
0265     /// @brief Method returns clone of the estimate with streamlined error source
0266     AnalysisObject* mkInert(const std::string& path = "",
0267                             const std::string& source = "") const noexcept {
0268       Estimate0D* rtn = newclone();
0269       rtn->setPath(path);
0270       if (rtn->numErrs() == 1) {
0271         try {
0272           rtn->renameSource("", source);
0273         }
0274         catch (YODA::UserError& e) { }
0275       }
0276       return rtn;
0277     }
0278 
0279     //@}
0280 
0281   };
0282 
0283   /// @name Generalised transformations
0284   /// @{
0285 
0286   inline void transform(Estimate0D& est, const Trf<1>& fn) {
0287     est.transform(fn);
0288   }
0289 
0290   template <typename FN>
0291   inline void transform(Estimate0D& est, const FN& fn) {
0292     transform(est, Trf<1>(fn));
0293   }
0294 
0295   /// @}
0296 
0297 
0298   /// @name Global operators for Estimate0D objects
0299   //@{
0300 
0301   /// @brief Add two Estimate0D objects
0302   inline Estimate0D operator + (Estimate0D lhs, const Estimate0D& rhs) {
0303     lhs += rhs;
0304     return lhs;
0305   }
0306 
0307   /// @brief Add two Estimate0D objects
0308   inline Estimate0D operator + (Estimate0D lhs, Estimate0D&& rhs) {
0309     lhs += std::move(rhs);
0310     return lhs;
0311   }
0312 
0313   /// @brief Subtract two Estimate0D objects
0314   inline Estimate0D operator - (Estimate0D lhs, const Estimate0D& rhs) {
0315     lhs -= rhs;
0316     return lhs;
0317   }
0318 
0319   /// @brief Subtract two Estimate0D objects
0320   inline Estimate0D operator - (Estimate0D lhs, Estimate0D&& rhs) {
0321     lhs -= std::move(rhs);
0322     return lhs;
0323   }
0324 
0325   /// @brief Divide two Estimate0D objects
0326   inline Estimate0D divide(const Estimate0D& numer, const Estimate0D& denom,
0327                            const std::string& pat_uncorr="^stat|^uncor" ) {
0328     Estimate0D rtn = divide(static_cast<const Estimate&>(numer),
0329                             static_cast<const Estimate&>(denom), pat_uncorr);
0330     if (rtn.hasAnnotation("ScaledBy")) rtn.rmAnnotation("ScaledBy");
0331     if (numer.path() == denom.path())  rtn.setPath(numer.path());
0332     return rtn;
0333   }
0334 
0335   /// @brief Divide two Estimate0D objects
0336   inline Estimate0D operator / (const Estimate0D& numer, const Estimate0D& denom) {
0337     return divide(numer, denom);
0338   }
0339 
0340   /// @brief Divide two Estimate0D objects
0341   inline Estimate0D operator / (Estimate0D&& numer, const Estimate0D& denom) {
0342     return divide(std::move(numer), denom);
0343   }
0344 
0345   /// @brief Divide two Estimate0D objects
0346   inline Estimate0D operator / (const Estimate0D& numer, Estimate0D&& denom) {
0347     return divide(numer, std::move(denom));
0348   }
0349 
0350   /// @brief Divide two Estimate0D objects
0351   inline Estimate0D operator / (Estimate0D&& numer, Estimate0D&& denom) {
0352     return divide(std::move(numer), std::move(denom));
0353   }
0354 
0355   /// @brief Divide two Estimate0D objects using binomial statistics
0356   inline Estimate0D efficiency(const Estimate0D& accepted, const Estimate0D& total,
0357                                const std::string& pat_uncorr="^stat|^uncor" ) {
0358     Estimate0D rtn = efficiency(static_cast<const Estimate&>(accepted),
0359                                 static_cast<const Estimate&>(total), pat_uncorr);
0360     if (rtn.hasAnnotation("ScaledBy")) rtn.rmAnnotation("ScaledBy");
0361     if (accepted.path() == total.path())  rtn.setPath(total.path());
0362     return rtn;
0363   }
0364 
0365   //@}
0366 
0367 }
0368 
0369 #endif