Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2026-05-23 08:15:38

0001 #ifndef MACRO_RECAL_MBD_MIP_C
0002 #define MACRO_RECAL_MBD_MIP_C
0003 //
0004 // Do a recalibration of the mip from the saved histograms
0005 //
0006 #include "get_runstr.h"
0007 
0008 #include <mbd/MbdCalib.h>
0009 
0010 #include <fun4all/Fun4AllUtils.h>
0011 
0012 #include <TCanvas.h>
0013 #include <TF1.h>
0014 #include <TFile.h>
0015 #include <TH1.h>
0016 #include <TH2.h>
0017 #include <TMath.h>
0018 #include <TPad.h>
0019 #include <TPaveStats.h>
0020 #include <TSpectrum.h>
0021 #include <TSystem.h>
0022 #include <TStyle.h>
0023 
0024 #include <fstream>
0025 
0026 R__LOAD_LIBRARY(libmbd.so)
0027 
0028 int verbose{0};
0029 
0030 Double_t qmin = 25.;
0031 Double_t qmax = 4000;
0032 TF1 *bkgf[128]{nullptr};
0033 TF1 *mipfit[128]{nullptr};
0034 TF1 *totfit[128]{nullptr};
0035 
0036 const int NUM_PMT = 128;
0037 //const int NUM_PMT = 2;
0038 //const int NUM_ARMS = 2;
0039 
0040 TH1 *h_q[NUM_PMT];       // orig histograms
0041 TH1 *h_tq[NUM_PMT];
0042 TH1 *h_bkg[NUM_PMT];     // background histogram
0043 TH1 *h_mip[NUM_PMT];     // mip signal histogram
0044 TH1 *h_bkgmip[NUM_PMT];  // bkg + fit histogram
0045 
0046 
0047 double minrej = 2000.;
0048 double peak = 2000.;
0049 double maxrej = 5000.;
0050 double n_at_peak{0};
0051 
0052 const int NPAR_BKGF = 9;
0053 double seed_threshold[128]{0};
0054 double seed_qmin[128]{0};
0055 double seed_minrej[128]{0};
0056 double seed_natpeak[128]{0};
0057 double seed_maxrej[128]{0};
0058 double seed_qmax[128]{0};
0059 double seed_par[128][NPAR_BKGF]{{0}};
0060 
0061 // Power law + exponential
0062 // [0] = plaw ampl
0063 // [1] = plaw parameter
0064 // [2] = plaw exponent
0065 // [3] = expo ampl
0066 // [4] = expo exponent
0067 Double_t expopowerlaw(Double_t *x, Double_t *par) //NOLINT(readability-non-const-parameter)
0068 {
0069   Float_t xx =x[0];
0070 
0071   if ( xx>minrej && xx<maxrej )
0072   {
0073     TF1::RejectPoint();
0074     //return std::numeric_limits<double>::quiet_NaN();
0075     return 100;
0076   }
0077 
0078   Double_t f = par[0]*pow((par[1]/(par[1]+xx)),par[2]) + par[3]*exp(-1.0*par[4]*xx);
0079 
0080   return f;
0081 }
0082 
0083 Double_t powerlaw(Double_t *x, Double_t *par) //NOLINT(readability-non-const-parameter)
0084 {
0085   Float_t xx =x[0];
0086   if ( xx>minrej && xx<maxrej )
0087   {
0088     TF1::RejectPoint();
0089     return 0;
0090   }
0091   Double_t f = par[0]*pow((par[1]/(par[1]+xx)),par[2]); 
0092   return f;
0093 }
0094 
0095 
0096 // Two gaussians
0097 // [0] = ampl, peak 1
0098 // [1] = mean
0099 // [2] = sigma
0100 // [3] = ampl, peak 2
0101 Double_t gaus2(Double_t *x, Double_t *par) //NOLINT(readability-non-const-parameter)
0102 {
0103   Double_t xx =x[0];
0104   Double_t f = par[0]*TMath::Gaus(xx,par[1],par[2]) + par[3]*TMath::Gaus(xx,2.0*par[1],sqrt(2)*par[2]); 
0105   return f;
0106 }
0107 
0108 // Simple skewed gaussian + 2nd gaussian peak
0109 // [0] = ampl, peak 1
0110 // [1] = mean
0111 // [2] = sigma
0112 // [3] = skewness
0113 // [4] = ampl, peak 2
0114 Double_t skgaus2(Double_t *x, Double_t *par) //NOLINT(readability-non-const-parameter)
0115 {
0116   Double_t xx =x[0];
0117 
0118   Double_t denom = par[2]+par[3]*(xx-par[1]);
0119   if (std::abs(denom) < 1e-12) denom = 1e-12;  // prevent division by zero
0120   Double_t f = par[0]*exp(-0.5*pow((xx-par[1])/denom,2.0))
0121     + par[4]*TMath::Gaus(xx,2.0*par[1],sqrt(2)*par[2]); 
0122 
0123   return f;
0124 }
0125 
0126 // Power law + exponential + gaus2
0127 // [0] = plaw ampl
0128 // [1] = plaw parameter
0129 // [2] = plaw exponent
0130 // [3] = expo ampl
0131 // [4] = expo exponent
0132 // [5] = gaus ampl, peak 1
0133 // [6] = gaus mean
0134 // [7] = gaus sigma
0135 // [8] = gaus ampl, peak 2
0136 Double_t expopowerlawskgaus2(Double_t *x, Double_t *par) //NOLINT(readability-non-const-parameter)
0137 {
0138   Double_t f = expopowerlaw(x,par) + skgaus2(x,&par[5]);
0139   return f;
0140 }
0141 
0142 // Two skewed gaussians
0143 // [0] = ampl, peak 1
0144 // [1] = xi (almost mean)
0145 // [2] = omega (almost sigma)
0146 // [3] = alpha (skewness)
0147 // [4] = ampl, peak 2
0148 Double_t skewedgaus2(Double_t *x, Double_t *par) // NOLINT(readability-non-const-parameter)
0149 {
0150   double xx = x[0];
0151   double xi = par[1];
0152   double omega = par[2];
0153   double alpha = par[3];
0154   double arg = (xx - xi) / omega;
0155   double smallphi = TMath::Gaus(arg, 0.0, 1.0, true);
0156   double bigphi = 0.5 * (1 + std::erf(alpha * arg/std::sqrt(2)));
0157   double f = par[0] * (2./omega) * smallphi * bigphi;
0158   f += par[4]*TMath::Gaus(xx,2.0*par[1],sqrt(2)*par[2]);
0159 
0160   return f;
0161 }
0162 
0163 Double_t woodssaxon(Double_t *x, Double_t *par) //NOLINT(readability-non-const-parameter)
0164 {
0165   Double_t xx =x[0];
0166   Double_t e = par[0]/(1.0+exp((xx-par[1])/par[2]));
0167   return e;
0168 }
0169 
0170 // Two gaussians + expo
0171 // [0] = ampl, peak 1
0172 // [1] = mean
0173 // [2] = sigma
0174 // [3] = ampl, peak 2
0175 // [4] = ampl, woods-saxon
0176 // [5] = a, woods-saxon 
0177 // [6] = slope, expo
0178 Double_t gaus2ws(Double_t *x, Double_t *par) //NOLINT(readability-non-const-parameter)
0179 {
0180   Double_t xx =x[0];
0181   Double_t f = par[0]*TMath::Gaus(xx,par[1],par[2]) + par[3]*TMath::Gaus(xx,2.0*par[1],sqrt(2)*par[2]); 
0182   //Double_t e = par[4]*TMath::Exp(-par[5]*xx);
0183   Double_t e = par[4]/(1.0+exp((xx-par[5])/par[6]));
0184   return f + e;
0185 }
0186 
0187 
0188 Double_t landau2(Double_t *x, Double_t *par) //NOLINT(readability-non-const-parameter)
0189 {
0190   Double_t xx =x[0];
0191   Double_t f = par[0]*TMath::Landau(xx,par[1],par[2]) + par[3]*TMath::Landau(xx,2.0*par[1],par[4]); 
0192   return f;
0193 }
0194 
0195 /*
0196 // Not used
0197 Double_t langaufun(Double_t *x, Double_t *par) // NOLINT(readability-non-const-parameter)
0198 {
0199   //Fit parameters:
0200   //par[0]=Width (scale) parameter of Landau density
0201   //par[1]=Most Probable (MP, location) parameter of Landau density
0202   //par[2]=Total area (integral -inf to inf, normalization constant)
0203   //par[3]=Width (sigma) of convoluted Gaussian function
0204   //
0205   //In the Landau distribution (represented by the CERNLIB approximation),
0206   //the maximum is located at x=-0.22278298 with the location parameter=0.
0207   //This shift is corrected within this function, so that the actual
0208   //maximum is identical to the MP parameter.
0209 
0210   // Numeric constants
0211   Double_t invsq2pi = 0.3989422804014;   // (2 pi)^(-1/2)
0212   Double_t mpshift  = -0.22278298;       // Landau maximum location
0213 
0214   // Control constants
0215   Double_t np = 100.0;      // number of convolution steps
0216   Double_t sc =   5.0;      // convolution extends to +-sc Gaussian sigmas
0217 
0218   // Variables
0219   Double_t xx;
0220   Double_t mpc;
0221   Double_t fland;
0222   Double_t sum = 0.0;
0223   Double_t xlow;
0224   Double_t xupp;
0225   Double_t step;
0226 
0227 
0228   // MP shift correction
0229   mpc = par[1] - mpshift * par[0];
0230 
0231   // Range of convolution integral
0232   xlow = x[0] - sc * par[3];
0233   xupp = x[0] + sc * par[3];
0234 
0235   step = (xupp-xlow) / np;
0236 
0237   // Convolution integral of Landau and Gaussian by sum
0238   for(double i=1.0; i<=np/2.0; i+=1.0)
0239   {
0240     xx = xlow + (i-0.5) * step;
0241     fland = TMath::Landau(xx,mpc,par[0]) / par[0];
0242     sum += fland * TMath::Gaus(x[0],xx,par[3]);
0243 
0244     xx = xupp - (i-.5) * step;
0245     fland = TMath::Landau(xx,mpc,par[0]) / par[0];
0246     sum += fland * TMath::Gaus(x[0],xx,par[3]);
0247   }
0248 
0249   return (par[2] * step * sum * invsq2pi / par[3]);
0250 }
0251 */
0252 
0253 // Read in the seeds
0254 void ReadSeeds(const std::string& sfname = "mipseeds.txt")
0255 {
0256   std::ifstream seedsfile( sfname );
0257   if (!seedsfile.is_open())
0258   {
0259     std::cout << "ERROR: Could not open seed file " << sfname << std::endl;
0260     return;
0261   }
0262   int pmt;
0263   for ( int ipmt=0; ipmt<128; ipmt++ )
0264   {
0265     seedsfile >> pmt;
0266     if ( pmt != ipmt )
0267     {
0268       std::cout << "ERROR, seedsfile is bad" << ipmt << "\t" << pmt << std::endl;
0269     }
0270     //seedsfile >> seed_threshold[pmt] >> seed_minrej[pmt] >> seed_natpeak[pmt] >> seed_maxrej[pmt] >> seed_qmax[pmt];
0271     for (int ipar=0; ipar<NPAR_BKGF; ipar++)
0272     {
0273       seedsfile >> seed_par[pmt][ipar];
0274     }
0275   }
0276 }
0277 
0278 // find the threshold
0279 // may also want to consider getting threshold from turn-on curves
0280 void FindThreshold(TH1 *horig, double& threshold, const int runtype = 0)
0281 {
0282   TH1 *h = (TH1*)horig->Clone("hnew");
0283   h->Smooth();
0284   threshold = 0.;
0285   double absolute_min = 10.;
0286   double absolute_max = 75.;    // max adc where the threshold could be (auau)
0287   if ( runtype==MBDRUNTYPE::PP200 )
0288   {
0289     absolute_max = 100.;
0290   }
0291   int absminbin = h->FindBin( absolute_min );
0292   int absmaxbin = h->FindBin( absolute_max );
0293   double absmaxval = h->GetBinContent( h->GetMaximumBin() );
0294   double maxval = 0.;     // max value found
0295   double prev_val = 0.;
0296   int maxbin = 0;         // bin for max value
0297   double maxratio = 0.;   // max ratio of bin/prev_bin
0298   int maxjumpbin = 0;     // where the max jump was
0299 
0300   for (int ibin=absminbin; ibin<=absmaxbin; ibin++)
0301   {
0302     double val = h->GetBinContent(ibin);
0303     if ( val > maxval )
0304     {
0305       maxval = val;
0306       maxbin = ibin;
0307     }
0308 
0309     if ( val>0. && prev_val>0. )
0310     {
0311       double ratio = val/prev_val;
0312       if ( val>(absmaxval*0.25) )
0313       {
0314         //std::cout << ibin << "\t" << ratio << std::endl;
0315         if ( ratio>maxratio )
0316         {
0317           maxratio = ratio;
0318           maxjumpbin = ibin;
0319         }
0320       }
0321     }
0322 
0323     prev_val = val;
0324   }
0325 
0326   if ( maxbin==absmaxbin )
0327   {
0328     // no exponential before mip peak, use max jump to find threshold
0329     // (Note: should raise gain for this channel if possible)
0330     double adc = h->GetBinCenter( maxjumpbin );
0331     double threshold_bin = h->FindBin( adc + 15. );
0332     threshold = h->GetBinLowEdge( threshold_bin );
0333   }
0334   else
0335   {
0336     // use max bin in threshold range
0337     threshold = h->GetBinLowEdge( maxbin );
0338   }
0339 
0340   delete h;
0341 
0342   //std::cout << threshold << std::endl;
0343 }
0344 
0345 void FindPeakRange(TH1 *horig, double& xmin, double& thispeak, double& xmax, const double threshold)
0346 {
0347   TH1 *h = (TH1*)horig->Clone("hnew");
0348   Double_t integ = h->Integral();
0349   if ( integ<12000. )
0350   {
0351     h->Rebin(4);
0352   }
0353   else if ( integ<24000. )
0354   {
0355     h->Rebin(2);
0356   }
0357   h->Smooth();
0358   
0359   // zero up to threshold
0360   int threshbin = h->FindBin(threshold);
0361   for (int ibin=1; ibin<threshbin; ibin++)
0362   {
0363     h->SetBinContent(ibin,0.);
0364   }
0365 
0366   // find mip peak
0367   Double_t binwid = h->GetBinWidth(1);
0368   Double_t ymax{0.};
0369   Int_t peakbin{0};
0370 
0371   Double_t temp_threshold = threshold;
0372   thispeak = temp_threshold;
0373 
0374   while ( std::abs(thispeak-temp_threshold) < (5.0*binwid) )
0375   {
0376     h->SetBinContent( peakbin, 0. );
0377     ymax = h->GetMaximum();
0378     peakbin = h->GetMaximumBin();
0379     thispeak = h->GetBinCenter( peakbin );
0380 
0381     if ( std::abs(thispeak-temp_threshold) < (5.0*binwid) )
0382     {
0383       temp_threshold = thispeak;
0384     }
0385     
0386     if ( verbose>=5 )
0387     {
0388       std::cout << "peakfind thresh x_at_peak peakval\t" << temp_threshold << "\t" << thispeak << "\t" << ymax << "\t" << peakbin << std::endl;
0389     }
0390 
0391     /*
0392     h->GetXaxis()->SetRangeUser(62,300);
0393     h->Draw();
0394     gPad->SetGridx(1);
0395     gPad->SetGridy(1);
0396     gPad->Modified();
0397     gPad->Update();
0398     std::string junk;
0399     cin >> junk;
0400     */
0401   }
0402 
0403   delete h;
0404 
0405   // find xmin (min between threshold and peak)
0406   h = (TH1*)horig->Clone("hnew");
0407   h->Smooth();
0408   int nbinsx = h->GetNbinsX();
0409   for (int ibin=1; ibin<=nbinsx; ibin++)
0410   {
0411     if ( ibin<threshbin || ibin>peakbin )
0412     {
0413       h->SetBinContent( ibin, 1e12 );
0414     }
0415   }
0416 
0417   xmin = h->GetBinLowEdge( h->GetMinimumBin() );
0418   if ( xmin==threshold )
0419   {
0420     xmin += binwid;     // no bkg b4 mip situation
0421   }
0422 
0423   Double_t peakmindiff = thispeak - xmin;
0424   xmax = 2*thispeak + 2.0*peakmindiff;  // 1.0 for pp
0425 
0426   delete h;
0427 }
0428 
0429 
0430 //void pro_recal_mbd_mip(const std::string &tfname = "DST_MBDUNCAL-00020869-0000.root", const int pass = 3)
0431 void pro_recal_mbd_mip(const int runnumber, const int pass = 3)
0432 {
0433   //std::cout << "tfname " << tfname << std::endl;
0434   gStyle->SetOptFit(1111);
0435   gStyle->SetOptStat(111111);
0436 
0437   // set up run-dependent settings
0438   // type0: auau200
0439   // type1: pp200
0440   // method0:  TSpectrum bkg + 2 gaus fit
0441   // method1:  expopowerlaw + 2 skgaus fit
0442 //  int runnumber = get_runnumber(tfname);
0443   //std::pair<int, int> runseg = Fun4AllUtils::GetRunSegment(tfname);
0444   //int runnumber = runseg.first;
0445   int type = get_runtype( runnumber );
0446   int method = 1;
0447   // NOLINTBEGIN(bugprone-branch-clone)
0448   if ( type == MBDRUNTYPE::AUAU200 )
0449   {
0450     method = 0;
0451   }
0452   else if ( type == MBDRUNTYPE::PP200 )
0453   {
0454     method = 1;
0455 
0456     // Read in Seeds File
0457     ReadSeeds();
0458   }
0459   else if ( type == MBDRUNTYPE::OO200 )
0460   {
0461     method = 0;
0462   }
0463   // NOLINTEND(bugprone-branch-clone)
0464   std::cout << "pro_recal_mbd_mip(), type method " << type << " " << method << std::endl;
0465 
0466   // make results directory
0467   TString dir = "results/";
0468   dir += runnumber;
0469   dir += "/";
0470   TString name = "mkdir -p ";
0471   name += dir;
0472   gSystem->Exec( name );
0473 
0474   // Read in TFile with h_q
0475   name = dir;
0476   name += "calmbdpass2.3_q-";
0477   name += runnumber;
0478   name += ".root";
0479   TFile *oldfile = TFile::Open(name,"READ");
0480 
0481   if ( (oldfile == nullptr) || oldfile->IsZombie() )
0482   {
0483     std::cout << "Error: bad tfile " << name << std::endl;
0484     return;
0485   }
0486 
0487   TString title;
0488   for (int ipmt=0; ipmt<NUM_PMT; ipmt++)
0489   {
0490     name = "h_q"; name += ipmt;
0491     title = "q"; title += ipmt;
0492     oldfile->GetObject(name, h_q[ipmt]);
0493     h_q[ipmt]->SetMarkerSize(0.6);
0494 
0495     /*
0496     if ( type == MBDRUNTYPE::AUAU200 )
0497     {
0498       //h_q[ipmt]->Rebin(2);
0499     }
0500     else if ( type == MBDRUNTYPE::PP200 )
0501     {
0502       //h_q[ipmt]->Rebin(4);  // b-off
0503       //h_q[ipmt]->Rebin(2);
0504     }
0505     */
0506 
0507     name = "h_tq"; name += ipmt;
0508     title = "tq"; title += ipmt;
0509     oldfile->GetObject(name,h_tq[ipmt]);
0510   }
0511 
0512   // Create new TFile
0513   name = dir; 
0514   name += "recalmbd_pass";
0515   name += pass;
0516   name += ".root";
0517   std::cout << name << std::endl;
0518 
0519   TFile *savefile = new TFile(name,"RECREATE");
0520 
0521   // Load in calib constants
0522 
0523   TCanvas *ac[100];
0524   int cvindex = 0;
0525 
0526   //q
0527   ac[cvindex] = new TCanvas("cal_q","q",425*1.5,550*1.5);
0528   if ( pass>0 )
0529   {
0530     ac[cvindex]->Divide(1,2);
0531     ac[cvindex]->cd(1);
0532   }
0533 
0534   std::ofstream cal_mip_file;
0535   TString calfname;
0536   if ( pass==3 ) 
0537   {
0538     calfname = dir;
0539     calfname += "mbd_qfit.calib";
0540     cal_mip_file.open( calfname );
0541     std::cout << "Writing to " << calfname << std::endl;
0542   }
0543 
0544   // Fit ranges
0545   // Run23AuAu
0546   qmin = 25.;
0547   //qmax = 1600;
0548   qmax = 2000;
0549 
0550   if ( type==MBDRUNTYPE::PP200 )
0551   {
0552     std::cout << "setting up for pp200" << std::endl;
0553     //qmin = 200;
0554     //qmax = 10000;       // Run24pp boff
0555     //qmin = 100;
0556     //qmin = 50;
0557     //qmin = 10;
0558     //qmax = 2000;       // Run24pp bon
0559     qmin = 20;
0560     qmax = 4000;       // Run25pp bon
0561   }
0562   else if ( type==MBDRUNTYPE::SIMAUAU200 || type==MBDRUNTYPE::SIMPP200 )
0563   {
0564     qmin = 0.25;
0565     qmax = 6.;
0566   }
0567 
0568   // Set up output pdf to save plots
0569   TString pdfname = dir; pdfname += "calmbdpass2."; pdfname += pass; pdfname += "_mip-"; pdfname += runnumber; pdfname += ".pdf";
0570   std::cout << pdfname << std::endl;
0571   ac[cvindex]->Print( pdfname + "[" );
0572 
0573   // output bkgfit save file
0574   TString savefitsname = dir;
0575   savefitsname += "savefitspass2."; savefitsname += pass; savefitsname += "_mip-";
0576   savefitsname += runnumber; savefitsname += ".txt";
0577   std::ofstream savefits(savefitsname);
0578 
0579   for (int ipmt=0; ipmt<NUM_PMT; ipmt++)
0580   {
0581     ac[cvindex]->cd(1);
0582     h_q[ipmt]->Draw();
0583 
0584     if ( verbose>9 && ipmt!=0 ) continue;  // check sgl channel
0585     if (pass>0)
0586     {
0587       double threshold{0.};
0588       FindThreshold( h_q[ipmt], threshold, type );
0589       std::cout << "threshold " << ipmt << "\t" << threshold << std::endl;
0590       h_q[ipmt]->GetXaxis()->SetRangeUser( threshold, qmax );
0591       h_q[ipmt]->Sumw2();
0592 
0593       FindPeakRange( h_q[ipmt], minrej, peak, maxrej, threshold );  // works only in pp for now
0594       qmin = threshold;
0595       n_at_peak = h_q[ipmt]->GetBinContent( h_q[ipmt]->FindBin( peak ) );
0596 
0597       std::cout << "peak range\t" << minrej << "\t" << peak << "\t" << maxrej << "\t" << qmin << "\t" << qmax << std::endl;
0598       savefits << ipmt << "\t" << threshold << "\t" << minrej << "\t" << n_at_peak << "\t" << maxrej << "\t" << qmax;
0599 
0600       double seedmean = peak;
0601       double seedsigma = 20.;
0602 
0603       if ( method==0 )
0604       {
0605         TSpectrum s{};
0606         h_bkg[ipmt] = s.Background( h_q[ipmt] );
0607         h_bkg[ipmt]->SetLineColor(2);
0608 
0609         h_mip[ipmt] = (TH1*)h_q[ipmt]->Clone();
0610         name = h_q[ipmt]->GetName(); name.ReplaceAll("q","mip");
0611         h_mip[ipmt]->SetName( name );
0612         h_mip[ipmt]->SetTitle( name );
0613         h_mip[ipmt]->SetLineColor( 4 );
0614         h_mip[ipmt]->Add( h_bkg[ipmt], -1.0 );
0615 
0616         seedmean = h_mip[ipmt]->GetBinCenter( h_mip[ipmt]->GetMaximumBin() );
0617         seedsigma = 0.2*seedmean;
0618       }
0619       else if ( method==1 )
0620       {
0621         h_bkg[ipmt] = (TH1*)h_q[ipmt]->Clone();
0622         name = h_q[ipmt]->GetName(); name.ReplaceAll("q","bkg");
0623         h_bkg[ipmt]->SetName( name );
0624         h_bkg[ipmt]->SetTitle( name );
0625         h_bkg[ipmt]->SetLineColor(2);
0626 
0627         // Fit background
0628         name = "bkgf"; name += ipmt;
0629         bkgf[ipmt] = new TF1(name,expopowerlaw,qmin,qmax,5);
0630         bkgf[ipmt]->SetNpx(1000);
0631         bkgf[ipmt]->SetParameter(0,seed_par[ipmt][0]*n_at_peak);
0632         bkgf[ipmt]->SetParameter(1,seed_par[ipmt][1]);
0633         bkgf[ipmt]->SetParameter(2,seed_par[ipmt][2]);
0634         bkgf[ipmt]->SetParameter(3,seed_par[ipmt][3]*n_at_peak);
0635         bkgf[ipmt]->SetParameter(4,seed_par[ipmt][4]);
0636         bkgf[ipmt]->SetLineColor(3);
0637         h_bkg[ipmt]->GetXaxis()->SetRangeUser(threshold,qmax);
0638         h_bkg[ipmt]->Draw();
0639         //h_bkg[ipmt]->Fit(bkgf[ipmt],"MR");
0640         h_bkg[ipmt]->Fit(bkgf[ipmt],"R");
0641 
0642         gPad->SetLogy(1);
0643         gPad->Modified();
0644         gPad->Update();
0645 
0646         if (verbose ) // after bkg fit
0647         {
0648           std::string junk2;
0649           std::cin >> junk2;
0650         }
0651 
0652         // get mip histogram
0653         h_mip[ipmt] = (TH1*)h_q[ipmt]->Clone();
0654         name = h_q[ipmt]->GetName(); name.ReplaceAll("q","mip");
0655         h_mip[ipmt]->SetName( name );
0656         h_mip[ipmt]->SetTitle( name );
0657 
0658 
0659         // double orig_minrej = minrej;
0660         // double orig_maxrej = maxrej;
0661         minrej = 0.;
0662         maxrej = 0.;
0663         h_mip[ipmt]->Add( bkgf[ipmt], -1.0 );
0664         h_bkg[ipmt]->Reset();
0665         h_bkg[ipmt]->Add(bkgf[ipmt]);
0666         h_q[ipmt]->Draw();
0667         h_bkg[ipmt]->Draw("same");
0668       }
0669 
0670       ac[cvindex]->cd(2);
0671      
0672       // Fit the mip peak after background subtraction
0673       name = "mipfit"; name += ipmt;
0674 
0675       // Two gaussian fit
0676       //mipfit[ipmt] = new TF1(name,gaus2,qmin,qmax,4);
0677       mipfit[ipmt] = new TF1(name,skgaus2,qmin,qmax,5);
0678       mipfit[ipmt]->SetNpx(1000);
0679       mipfit[ipmt]->SetLineColor(4);
0680       mipfit[ipmt]->SetParNames("ampl","mean","sigma","skew","ampl2");
0681 
0682       /*
0683       if ( type==MBDRUNTYPE::SIMAUAU200 )
0684       {
0685         seedsigma = 0.2;
0686       }
0687       else if ( type==MBDRUNTYPE::PP200 )
0688       {
0689         seedsigma = seedmean*(116./719.);  // b-on
0690         //seedsigma = 50;  // b-on
0691         //seedsigma = 200;  // b-off
0692       }
0693       */
0694 
0695       // for gaus2
0696       double seed_ampl = 5.0*h_mip[ipmt]->GetMaximum();
0697       mipfit[ipmt]->SetParameter( 0, seed_ampl );
0698       mipfit[ipmt]->SetParameter( 1, seedmean );
0699       mipfit[ipmt]->SetParameter( 2, seedsigma );
0700       mipfit[ipmt]->SetParameter( 3, 0.1 );
0701       if ( type==MBDRUNTYPE::PP200 )
0702       {
0703         mipfit[ipmt]->SetParameter( 4, seed_ampl*0.1 );
0704         mipfit[ipmt]->FixParameter(4,0.);
0705       }
0706       else if ( type==MBDRUNTYPE::AUAU200 )
0707       {
0708         mipfit[ipmt]->SetParameter( 4, seed_ampl*0.2 );
0709       }
0710 
0711       std::cout << "MIPFIT SEEDS " << seed_ampl << "\t" << seedmean << "\t" << seedsigma << std::endl;
0712 
0713       //h_mip[ipmt]->Fit( mipfit[ipmt], "RM" );
0714       h_mip[ipmt]->Fit( mipfit[ipmt], "R" );
0715       gPad->Modified();
0716       gPad->Update();
0717 
0718       if ( verbose ) // after mip fit
0719       {
0720         std::string junk2;
0721         std::cin >> junk2;
0722       }
0723 
0724       // Now do total re-fit (after we have gotten seeds for mip and background)
0725       if ( method==1 )
0726       {
0727         ac[cvindex]->cd(1);
0728         name = "totfit"; name += ipmt;
0729         minrej = 0.;
0730         maxrej = 0.;
0731         //totfit[ipmt] = new TF1(name,expopowerlawgaus2,qmin,qmax,9);
0732         totfit[ipmt] = new TF1(name,expopowerlawskgaus2,qmin,qmax,10);
0733         totfit[ipmt]->SetNpx(1000);
0734         totfit[ipmt]->SetLineColor(4);
0735         totfit[ipmt]->SetParNames("plaw_ampl", "plaw_alpha", "plaw_power", "expo_ampl", "expo_power",
0736             "gaus_ampl", "gaus_mean", "gaus_sigma", "gaus_skew", "gaus2_ampl");
0737         for (int ipar=0; ipar<5; ipar++)
0738         {
0739           totfit[ipmt]->SetParameter(ipar,bkgf[ipmt]->GetParameter(ipar));
0740         }
0741         for (int ipar=5; ipar<totfit[ipmt]->GetNumberFreeParameters(); ipar++)
0742         {
0743           totfit[ipmt]->SetParameter(ipar,mipfit[ipmt]->GetParameter(ipar-5));
0744         }
0745 
0746         totfit[ipmt]->SetParameter(7,std::abs(totfit[ipmt]->GetParameter(7)));
0747         //totfit[ipmt]->SetParLimits(9,0.,1e12);
0748         totfit[ipmt]->FixParameter(9,0.);
0749 
0750         h_q[ipmt]->Fit( totfit[ipmt], "RM" );
0751 
0752         double redchi2 = totfit[ipmt]->GetChisquare()/totfit[ipmt]->GetNDF();
0753         if ( redchi2>5.0 )
0754         {
0755           totfit[ipmt]->SetParameter(0,seed_par[ipmt][0]*n_at_peak);
0756           totfit[ipmt]->SetParameter(1,seed_par[ipmt][1]);
0757           totfit[ipmt]->SetParameter(2,seed_par[ipmt][2]);
0758           totfit[ipmt]->SetParameter(3,seed_par[ipmt][3]*n_at_peak);
0759           totfit[ipmt]->SetParameter(4,seed_par[ipmt][4]);
0760           totfit[ipmt]->SetParameter(5,seed_ampl );
0761           totfit[ipmt]->SetParameter(6,seedmean );
0762           totfit[ipmt]->SetParameter(7,seedsigma );
0763           totfit[ipmt]->SetParameter(8,seed_par[ipmt][8]);
0764           h_q[ipmt]->Fit( totfit[ipmt], "RM" );
0765         }
0766         gPad->Modified();
0767         gPad->Update();
0768         if (verbose)
0769         {
0770           std::string junk;
0771           std::cout << "? ";
0772           std::cin >> junk;
0773         }
0774 
0775         for (int ipar=0; ipar<5; ipar++)
0776         {
0777           bkgf[ipmt]->SetParameter( ipar, totfit[ipmt]->GetParameter( ipar ));
0778         }
0779         for (int ipar=5; ipar<totfit[ipmt]->GetNumberFreeParameters(); ipar++)
0780         {
0781           mipfit[ipmt]->SetParameter( ipar-5, totfit[ipmt]->GetParameter( ipar ));
0782           mipfit[ipmt]->SetParError( ipar-5, totfit[ipmt]->GetParError( ipar ));
0783         }
0784 
0785         // get h_mip again
0786         h_mip[ipmt]->Reset();
0787         //h_mip[ipmt]->Clear();
0788         h_mip[ipmt]->ResetStats();
0789         h_mip[ipmt]->Add( h_q[ipmt] );
0790         h_mip[ipmt]->Add( bkgf[ipmt], -1.0 );
0791 
0792         //h_mip[ipmt]->Draw();
0793         h_mip[ipmt]->Fit(mipfit[ipmt],"R");
0794         //mipfit[ipmt]->Draw("same");
0795       }
0796 
0797       double integ = mipfit[ipmt]->GetParameter(0);
0798       double best_peak = mipfit[ipmt]->GetParameter(1);
0799       double width = mipfit[ipmt]->GetParameter(2);
0800       double integerr = mipfit[ipmt]->GetParError(0);
0801       double best_peakerr = mipfit[ipmt]->GetParError(1);
0802       double widtherr = mipfit[ipmt]->GetParError(2);
0803       double chi2 = mipfit[ipmt]->GetChisquare();
0804       double ndf = mipfit[ipmt]->GetNDF();
0805       if ( method==1 )
0806       {
0807         double ORIG_chi2 = chi2;
0808         chi2 = h_mip[ipmt]->Chisquare(mipfit[ipmt],"R"); // from re-fit
0809         std::cout << "CHI2COMPARE " << ipmt << "\t" << chi2 << "\t" << ORIG_chi2 << "\t" << ORIG_chi2-chi2 << std::endl;
0810         mipfit[ipmt]->SetChisquare( chi2 );
0811       }
0812 
0813       cal_mip_file << ipmt << "\t" << integ << "\t" << best_peak << "\t" << std::abs(width) << "\t"
0814         << integerr << "\t" << best_peakerr << "\t" << widtherr << "\t"
0815         << chi2/ndf << std::endl;
0816       std::cout << ipmt << "\t" << integ << "\t" << best_peak << "\t" << width << "\t"
0817         << integerr << "\t" << best_peakerr << "\t" << widtherr << "\t"
0818         << chi2/ndf << std::endl;
0819 
0820       if ( method==0 )
0821       {
0822         for (int ipar=0; ipar<mipfit[ipmt]->GetNumberFreeParameters(); ipar++)
0823         {
0824           if ( ipar==0 || ipar==4 ) // scale all the amplitude parameters
0825           {
0826             savefits << "\t" << mipfit[ipmt]->GetParameter(ipar)/n_at_peak;
0827           }
0828           else
0829           {
0830             savefits << "\t" << mipfit[ipmt]->GetParameter(ipar);
0831           }
0832         }
0833         savefits << std::endl;
0834       }
0835       else if ( method==1 )
0836       {
0837         for (int ipar=0; ipar<totfit[ipmt]->GetNumberFreeParameters(); ipar++)
0838         {
0839           if ( ipar==0 || ipar==3 || ipar==5 || ipar==9 ) // scale all the amplitude parameters
0840           {
0841             savefits << "\t" << totfit[ipmt]->GetParameter(ipar)/n_at_peak;
0842           }
0843           else
0844           {
0845             savefits << "\t" << totfit[ipmt]->GetParameter(ipar);
0846           }
0847         }
0848         savefits << std::endl;
0849 
0850         // Get full fit
0851         h_bkg[ipmt]->Reset();
0852         h_bkg[ipmt]->Add(bkgf[ipmt]);
0853       }
0854 
0855       h_bkgmip[ipmt] = (TH1*)h_q[ipmt]->Clone();
0856       name = h_q[ipmt]->GetName(); name.ReplaceAll("q","bkgmip");
0857       h_bkgmip[ipmt]->SetName( name );
0858       h_bkgmip[ipmt]->SetTitle( name );
0859       h_bkgmip[ipmt]->Reset();
0860       h_bkgmip[ipmt]->Add(h_bkg[ipmt]);
0861       //h_bkgmip[ipmt]->Sumw2();
0862       h_bkgmip[ipmt]->Add( mipfit[ipmt] );
0863       h_bkgmip[ipmt]->SetLineColor( kCyan );
0864 
0865       // Now draw the full dist, plus fit
0866       ac[cvindex]->cd(1);
0867       gPad->SetLogy(1);
0868       h_q[ipmt]->GetXaxis()->SetRangeUser( qmin, qmax );
0869       //h_q[ipmt]->SetMinimum(10.);
0870       h_q[ipmt]->Draw();
0871       h_bkg[ipmt]->Draw("histsame");
0872       h_bkgmip[ipmt]->Draw("histsame");
0873       TPaveStats *st = (TPaveStats*)h_q[ipmt]->FindObject("stats");
0874       if ( st )
0875       {
0876         st->SetX1NDC(0.6); // X start position (0 to 1)
0877         st->SetY1NDC(0.4); // Y start position (0 to 1)
0878         st->SetX2NDC(0.99); // X end position
0879         st->SetY2NDC(0.99); // Y end position
0880       }
0881 
0882       gPad->Modified();
0883       gPad->Update();
0884 
0885       ac[cvindex]->cd(2);
0886       h_mip[ipmt]->Draw();
0887       if ( type==MBDRUNTYPE::PP200 )
0888       {
0889         h_mip[ipmt]->GetXaxis()->SetRangeUser(qmin,1200);
0890         if ( mipfit[ipmt]->GetParameter(1)>600. )
0891         {
0892           h_mip[ipmt]->GetXaxis()->SetRangeUser(qmin,1400);
0893         }
0894       }
0895       else if ( type==MBDRUNTYPE::AUAU200 )
0896       {
0897         h_mip[ipmt]->GetXaxis()->SetRangeUser(qmin,1000);
0898       }
0899       gPad->SetGridy(1);
0900       gPad->Modified();
0901       gPad->Update();
0902 
0903       if (verbose)
0904       {
0905         std::string junk;
0906         std::cout << "? ";
0907         std::cin >> junk;
0908       }
0909 
0910       title = "h_qfit"; title += ipmt;
0911       //std::cout << pdfname << " " << title << std::endl;
0912       ac[cvindex]->Print( pdfname, title );
0913     }
0914 
0915 
0916   }
0917 
0918   //savefits.write();
0919   savefits.close();
0920 
0921   ac[cvindex]->Print( pdfname + "]" );
0922   ++cvindex;
0923 
0924   if ( pass==3 )
0925   {
0926     cal_mip_file.close();
0927 
0928     // Convert to CDB format
0929     MbdCalib mcal;
0930     mcal.Download_Gains( calfname.Data() );
0931     calfname.ReplaceAll(".calib",".root");
0932     mcal.Write_CDB_Gains( calfname.Data() );
0933   }
0934 
0935   for (auto & hist: h_q)
0936   {
0937     hist->Write();
0938   }
0939   savefile->Write();
0940   savefile->Close();
0941 }
0942 #endif