Back to home page

sPhenix code displayed by LXR

 
 

    


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; // GeV
0015 const double m_K = 0.4937; // GeV
0016 const double m_p = 0.9382; // GeV
0017 const double m_d = 1.876; // GeV
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 //  TFile* f = TFile::Open(infile.c_str());
0083 //  TTree* t = (TTree*)f->Get("residualtree");
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     //if(entry==t->GetEntries()-1) break;
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   //f->Close();
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     //std::cout << "dedx: (" << dedx_pi << ", " << dedx_K << ", " << dedx_p << ", " << dedx_d << ")" << std::endl;
0148     //std::cout << "measured: " << dEdx[i] << std::endl;
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     //std::cout << "dist: (" << pi_dist << ", " << K_dist << ", " << p_dist << ", " << d_dist << ")" << std::endl;
0156 
0157     if(pi_dist<K_dist && pi_dist<p_dist && pi_dist<d_dist)
0158     {
0159       //std::cout << "pion" << std::endl;
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       //std::cout << "K" << std::endl;
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       //std::cout << "p" << std::endl;
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       //std::cout << "d" << std::endl;
0182       chi2 += d_dist*d_dist;
0183       d_chi2 += d_dist*d_dist;
0184       d_ndf += 1.;
0185     }
0186 
0187     ndf += 1.;
0188     //std::cout << "chi2: " << chi2 << std::endl;
0189     //std::cout << "ndf: " << ndf << std::endl;
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   //const double quality = chi2/ndf;
0199 
0200   //std::cout << "A: " << A << " quality: " << quality << std::endl;
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     //std::cout << "dedx: (" << dedx_pi << ", " << dedx_K << ", " << dedx_p << ", " << dedx_d << ")" << std::endl;
0216     //std::cout << "measured: " << dEdx[i] << std::endl;
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   const double quality = sqrt((pi_chi2*pi_chi2)/(pi_ndf*pi_ndf) +
0292                         (K_chi2*K_chi2)/(K_ndf*K_ndf) +
0293                         (p_chi2*p_chi2)/(p_ndf*p_ndf) +
0294                         (d_chi2*d_chi2)/(d_ndf*d_ndf));
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   TF3* f = create_TF3_new("temp");
0350   double minA;
0351   double minB;
0352   double minC;
0353   f->GetMinimumXYZ(minA,minB,minC);
0354   delete f;
0355   return std::make_tuple(minA,minB,minC);
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