File indexing completed on 2026-04-04 08:11:57
0001 #ifndef GLOBALDEDXFITTER_H
0002 #define GLOBALDEDXFITTER_H
0003
0004 #include "bethe_bloch.h"
0005 #include "TF1.h"
0006 #include "TF2.h"
0007 #include "TF3.h"
0008 #include "TChain.h"
0009 #include "TGraph.h"
0010 #include "Math/Minimizer.h"
0011 #include "Math/Functor.h"
0012 #include "Math/Factory.h"
0013
0014 const double m_pi = 0.1396;
0015 const double m_K = 0.4937;
0016 const double m_p = 0.9382;
0017 const double m_d = 1.876;
0018
0019 class GlobaldEdxFitter
0020 {
0021 public:
0022 GlobaldEdxFitter(double xmin = 10., double xmax = 50.)
0023 {
0024 min_norm = xmin;
0025 max_norm = xmax;
0026 };
0027 void processResidualData(size_t ntracks = 200000,
0028 size_t skip = 0,
0029 std::string infile="/sphenix/tg/tg01/hf/mjpeters/run53877_tracks/track_output_53877*.root_resid.root");
0030 void addTrack(double trk_dEdx, double trk_p);
0031 size_t getNtracks()
0032 {
0033 return dEdx.size();
0034 }
0035
0036 double get_fitquality(double norm, double ZS_loss = 0.);
0037 double get_fitquality_new(double A);
0038 TF1* create_TF1(std::string name);
0039 TF2* create_TF2(std::string name);
0040 TF3* create_TF3_new(std::string name);
0041 double get_minimum();
0042 double get_minimum_new();
0043 std::pair<double,double> get_minimum_ZS();
0044 void set_range(double xmin, double xmax, double ZSmin, double ZSmax)
0045 {
0046 min_norm = xmin;
0047 max_norm = xmax;
0048 min_ZS = ZSmin;
0049 max_ZS = ZSmax;
0050 }
0051 void reset()
0052 {
0053 p.clear();
0054 dEdx.clear();
0055 betagamma.clear();
0056 }
0057 std::vector<double> get_betagamma(double A);
0058 TGraph* graph_vsbetagamma(double A);
0059 TGraph* graph_vsp();
0060 private:
0061 std::vector<double> p;
0062 std::vector<double> dEdx;
0063 std::vector<double> betagamma;
0064
0065 double get_fitquality_functor(const double* x);
0066
0067 double get_fitquality_wrapper(double* x, double* p);
0068 double get_fitquality_wrapper_ZS(double* x, double* p);
0069 double get_fitquality_wrapper_new(double* x, double* p);
0070 double min_norm = 10.;
0071 double max_norm = 50.;
0072 double min_ZS = 0.;
0073 double max_ZS = 200.;
0074 double min_B = 8.;
0075 double max_B = 12.;
0076 };
0077
0078 void GlobaldEdxFitter::processResidualData(size_t ntracks, size_t skip, std::string infile)
0079 {
0080 std::unique_ptr<TChain> t = std::make_unique<TChain>();
0081 t->Add((infile+"?#residualtree").c_str());
0082
0083
0084
0085 float px;
0086 float py;
0087 float pz;
0088 float dedx;
0089 float eta;
0090 int nmaps;
0091 int nintt;
0092 int ntpc;
0093 float dcaxy;
0094
0095 t->SetBranchAddress("px",&px);
0096 t->SetBranchAddress("py",&py);
0097 t->SetBranchAddress("pz",&pz);
0098 t->SetBranchAddress("dedx",&dedx);
0099 t->SetBranchAddress("eta",&eta);
0100 t->SetBranchAddress("nmaps",&nmaps);
0101 t->SetBranchAddress("nintt",&nintt);
0102 t->SetBranchAddress("ntpc",&ntpc);
0103 t->SetBranchAddress("dcaxy",&dcaxy);
0104
0105 for(size_t entry=skip; entry<(skip+ntracks); entry++)
0106 {
0107
0108 if(entry % 1000 == 0) std::cout << entry << std::endl;
0109 t->GetEntry(entry);
0110 if(nmaps>0 && nintt>0 && fabs(eta)<1. && dcaxy<0.5 && ntpc>30)
0111 {
0112 p.push_back(sqrt(px*px+py*py+pz*pz));
0113 dEdx.push_back(dedx);
0114 }
0115 }
0116 std::cout << "number of good tracks: " << p.size() << std::endl;
0117
0118 }
0119
0120 void GlobaldEdxFitter::addTrack(double trk_dEdx, double trk_p)
0121 {
0122 dEdx.push_back(trk_dEdx);
0123 p.push_back(trk_p);
0124 }
0125
0126 double GlobaldEdxFitter::get_fitquality_new(double A)
0127 {
0128 double chi2 = 0.;
0129 double ndf = -1.;
0130
0131 double pi_chi2 = 0.;
0132 double K_chi2 = 0.;
0133 double p_chi2 = 0.;
0134 double d_chi2 = 0.;
0135 double pi_ndf = -1.;
0136 double K_ndf = -1.;
0137 double p_ndf = -1.;
0138 double d_ndf = -1.;
0139
0140 for(size_t i=0; i<dEdx.size(); i++)
0141 {
0142 const double dedx_pi = bethe_bloch_new_1D(p[i]/dedx_constants::m_pi,A);
0143 const double dedx_K = bethe_bloch_new_1D(p[i]/dedx_constants::m_K,A);
0144 const double dedx_p = bethe_bloch_new_1D(p[i]/dedx_constants::m_p,A);
0145 const double dedx_d = bethe_bloch_new_1D(p[i]/dedx_constants::m_d,A);
0146
0147
0148
0149
0150 const double pi_dist = fabs(dEdx[i]-dedx_pi);
0151 const double K_dist = fabs(dEdx[i]-dedx_K);
0152 const double p_dist = fabs(dEdx[i]-dedx_p);
0153 const double d_dist = fabs(dEdx[i]-dedx_d);
0154
0155
0156
0157 if(pi_dist<K_dist && pi_dist<p_dist && pi_dist<d_dist)
0158 {
0159
0160 chi2 += pi_dist*pi_dist;
0161 pi_chi2 += pi_dist*pi_dist;
0162 pi_ndf += 1.;
0163 }
0164 else if(K_dist<pi_dist && K_dist<p_dist && K_dist<d_dist)
0165 {
0166
0167 chi2 += K_dist*K_dist;
0168 K_chi2 += K_dist*K_dist;
0169 K_ndf += 1.;
0170 }
0171 else if(p_dist<pi_dist && p_dist<K_dist && p_dist<d_dist)
0172 {
0173
0174 chi2 += p_dist*p_dist;
0175 p_chi2 += p_dist*p_dist;
0176 p_ndf += 1.;
0177 }
0178
0179 else if(d_dist<pi_dist && d_dist<K_dist && d_dist<p_dist)
0180 {
0181
0182 chi2 += d_dist*d_dist;
0183 d_chi2 += d_dist*d_dist;
0184 d_ndf += 1.;
0185 }
0186
0187 ndf += 1.;
0188
0189
0190 }
0191
0192 if(pi_ndf<1.) {pi_chi2 = 0.; pi_ndf = 1.;}
0193 if(K_ndf<1.) {K_chi2 = 0.; K_ndf = 1.;}
0194 if(p_ndf<1.) {p_chi2 = 0.; p_ndf = 1.;}
0195 if(d_ndf<1.) {d_chi2 = 0.; d_ndf = 1.;}
0196
0197 const double quality = sqrt((pi_chi2*pi_chi2)/(pi_ndf*pi_ndf)+(K_chi2*K_chi2)/(K_ndf*K_ndf)+(p_chi2*p_chi2)/(p_ndf*p_ndf)+(d_chi2*d_chi2)/(d_ndf*d_ndf));
0198
0199
0200
0201
0202 return quality;
0203 }
0204
0205 std::vector<double> GlobaldEdxFitter::get_betagamma(double A)
0206 {
0207 std::vector<double> betagamma;
0208 for(size_t i=0; i<dEdx.size(); i++)
0209 {
0210 const double dedx_pi = bethe_bloch_new_1D(p[i]/dedx_constants::m_pi,A);
0211 const double dedx_K = bethe_bloch_new_1D(p[i]/dedx_constants::m_K,A);
0212 const double dedx_p = bethe_bloch_new_1D(p[i]/dedx_constants::m_p,A);
0213 const double dedx_d = bethe_bloch_new_1D(p[i]/dedx_constants::m_d,A);
0214
0215
0216
0217
0218 const double pi_dist = fabs(dEdx[i]-dedx_pi);
0219 const double K_dist = fabs(dEdx[i]-dedx_K);
0220 const double p_dist = fabs(dEdx[i]-dedx_p);
0221 const double d_dist = fabs(dEdx[i]-dedx_d);
0222
0223 if(pi_dist<K_dist && pi_dist<p_dist && pi_dist<d_dist)
0224 {
0225 betagamma.push_back(p[i]/dedx_constants::m_pi);
0226 }
0227 else if(K_dist<pi_dist && K_dist<p_dist && K_dist<d_dist)
0228 {
0229 betagamma.push_back(p[i]/dedx_constants::m_K);
0230 }
0231 else if(p_dist<pi_dist && p_dist<K_dist && p_dist<d_dist)
0232 {
0233 betagamma.push_back(p[i]/dedx_constants::m_p);
0234 }
0235 else if(d_dist<pi_dist && d_dist<K_dist && d_dist<p_dist)
0236 {
0237 betagamma.push_back(p[i]/dedx_constants::m_d);
0238 }
0239 }
0240 return betagamma;
0241 }
0242
0243 double GlobaldEdxFitter::get_fitquality(double norm, double ZS_loss)
0244 {
0245 float pi_chi2 = 0.;
0246 float K_chi2 = 0.;
0247 float p_chi2 = 0.;
0248 float d_chi2 = 0.;
0249 float pi_ndf = -1.;
0250 float K_ndf = -1.;
0251 float p_ndf = -1.;
0252 float d_ndf = -1.;
0253 float ndf = -1;
0254
0255 for(size_t i=0; i<dEdx.size(); i++)
0256 {
0257
0258 const float dedx_pi = norm*bethe_bloch_total(p[i]/dedx_constants::m_pi) - ZS_loss;
0259 const float dedx_K = norm*bethe_bloch_total(p[i]/dedx_constants::m_K) - ZS_loss;
0260 const float dedx_p = norm*bethe_bloch_total(p[i]/dedx_constants::m_p) - ZS_loss;
0261 const float dedx_d = norm*bethe_bloch_total(p[i]/dedx_constants::m_d) - ZS_loss;
0262
0263 const float pi_dist = fabs(dedx_pi-dEdx[i]);
0264 const float K_dist = fabs(dedx_K-dEdx[i]);
0265 const float p_dist = fabs(dedx_p-dEdx[i]);
0266 const float d_dist = fabs(dedx_d-dEdx[i]);
0267
0268 if(pi_dist<K_dist && pi_dist<p_dist && pi_dist<d_dist)
0269 {
0270 pi_chi2 += pi_dist*pi_dist/fabs(dedx_pi);
0271 pi_ndf += 2.;
0272 }
0273 else if(K_dist<pi_dist && K_dist<p_dist && K_dist<d_dist)
0274 {
0275 K_chi2 += K_dist*K_dist/fabs(dedx_K);
0276 K_ndf += 2.;
0277 }
0278 else if(p_dist<pi_dist && p_dist<K_dist && p_dist<d_dist)
0279 {
0280 p_chi2 += p_dist*p_dist/fabs(dedx_p);
0281 p_ndf += 2.;
0282 }
0283 else if(d_dist<pi_dist && d_dist<K_dist && d_dist<p_dist)
0284 {
0285 d_chi2 += d_dist*d_dist/fabs(dedx_d);
0286 d_ndf += 2.;
0287 }
0288 ndf += 2;
0289 }
0290
0291
0292
0293
0294
0295
0296
0297 const double quality = sqrt((pi_chi2*pi_chi2 +
0298 K_chi2*K_chi2 +
0299 p_chi2*p_chi2)
0300 /(ndf*ndf));
0301
0302 std::cout << "norm: " << norm << " ZS: " << ZS_loss << std::endl;
0303 std::cout << "quality: " << quality << std::endl;
0304
0305 return quality;
0306 }
0307
0308 double GlobaldEdxFitter::get_fitquality_functor(const double* x)
0309 {
0310 return get_fitquality_new(x[0]);
0311 }
0312
0313 double GlobaldEdxFitter::get_fitquality_wrapper(double* x, double* p)
0314 {
0315 return get_fitquality(x[0]);
0316 }
0317
0318 double GlobaldEdxFitter::get_fitquality_wrapper_ZS(double* x, double* p)
0319 {
0320 return get_fitquality(x[0],x[1]);
0321 }
0322
0323 double GlobaldEdxFitter::get_fitquality_wrapper_new(double* x, double* p)
0324 {
0325 return get_fitquality_new(x[0]);
0326 }
0327
0328 TF3* GlobaldEdxFitter::create_TF3_new(std::string name)
0329 {
0330 TF3* f = new TF3(name.c_str(),this,&GlobaldEdxFitter::get_fitquality_wrapper_new,min_norm,max_norm,min_B,max_B,min_ZS,max_ZS,0,"GlobaldEdxFitter","get_fitquality_wrapper_new");
0331 return f;
0332 }
0333
0334 TF1* GlobaldEdxFitter::create_TF1(std::string name)
0335 {
0336 TF1* f = new TF1(name.c_str(),this,&GlobaldEdxFitter::get_fitquality_wrapper_new,min_norm,max_norm,0,"GlobaldEdxFitter","get_fitquality_wrapper");
0337 return f;
0338 }
0339
0340 TF2* GlobaldEdxFitter::create_TF2(std::string name)
0341 {
0342 TF2* f = new TF2(name.c_str(),this,&GlobaldEdxFitter::get_fitquality_wrapper_ZS,min_norm,max_norm,min_ZS,max_ZS,0,"GlobaldEdxFitter","get_fitquality_wrapper_ZS");
0343 return f;
0344 }
0345
0346 double GlobaldEdxFitter::get_minimum_new()
0347 {
0348
0349
0350
0351
0352
0353
0354
0355
0356
0357 ROOT::Math::Minimizer* minimizer = ROOT::Math::Factory::CreateMinimizer("Minuit2");
0358 minimizer->SetMaxFunctionCalls(1000000);
0359 minimizer->SetMaxIterations(10000);
0360 minimizer->SetTolerance(0.1);
0361 minimizer->SetPrintLevel(1);
0362 ROOT::Math::Functor f(this,&GlobaldEdxFitter::get_fitquality_functor,1);
0363 double step[1] = {.01};
0364 double variable[1] = {20.};
0365 minimizer->SetFunction(f);
0366 minimizer->SetVariable(0,"A",variable[0],step[0]);
0367 minimizer->Minimize();
0368 const double *xs = minimizer->X();
0369 return xs[0];
0370 }
0371
0372 double GlobaldEdxFitter::get_minimum()
0373 {
0374 TF1* f = create_TF1("temp");
0375 f->SetNpx(1000);
0376 double minX = f->GetMinimumX();
0377 delete f;
0378 return minX;
0379 }
0380
0381 std::pair<double,double> GlobaldEdxFitter::get_minimum_ZS()
0382 {
0383 TF2* f = create_TF2("temp");
0384 double minX;
0385 double minY;
0386 f->GetMinimumXY(minX,minY);
0387 delete f;
0388 return std::make_pair(minX,minY);
0389 }
0390
0391 TGraph* GlobaldEdxFitter::graph_vsbetagamma(double A)
0392 {
0393 std::vector<double> betagamma = get_betagamma(A);
0394 TGraph* g = new TGraph(dEdx.size(),betagamma.data(),dEdx.data());
0395 return g;
0396 }
0397
0398 TGraph* GlobaldEdxFitter::graph_vsp()
0399 {
0400 TGraph* g = new TGraph(dEdx.size(),p.data(),dEdx.data());
0401 return g;
0402 }
0403
0404 #endif