Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-05 08:13:03

0001 #pragma once
0002 #include <math.h>
0003 
0004 float inf = INFINITY;
0005 
0006 class LeastSquare
0007 {
0008     /*!
0009       @class LeastSquare
0010       @brief It calculates slope and intercept of the liner function y = a x + b from given data by least square
0011      */
0012 private:
0013     //! A TGraph as a data container
0014     TGraph *g_;
0015 
0016     //! vector variables for data
0017     vector<double> x_;
0018     vector<double> y_;
0019     vector<double> yerr_;
0020 
0021     //! variables
0022     double slope_ = 0;
0023     double intercept_ = 0;
0024     bool debug_ = false;
0025 
0026     // void SetValues()
0027     // {
0028     //     /*!
0029     //       @brief Data is taken from g_ and stored in x_ and y_
0030     //      */
0031     //     x_.erase(x_.begin(), x_.end());
0032     //     y_.erase(y_.begin(), y_.end());
0033 
0034     //     for (int i = 0; i < g_->GetN(); i++)
0035     //     {
0036     //         double x, y;
0037     //         g_->GetPoint(i, x, y);
0038     //         x_.push_back(x);
0039     //         y_.push_back(y);
0040     //     }
0041     // }
0042 
0043     //! Mean of argument is returned
0044     double GetMean(vector<double> &values)
0045     {
0046         return accumulate(values.begin(), values.end(), 0.0) / values.size();
0047     }
0048 
0049     //! Variance of argument is returned
0050     double GetVariance(vector<double> &values)
0051     {
0052         double rtn = 0;
0053         double mean = this->GetMean(values);
0054 
0055         for (auto &val : values)
0056             rtn += pow(val - mean, 2);
0057 
0058         return rtn / values.size();
0059     }
0060 
0061     double Getval_err2(vector<double> values)//x/err^2
0062     {
0063         double sum_ = 0;
0064         for(int i=0; i<values.size(); i++)
0065         {
0066             sum_ += values[i]/(yerr_[i]*yerr_[i]);
0067         }
0068         // for (auto &val : values)
0069         //     sum_+=(val)/(yerr_[i]*yerr_[i]);
0070 
0071         return sum_;
0072     }
0073 
0074     double Get1_err2()// 1/err^2
0075     {
0076         double sum_=0;
0077         for(int i=0; i<yerr_.size(); i++){
0078             sum_ +=1 / (yerr_[i]*yerr_[i]);
0079         }
0080         return sum_;
0081     }
0082 
0083     double Getxy_err2()//xy/err^2
0084     {
0085         double sum_=0;
0086         for(int i=0; i<yerr_.size(); i++){
0087             sum_ +=(x_[i]*y_[i])/(yerr_[i]*yerr_[i]);
0088         }
0089         return sum_;
0090     }
0091 
0092     double Getx2_err2()//y/err^2
0093     {
0094         double sum_ = 0;
0095         for(int i=0; i<yerr_.size(); i++){
0096             sum_ +=(x_[i] * x_[i])/(yerr_[i]*yerr_[i]);
0097         }
0098         return sum_;
0099     }
0100 
0101     //! Covariance of x_ and y_ is returned
0102     double GetCovariance()
0103     {
0104         double rtn = 0;
0105         double x_mean = this->GetMean(x_);
0106         double y_mean = this->GetMean(y_);
0107         for (int i = 0; i < (int)x_.size(); i++)
0108         {
0109             rtn += (x_[i] - x_mean) * (y_[i] - y_mean);
0110             // cout<<"x : "<<x_[i]<<"  y : "<<y_[i]<<endl;
0111         }
0112         // cout <<"x_mean : "<<x_mean<< "  covariance : " << rtn / x_.size() << endl;
0113 
0114 
0115         return rtn / x_.size();
0116     }
0117 
0118 public:
0119     //! The default constructor
0120     LeastSquare(){};
0121 
0122     //! A constructor which takes a TGraph as data input
0123     LeastSquare(TGraph *g) : g_(g){};
0124 
0125     //! It returns the slope. It should to be executed afte Calc()
0126     double GetSlope() { return slope_; };
0127     //! It returns the intercept. It should to be executed afte Calc()
0128     double GetIntercept() { return intercept_; };
0129 
0130     void Setdatax(vector<double> &x)
0131     {
0132         x_.erase(x_.begin(), x_.end());
0133         x_ = x;
0134     }
0135 
0136     void Setdatay(vector<double> &y)
0137     {
0138         y_.erase(y_.begin(), y_.end());
0139         y_ = y;
0140     }
0141 
0142     void Setdatayerr(vector<double> &yerr)
0143     {
0144         yerr_.erase(yerr_.begin(), yerr_.end());
0145         yerr_ = yerr;
0146     }
0147 
0148     // double GetAngle(){
0149     //     double midx = (x_[0] + x_[1]) /2;
0150     //     double midy = (y_[0] + y_[1]) /2;
0151     //     phi_ = atan2(midy, midx)
0152     //         return phi_;
0153     // }
0154 
0155     // void doRotate(double phi)
0156     // {
0157     //     for(int i=0; i<v1.size(); i++)
0158     //     {
0159     //         x_[i] = cos(phi) * x_[i] + sin(phi) * y_[i];
0160     //         y_[i] = cos(phi) * y_[i] - sin(phi) * x_[i];
0161     //     }
0162     // }
0163 
0164     //! Calculation of the slope and intercept is done by least square. The results are stored in the private variables.
0165     bool Calc(int mode)
0166     {
0167         double slope;
0168         double intercept;
0169         if(mode == 0)
0170         {
0171         // this->SetValues();
0172         double x_mean = this->GetMean(x_);
0173         double y_mean = this->GetMean(y_);
0174 
0175         double x_variance = this->GetVariance(x_);
0176         double y_variance = this->GetVariance(y_);
0177 
0178         double covariance = this->GetCovariance();
0179 
0180         slope = covariance / x_variance;
0181         if(x_variance == 0)
0182         slope = inf;
0183         intercept = y_mean - slope * x_mean;
0184 
0185         // doRotate(GetAngle());
0186         }
0187         else if(mode == 1)
0188         {
0189 
0190         double slope_num = this->Get1_err2()* this->Getxy_err2() - this->Getval_err2(x_) * this->Getval_err2(y_);
0191 
0192         double slope_den = this->Getx2_err2() * this->Get1_err2() - (this->Getval_err2(x_) * this->Getval_err2(x_));
0193 
0194         double intercept_num = - this->Getval_err2(x_) * this->Getxy_err2() + this->Getx2_err2()* this->Getval_err2(y_);
0195 
0196         slope = slope_num / slope_den;
0197         if(slope_den == 0)
0198         slope = inf;
0199         intercept = intercept_num / slope_den;
0200         }
0201         
0202         // if (debug_)
0203         // {
0204         //     int length = 15;
0205         //     cout << string(length * 4, '-') << endl;
0206         //     for (int i = 0; i < (int)x_.size(); i++)
0207         //     {
0208         //         cout << setw(length) << "p" << i << " ()"
0209         //              << setw(length) << setprecision(5) << x_[i] << ", "
0210         //              << setw(length) << setprecision(5) << y_[i] << " )" << endl;
0211         //     }
0212         //     cout << setw(length) << "Mean: "
0213         //          << setw(length) << setprecision(5) << x_mean << "\t"
0214         //          << setw(length) << setprecision(5) << y_mean << endl;
0215         //     cout << setw(length) << "Variance: "
0216         //          << setw(length) << setprecision(5) << x_variance << "\t"
0217         //          << setw(length) << setprecision(5) << y_variance << endl;
0218         //     cout << setw(length) << "Covariance: "
0219         //          << setw(length) << setprecision(5) << covariance << endl;
0220         //     cout << setw(length) << "Slope: "
0221         //          << setw(length) << setprecision(5) << slope << endl;
0222         //     cout << setw(length) << "Intercept: "
0223         //          << setw(length) << setprecision(5) << intercept << endl;
0224         // }
0225 
0226         slope_ = slope;
0227         intercept_ = intercept;
0228         return true;
0229     }
0230 
0231     void SetDebugMode(bool flag) { debug_ = flag; };
0232 };
0233 
0234 TGraph *GetGraph(TRandom3 *random)
0235 {
0236 
0237     TGraph *g = new TGraph();
0238     if (true)
0239     {
0240         for (int i = 0; i < 3; i++)
0241         {
0242             double y = 2 * i * random->Gaus(1, 0.1);
0243             g->SetPoint(g->GetN(), i, y);
0244             // hist->Fill( y );
0245         }
0246     }
0247     else
0248     {
0249 
0250         // example from https://sci-pursuit.com/math/statistics/least-square-method.html
0251         g->SetPoint(0, 50, 40);
0252         g->SetPoint(1, 60, 70);
0253         g->SetPoint(2, 70, 90);
0254         g->SetPoint(3, 80, 60);
0255         g->SetPoint(4, 90, 100);
0256     }
0257 
0258     // TH1* hist = new TH1D( "hist", "title", 100, -10, 10 );
0259     // g->SetMarkerStyle( 20 );
0260     //  cout << "Hist StdDev: " << hist->GetStdDev() << endl;
0261     //  cout << "Hist Variance: " << pow( hist->GetStdDev(), 2 ) << endl;
0262     //  cout << "Graph Covariance: " << g->GetCovariance() << endl;
0263 
0264     return g;
0265 }
0266 
0267 //! A test function with LeastSquare class
0268 int TestMine(int loop_num, int mode)
0269 {
0270     TRandom3 *random = new TRandom3();
0271     for (int i = 0; i < loop_num; i++)
0272     {
0273         auto g = GetGraph(random);
0274         LeastSquare *ls = new LeastSquare(g);
0275         ls->SetDebugMode(true);
0276         ls->Calc(mode);
0277     }
0278 
0279     return 0;
0280 }
0281 
0282 //! A test function with ROOT fitting
0283 int TestRootFit(int loop_num)
0284 {
0285 
0286     TRandom3 *random = new TRandom3();
0287     for (int i = 0; i < loop_num; i++)
0288     {
0289         auto g = GetGraph(random);
0290         TF1 *f = new TF1("f", "pol1", -10, 10);
0291         g->Fit(f, "QN0CF");
0292     }
0293 
0294     return 0;
0295 }
0296 
0297 //! A test function with LeastSquare class
0298 int TestBoth(int loop_num, int mode)
0299 {
0300     TRandom3 *random = new TRandom3();
0301     for (int i = 0; i < loop_num; i++)
0302     {
0303         auto g = GetGraph(random);
0304         LeastSquare *ls = new LeastSquare(g);
0305         ls->SetDebugMode(true);
0306         ls->Calc(mode);
0307 
0308         TF1 *f = new TF1("f", "pol1", -10, 10);
0309         g->Fit(f, "QN0CF");
0310         double length = 15;
0311         cout << "-- ROOT fitting " << string(length, '-') << endl;
0312         cout << setw(length) << "Slope: "
0313              << setw(length) << setprecision(5) << f->GetParameter(1) << endl;
0314         cout << setw(length) << "Intercept: "
0315              << setw(length) << setprecision(5) << f->GetParameter(0) << endl;
0316     }
0317 
0318     return 0;
0319 }
0320 
0321 int least_square(int loop_num = 1e5, int test_mode = 0, int mode = 0)
0322 {
0323     /*!
0324       @brief This is the main function.
0325       @param loop_num The number of tests
0326       @param test_mode 0 tests LeastSquare class. 1 tests ROOT fitting.
0327       @details How to run:
0328       Example 1: Testing LeastSquare class for 100 times:
0329         $ root 'least_square( 100, 0 )'
0330 
0331       Example 2: Testing ROOT fitting for 10000 times:
0332         $ root 'least_square( 10000, 1 )'
0333      */
0334 
0335     if (test_mode == 0)
0336         TestMine(loop_num, mode);
0337     else if (test_mode == 1)
0338         TestRootFit(loop_num);
0339     else
0340         TestBoth(loop_num, mode);
0341     return 0;
0342 }