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
0010
0011
0012 private:
0013
0014 TGraph *g_;
0015
0016
0017 vector<double> x_;
0018 vector<double> y_;
0019 vector<double> yerr_;
0020
0021
0022 double slope_ = 0;
0023 double intercept_ = 0;
0024 bool debug_ = false;
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044 double GetMean(vector<double> &values)
0045 {
0046 return accumulate(values.begin(), values.end(), 0.0) / values.size();
0047 }
0048
0049
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)
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
0069
0070
0071 return sum_;
0072 }
0073
0074 double Get1_err2()
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()
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()
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
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
0111 }
0112
0113
0114
0115 return rtn / x_.size();
0116 }
0117
0118 public:
0119
0120 LeastSquare(){};
0121
0122
0123 LeastSquare(TGraph *g) : g_(g){};
0124
0125
0126 double GetSlope() { return slope_; };
0127
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
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165 bool Calc(int mode)
0166 {
0167 double slope;
0168 double intercept;
0169 if(mode == 0)
0170 {
0171
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
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
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
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
0245 }
0246 }
0247 else
0248 {
0249
0250
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
0259
0260
0261
0262
0263
0264 return g;
0265 }
0266
0267
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
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
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
0325
0326
0327
0328
0329
0330
0331
0332
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 }