Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-12-17 09:23:56

0001 //
0002 // To calibrate the tails from events in previous crossings,
0003 //
0004 //    1. first create the mdbsigXX.txt files (uncomment pileupfile in MbdSig.cc)
0005 //
0006 //    2. get_tails() : extracts the mean of the tails from all time and charge ch's from all events
0007 //                     can be used to play with functional fits
0008 //                     (once fit fcn determined, not necessary and can skip to 2)
0009 //
0010 //    3. calc_residuals() : fit the waveforms from events where there was no event in crossing,
0011 //                          but there was an event in prev. crossing
0012 //                          writes out fit parameters to tfit and qfit tree
0013 //                          makes plots of residuals to fits
0014 //                          only the charge fit makes sense here, since the time can be done by simple
0015 //                          correlation
0016 //
0017 //    4. fit_time_pileupcorr() : find slope of s8 vs s0 in time channels, write out mbd_pileup.calib file
0018 //                               this is already done at end of calc_residuals
0019 //
0020 #include "find_th2ridge.C"
0021 
0022 #include <TGraphErrors.h>
0023 #include <TF1.h>
0024 #include <TFile.h>
0025 #include <TPad.h>
0026 #include <TTree.h>
0027 
0028 #include <fstream>
0029 #include <iostream>
0030 #include <set>
0031 #include <string>
0032 
0033 const int NFEECH = 256;
0034 //const int NFEECH = 10;
0035 const int NSAMPLES = 16;
0036  
0037 TH2 *h2_tail[NFEECH];
0038 TH2 *h2_residuals[NFEECH];
0039 TH2 *h2_s8s0[NFEECH]{nullptr};
0040 TGraphErrors *g_tail[NFEECH];
0041 TF1 *fit[NFEECH] = {nullptr};
0042 TF1 *fit_s8s0[NFEECH] = {nullptr};
0043 
0044 // Tree variables
0045 TTree *tfit_tree{nullptr};
0046 Short_t tch{-1};
0047 Float_t tchi2ndf{-1.};
0048 Float_t tfitpar[10]{0.};
0049 TTree *qfit_tree{nullptr};
0050 Short_t qch{-1};
0051 Float_t qchi2ndf{-1.};
0052 Float_t qfitpar[10]{0.};
0053 
0054 Double_t powerlaw(Double_t *x, Double_t *par) // NOLINT(readability-non-const-parameter)
0055 {
0056   Float_t xx =x[0];
0057 
0058   Double_t f = par[0]*pow((par[1]/(par[1]+xx)),par[2]); 
0059 
0060   return f;
0061 }
0062 
0063 //
0064 // Do test fits of the g_tail, which is the mean tail shape from all events
0065 // Used to develop the fit function
0066 //
0067 void fit_test(const int feech = 8, const std::string &fname = "mbdsig_tails.root")
0068 {
0069   TString name;
0070 
0071   static TFile *tfile{nullptr};
0072 
0073   if ( tfile == nullptr )
0074   {
0075     std::cout << "Opening " << fname << std::endl;
0076     tfile = new TFile(fname.c_str(),"READ");
0077   }
0078 
0079   name = "g_tail"; name += feech;
0080   TGraphErrors *g = (TGraphErrors*)tfile->Get( name );
0081 
0082   TF1 *fit2mean{nullptr};
0083 
0084   if ( ((feech/8)%2)==0 ) // time channel
0085   {
0086     //fit2mean = new TF1("fit2mean","gaus+[3]*x+[4]",0,16);
0087     fit2mean = new TF1("fit2mean","gaus+pol2(3)",0,16);
0088     fit2mean->SetParameters(131.5,-18,5.87,-0.002,-0.002/16.,1e-3);
0089     //fit2mean->SetParameters(49.18,-14.544,5.2014,0.0139,-0.00147,4.064e-5);
0090 
0091     g->Draw("ap");
0092     g->Fit(fit2mean,"R");
0093 
0094     TF1 *gaussian = new TF1("gaussian","gaus",0,16);
0095     gaussian->SetParameters(fit2mean->GetParameter(0),fit2mean->GetParameter(1),fit2mean->GetParameter(2));
0096     gaussian->SetLineColor(4);
0097     gaussian->Draw("same");
0098   }
0099   else
0100   {
0101     //fit2mean = new TF1("fit2mean","gaus+pol2(3)",0,16);
0102     //fit2mean->SetParameters(131.5,-18,5.87,-0.002,-0.002/16.,1e-3);
0103 
0104     fit2mean = new TF1("fit2mean","expo + pol2(2)",0,16);
0105     fit2mean->SetParameters(1,-1/16.,1e-2,1e-3,1e-4);
0106 
0107     g->Draw("ap");
0108     g->Fit(fit2mean,"R");
0109   }
0110 
0111   gPad->SetLogy(1);
0112 }
0113 
0114 void fit_tail(TGraph *g, const int feech)
0115 {
0116   int verbose = 0;
0117 
0118   TString name;
0119   if ( fit[feech] == nullptr )
0120   {
0121     if ( ((feech/8)%2)==0 ) // time channel
0122     {
0123       name = "fit"; name += feech;
0124       fit[feech] = new TF1(name,"gaus+pol2(3)",-0.1,16);
0125       fit[feech]->SetLineColor(2);
0126       fit[feech]->SetParameters(5.5*g->GetPointY(0),-4.8,2.6,-0.002,-0.002/16.,1e-3);
0127       //fit[feech]->SetParameters(49.18,-14.544,5.2014,0.0139,-0.00147,4.064e-5);
0128     }
0129     else
0130     {
0131       name = "fit"; name += feech;
0132       //fit[feech] = new TF1(name,"expo+pol2(2)",0,16);
0133       //fit[feech]->SetParameters(1,-1/16.,1e-2,1e-3,1e-4);
0134       
0135       //fit[feech] = new TF1(name,"expo",0,4);
0136       //fit[feech]->SetParameters(log(g->GetPointY(0)),-1/16);
0137 
0138       fit[feech] = new TF1(name,"gaus",-0.1,4.1);
0139       fit[feech]->SetParameters(1.43*g->GetPointY(0),-3.2,3.8);
0140       
0141       fit[feech]->SetLineColor(2);
0142     }
0143   }
0144 
0145   if ( ((feech/8)%2)==0 ) // time channel
0146   {
0147     if ( verbose )
0148     {
0149       g->Draw("ap");
0150       fit[feech]->SetRange(-0.1,16);
0151       g->Fit(fit[feech],"R");
0152       gPad->SetLogy(1);
0153       Double_t chi2 = fit[feech]->GetChisquare();
0154       Double_t ndf = fit[feech]->GetNDF();
0155       std::cout << "chi2 ndf " << chi2 << "\t" << ndf << std::endl;
0156     }
0157     else
0158     {
0159       fit[feech]->SetRange(-0.1,16);
0160       g->Fit(fit[feech],"RNQ");
0161 
0162       // save to tree
0163       tch = feech;
0164       for (int ipar=0; ipar<6; ipar++)
0165       {
0166         tfitpar[ipar] = static_cast<Float_t>( fit[feech]->GetParameter(ipar) );
0167       }
0168 
0169       // copy samp 0 and samp 8 values. samp 8 should be timing maxsamp
0170       tfitpar[7] = static_cast<Float_t>( g->GetPointY(0) );
0171       tfitpar[8] = static_cast<Float_t>( g->GetPointY(1) );
0172       tfitpar[9] = static_cast<Float_t>( g->GetPointY(8) );
0173 
0174       h2_s8s0[feech]->Fill( g->GetPointY(0), g->GetPointY(8) );
0175 
0176       Double_t chi2 = fit[feech]->GetChisquare();
0177       Double_t ndf = fit[feech]->GetNDF();
0178       tchi2ndf = chi2/ndf;
0179       tfit_tree->Fill();
0180     }
0181 
0182     if ( verbose )
0183     {
0184       /*
0185       TF1 *gaussian = new TF1("gaussian","gaus",0,16);
0186       gaussian->SetParameters(fit[feech]->GetParameter(0),fit[feech]->GetParameter(1),fit[feech]->GetParameter(2));
0187       gaussian->SetLineColor(4);
0188       gaussian->Draw("same");
0189       */
0190     }
0191 
0192   }
0193   else    // charge channel
0194   {
0195     if ( verbose )
0196     {
0197       g->Draw("ap");
0198       //gPad->SetLogy(1);
0199       fit[feech]->SetRange(-0.1,4.1);
0200       //fit[feech]->SetParameters(1.43*g->GetPointY(0),-3.2,3.8);
0201       fit[feech]->SetParameters(200.*g->GetPointY(0),-32.,9.8);
0202       g->Fit(fit[feech],"R");
0203 
0204       Double_t chi2 = fit[feech]->GetChisquare();
0205       Double_t ndf = fit[feech]->GetNDF();
0206       std::cout << "chi2 ndf " << chi2 << "\t" << ndf << std::endl;
0207 
0208     }
0209     else
0210     {
0211       fit[feech]->SetRange(-0.1,4.1);
0212       //fit[feech]->SetParameters(1.43*g->GetPointY(0),-3.2,3.8);
0213       fit[feech]->SetParameters(200.*g->GetPointY(0),-32.,9.8);
0214       g->Fit(fit[feech],"RNQ");
0215 
0216       // save to tree
0217       qch = feech;
0218       for (int ipar=0; ipar<3; ipar++)
0219       {
0220         qfitpar[ipar] = static_cast<Float_t>( fit[feech]->GetParameter(ipar) );
0221       }
0222       Double_t chi2 = fit[feech]->GetChisquare();
0223       Double_t ndf = fit[feech]->GetNDF();
0224       qchi2ndf = chi2/ndf;
0225 
0226       qfit_tree->Fill();
0227 
0228     }
0229 
0230     /*
0231     TF1 *expon = new TF1("expon","expo",0,16);
0232     expon->SetParameters(fit[feech]->GetParameter(0),fit[feech]->GetParameter(1));
0233     expon->SetLineColor(4);
0234     expon->Draw("same");
0235     */
0236 
0237   }
0238 
0239   if ( verbose )
0240   {
0241     fit[feech]->SetRange(0,16);
0242     fit[feech]->Draw("same");
0243   
0244     gPad->Modified();
0245     gPad->Update();
0246     std::string junk;
0247     std::cin >> junk;
0248   }
0249 }
0250 
0251 
0252 //
0253 // get the events with only tails in them to use for fitting
0254 //
0255 void get_tails()
0256 {
0257   std::ifstream infile;
0258 
0259   TString name;
0260 
0261   name = "mbdsig_tails.root";
0262   TFile *savefile = new TFile(name,"RECREATE");
0263 
0264   for (int ifeech=0; ifeech<NFEECH; ifeech++)
0265   {
0266     name = "h2_tail"; name += ifeech;
0267     h2_tail[ifeech]  = new TH2F(name,name,NSAMPLES,-0.5,NSAMPLES-0.5,2200,-0.1,1.1);
0268   }
0269 
0270   // set up the sample number array
0271   double xsamp[NSAMPLES];
0272   double yval[NSAMPLES];
0273   for (int isamp=0; isamp<NSAMPLES; isamp++)
0274   {
0275     xsamp[isamp] = isamp;
0276   }
0277 
0278 
0279   std::string junk1;
0280   std::string junk2;
0281   int ch;
0282   double mean;
0283   double pedsigma = 4.0;
0284 
0285   for (int ifeech=0; ifeech<NFEECH; ifeech++)
0286   {
0287     name = "mbdsig"; name += ifeech; name += ".txt";
0288     infile.open( name.Data() );
0289     int evt = 1;
0290     while ( infile >> junk1 >> ch >> junk2 >> mean )
0291     {
0292       if ( evt%1000 == 1 )
0293       {
0294         std::cout << "evt " << evt << std::endl;
0295       }
0296 
0297       for (double & isamp : yval)
0298       {
0299         infile >> isamp;
0300       }
0301 
0302       // find those tail only events with high enough amplitude
0303       if ( (fabs(yval[12]-mean) < pedsigma*3) && ((yval[0]-mean) > 200) )
0304       {
0305         // fill histogram
0306         for (int isamp=0; isamp<NSAMPLES; isamp++)
0307         {
0308           h2_tail[ifeech]->Fill( isamp, (yval[isamp]-mean)/(yval[0]-mean) );
0309         }
0310       }
0311 
0312       /*
0313       if ( fabs(yval[12]-mean) < pedsigma*3 )
0314       {
0315         g_subpulse->Draw("ap");
0316         gPad->Modified();
0317         gPad->Update();
0318         std::cin >> junk2;
0319       }
0320       */
0321 
0322       evt++;
0323     }
0324 
0325     infile.close();
0326   }
0327 
0328   for (int ifeech=0; ifeech<NFEECH; ifeech++)
0329   {
0330     g_tail[ifeech] = find_th2ridge(h2_tail[ifeech]);
0331     //g_tail[ifeech]->InsertPointBefore(0,0,1);
0332     g_tail[ifeech]->SetPointError(0,0,g_tail[ifeech]->GetErrorY(1));
0333     name = "g_tail"; name += ifeech;
0334     g_tail[ifeech]->SetName(name);
0335 
0336     h2_tail[ifeech]->Draw("colz");
0337     g_tail[ifeech]->Draw("cp");
0338 
0339     name = "tail_"; name += ifeech; name += ".png";
0340     gPad->Print( name );
0341 
0342     gPad->SetLogz(1);
0343     gPad->Modified();
0344     gPad->Update();
0345     /*
0346     std::string junk;
0347     std::cin >> junk;
0348     */
0349 
0350     g_tail[ifeech]->Write();
0351   }
0352 
0353   savefile->Write();
0354 }
0355 
0356 //
0357 // fits s8 vs s0 in time channels to get time pileup correction
0358 // then writes out mbd_pileup.calib file
0359 //
0360 void fit_time_pileupcorr()
0361 { 
0362   std::ofstream calibfile("mbd_pileup.calib");
0363 
0364   TString name;
0365 
0366   for (int ifeech=0; ifeech<NFEECH; ifeech++)
0367   {
0368     if ( ((ifeech/8)%2) == 0 )  // time ch
0369     {
0370       name = "f_s8s0_"; name += ifeech;
0371       fit_s8s0[ifeech] = new TF1(name,"[0]*x",0,4500);
0372       fit_s8s0[ifeech]->SetParameters(0.01);
0373 
0374       h2_s8s0[ifeech]->Fit(fit_s8s0[ifeech],"R");
0375 
0376       double p0 = fit_s8s0[ifeech]->GetParameter(0);
0377       double p0err = fit_s8s0[ifeech]->GetParError(0);
0378       double chi2ndf = fit_s8s0[ifeech]->GetChisquare()/fit_s8s0[ifeech]->GetNDF();
0379 
0380       calibfile << ifeech
0381                 << "\t" << p0 << "\t" << p0err
0382                 << "\t" << 0. << "\t" << 0.
0383                 << "\t" << 0. << "\t" << 0.
0384                 << "\t" << chi2ndf << std::endl;
0385     }
0386     else  // charge ch
0387     {
0388       calibfile << ifeech
0389                 << "\t" << 200. << "\t" << 0.
0390                 << "\t" << -32. << "\t" << 0.
0391                 << "\t" << 9.8 << "\t" << 0.
0392                 << "\t" << 1. << std::endl;
0393     }
0394   }
0395 
0396   calibfile.close();
0397 }
0398 
0399 
0400 //
0401 // get the residuals event by event
0402 //
0403 void calc_residuals()
0404 {
0405   std::ifstream infile;
0406 
0407   TString name;
0408 
0409   name = "mbdsig_tailresiduals.root";
0410   TFile *savefile = new TFile(name,"RECREATE");
0411 
0412   for (int ifeech=0; ifeech<NFEECH; ifeech++)
0413   {
0414     name = "h2_residuals"; name += ifeech;
0415     h2_residuals[ifeech]  = new TH2F(name,name,NSAMPLES,-0.5,NSAMPLES-0.5,200,-100,100);
0416     h2_residuals[ifeech]->SetXTitle("sample");
0417 
0418     name = "h2_s8s0_"; name += ifeech;
0419     h2_s8s0[ifeech]  = new TH2F(name,name,900,-0.5,4500-0.5,100,-20,120);
0420     h2_s8s0[ifeech]->SetXTitle("s0");
0421     h2_s8s0[ifeech]->SetYTitle("s8");
0422   }
0423 
0424   tfit_tree = new TTree("tfit","time ch fits");
0425   tfit_tree->Branch("ch",&tch,"ch/S");
0426   tfit_tree->Branch("chi2ndf",&tchi2ndf,"chi2ndf/F");
0427   tfit_tree->Branch("ampl",&tfitpar[0],"ampl/F");
0428   tfit_tree->Branch("mean",&tfitpar[1],"mean/F");
0429   tfit_tree->Branch("sig",&tfitpar[2],"sig/F");
0430   tfit_tree->Branch("p0",&tfitpar[3],"p0/F");
0431   tfit_tree->Branch("p1",&tfitpar[4],"p1/F");
0432   tfit_tree->Branch("p2",&tfitpar[5],"p2/F");
0433   tfit_tree->Branch("s0",&tfitpar[7],"s0/F");   // samp0
0434   tfit_tree->Branch("s1",&tfitpar[8],"s1/F");   // samp1
0435   tfit_tree->Branch("s8",&tfitpar[9],"s8/F");   // samp8 (used for timing)
0436 
0437   qfit_tree = new TTree("qfit","charge ch fits");
0438   qfit_tree->Branch("ch",&qch,"ch/S");
0439   qfit_tree->Branch("chi2ndf",&qchi2ndf,"chi2ndf/F");
0440   qfit_tree->Branch("ampl",&qfitpar[0],"ampl/F");
0441   qfit_tree->Branch("mean",&qfitpar[1],"mean/F");
0442   qfit_tree->Branch("sig",&qfitpar[2],"sig/F");
0443 
0444   TGraphErrors *g_subpulse = new TGraphErrors(NSAMPLES);
0445 
0446   // set up the sample number array
0447   double xsamp[NSAMPLES];
0448   double yval[NSAMPLES];
0449   for (int isamp=0; isamp<NSAMPLES; isamp++)
0450   {
0451     xsamp[isamp] = isamp;
0452   }
0453 
0454   std::string junk1;
0455   std::string junk2;
0456   int ch;
0457   double mean;
0458   double pedsigma = 4.0;
0459 
0460   for (int ifeech=0; ifeech<NFEECH; ifeech++)
0461   {
0462     name = "mbdsig"; name += ifeech; name += ".txt";
0463     std::cout << "Processing " << name << std::endl;
0464     infile.open( name.Data() );
0465     int evt = 1;
0466     while ( infile >> junk1 >> ch >> junk2 >> mean )
0467     {
0468       if ( evt%1000 == 1 )
0469       {
0470         std::cout << "evt " << evt << "\tch " << ifeech << std::endl;
0471       }
0472 
0473       for (int isamp=0; isamp<NSAMPLES; isamp++)
0474       {
0475         infile >> yval[isamp];
0476         g_subpulse->SetPoint( isamp, isamp, yval[isamp] - mean);
0477         g_subpulse->SetPointError( isamp, 0., 5.);
0478       }
0479 
0480       // find those tail only events with high enough amplitude
0481       if ( (fabs(yval[12]-mean) < pedsigma*3) && ((yval[0]-mean) > 200) )
0482       {
0483         fit_tail( g_subpulse, ifeech );
0484 
0485         // fill histogram
0486         for (int isamp=0; isamp<NSAMPLES; isamp++)
0487         {
0488           h2_residuals[ifeech]->Fill( isamp, (yval[isamp]-mean) - fit[ifeech]->Eval(isamp) );
0489           /*
0490           if ( fabs((yval[isamp]-mean) - fit[ifeech]->Eval(isamp)) > 100 )
0491           {
0492             std::cout << "xxx " << isamp << "\t" << yval[isamp]-mean << "\t" << fit[ifeech]->Eval(isamp) << std::endl;
0493             isbad = 1;
0494           }
0495           */
0496         }
0497       }
0498 
0499       evt++;
0500     }
0501 
0502     infile.close();
0503   }
0504 
0505   fit_time_pileupcorr();
0506 
0507   savefile->Write();
0508 }
0509 
0510