#include "TPeakFit.h"
#include "TStopwatch.h"
ClassImp(TPeakFit)

int   _NF_ = 0;
int   _FIRST_ = 0;
TH1*  _HIST_=0;
TF1*  _F_[MAXFUNC1];
float _Y_[MAXFUNC1];
int   _I0_;
int   _I1_;
bool  _SAMEWIDTH_;
float _CHI2_;
float _NP_;


///////////////////////////////////////////////////
void _CHI_(Int_t& npar, Double_t* gin, Double_t &f, Double_t *par, Int_t iflag)
{
  int i,n,s,ss = 0;
  Double_t chi = 0;
  float X,Y,EY,EX,F,N=0;
  float W = 0;

  for(i=0;i<_NF_;i++)
  {
    if(_F_[i]) n = _F_[i]->GetNpar(); else n = 0;
    for(s=0;s<n;s++)
    {
      if(_SAMEWIDTH_)
      {
        if(s==2) // width
        {
          if(i==_FIRST_) W = par[ss+s];
          par[ss+s] = W;
        }
      }
      if(_F_[i]) _F_[i]->SetParameter(s,par[ss+s]);
    }
    ss+=n;
  }
  for(i = 0;i<(_I1_-_I0_);i++)
  {
    X  = _HIST_->GetBinCenter(_I0_+i);
    Y  = _HIST_->GetBinContent(_I0_+i);
    EY = _HIST_->GetBinError(_I0_+i);
    EX = _HIST_->GetBinWidth(_I0_+i)/2.0;
    if(EY<=0) EY=1;
    F  = 0;
    for(n=0;n<_NF_;n++) if(_F_[n]) F+=_F_[n]->Eval(X);
    chi += (Y-F)*(Y-F)/(EY*EY+EX*EX);
    N++;
  }
  f = chi;
  _NP_ = N;
  _CHI2_ = f;
  return;
}

TPeakFit::TPeakFit():TObject()
{
  mFunctions = new TContainer();
  mFunctions->empty();
  mHist = NULL;
  mBack = NULL;
  mNP = 0;
  mMaxBackDegree = 1000;
  setPeakVar(7);
  setWidthVar(7);
  setMinArea(0.1);
  setMaxArea(10);
  setMinAssym(0.1);
  setMaxAssym(2.0);
  setSameWidth(false);
  setAssymOnOff(false);
  setIndependentBack(false);
  setBackVar(0.2);
  mSum = NULL;
}
TPeakFit::~TPeakFit()
{
  delete mFunctions;
  if(mSum) delete mSum;
}
void TPeakFit::setBackground(int N,float* x,float* y)
{
  if(mBack) delete mBack;
  mBack = NULL;
  if(N<=0) return;
  mBack = new TGraph(N,x,y);
  mMaxBackDegree = N;
}
void TPeakFit::addPeak(float amp, float avg, float sig, float ass)
{
  mNP++;
  char name[30];
  sprintf(name,"Peak%03d",mNP);
  //TF1* f = new TF1(name,
  //                 "[0]*exp(-0.5*(x-[1])*(x-[1])/([2]*[2]*([3]*[3]*(x<=[1])+1*(x>[1]))))"
  //                 ,mFitMin,mFitMax);
  TF1* f = new TF1(name,
                   "[0]*(exp(-0.5*((x-[1])/([2]*[3]))*((x-[1])/([2]*[3])))*(x<=[1])+exp(-0.5*((x-[1])/[2])*((x-[1])/[2]))*(x>[1]))"
                   ,mFitMin,mFitMax);
  f->SetParameters(amp,avg,sig,ass);
  mFunctions->remove(name);
  mFunctions->add(f);
  return;
}
TF1* TPeakFit::getPeak(int p)
{
  char name[30];
  sprintf(name,"Peak%03d",p);
  return (TF1*)mFunctions->get(name);
}
void TPeakFit::fitBack()
{
  int i;
  int N;
  float x[2],y[2];
  if(!mHist) return;
  if(mBackDegree<0)
  {
    TF1 *f = new TF1("back","0",mFitMin,mFitMax);
    mFunctions->remove("back");
    mFunctions->add(f);
    return;
  }

  if(mBackDegree>=mMaxBackDegree) mBackDegree=mMaxBackDegree-1;

  if(!mBack &&  mBackDegree>=0) // no background defined by the user
  {
    if(mBackDegree>1) mBackDegree = 1;
    N = 2;
    x[0] = mFitMin;
    x[1] = mFitMax;
    y[0] = mHist->GetBinContent(mHist->FindBin(x[0]));
    y[1] = mHist->GetBinContent(mHist->FindBin(x[1]));
    //cout <<x[0]<<"  "<<x[1]<<"  "<<y[0]<<"  "<<y[1]<<endl;
    setBackground(N,x,y);
  }
  char name[15];
  sprintf(name,"pol%d",mBackDegree);
  TF1 *f = new TF1("back",name,mFitMin,mFitMax);
  if(mBack) mBack->Fit(f,"RQN");
  mFunctions->remove("back");
  mFunctions->add(f);
  return;
}
void TPeakFit::fit()
{
  int i,j,npar,s,n,ierr;
  float p,pmin,pmax;
  int B = -1;
  Double_t arg[10];
  Double_t P,E;
  if(!mHist) return;

  fitBack();

  _NF_ = 0;
  npar = 0;
  for(i=0;i<MAXFUNC1;i++) _F_[i] = NULL;
  if(getBack()) {_F_[_NF_] = getBack(); npar+=_F_[_NF_]->GetNpar(); B = _NF_; _NF_++; }
  bool firstPeak = false;
  for(i = 0;i<mNP;i++) if(getPeak(i+1))
  {
    _F_[_NF_] = getPeak(i+1);
    npar+=_F_[_NF_]->GetNpar();
    if(!firstPeak) {_FIRST_ = _NF_; firstPeak = true;}
    _NF_++;
  }
  mNP = _NF_;
  _SAMEWIDTH_ = mSameWid;

  _I0_ = mHist->FindBin(mFitMin);
  _I1_ = mHist->FindBin(mFitMax);
  _HIST_ = mHist;

  TMinuit *m = new TMinuit(npar);
  arg[0] = -1;
  m->mnexcm("SET PRI",arg,1,ierr);
  m->mnexcm("SET NOWARNINGS",arg,1,ierr);
  m->mnexcm("SET ERR",arg,1,ierr);
  m->SetFCN(_CHI_);
  s = 0;
  for(i=0;i<_NF_;i++)
  {
    if(_F_[i]) n = _F_[i]->GetNpar(); else n = 0;
    for(j=0;j<n;j++)
    {
      if(_F_[i]) p = _F_[i]->GetParameter(j); else p = 0;
      if (j==0 && i!=B) {pmin = mMinArea*p; pmax = mMaxArea*p;} // area
      if (j==1 && i!=B) {pmin = p-mPeakVar; pmax = p+mPeakVar;} // peak position
      if (j==2 && i!=B) {pmin = p-mWidVar;  pmax = p+mWidVar;}  // sigma
      if (j==3 && i!=B) {pmin = mMinAssym;  pmax = mMaxAssym;}  // assymetry
      if (j==3 && !mAssym && i!=B) { p = 1; pmin = 1;  pmax = 1;}; // turn off assymetry
      if (i==B && p>0) { pmin = (1-mBackVar)*p; pmax = (1+mBackVar)*p; }
      if (i==B && p<0) { pmin = (1+mBackVar)*p; pmax = (1-mBackVar)*p; }
      if (i==B && p==0){ pmin = -mBackVar; pmax = mBackVar; }
      if (i==B && mBackMode) //fixed background
      {
        pmin = p;
        pmax = p;
      }
      m->mnparm(s+j,"",p,(pmax-pmin)/5,pmin,pmax,ierr);
    }
    s+=n;
  }
  arg[0] = 500;
  arg[1] = 1;
  m->mnexcm("MIG",arg,2,ierr);

  // moving parameters back to function
  s = 0;
  for(i=0;i<_NF_;i++)
  {
    if(_F_[i]) n = _F_[i]->GetNpar(); else n = 0;
    for(j=0;j<n;j++)
    {
      m->GetParameter(s+j,P,E);
      //cout <<"par "<<s+j<<"  P = "<<P<<"  E = "<<E<<endl;
      if(_F_[i])
      {
        _F_[i]->SetParameter(j,P);
        _F_[i]->SetParError(j,E);
        if(mSameWid && _F_[i]!=getBack() && j==2)
        {
          _F_[i]->SetParameter(j,_F_[_FIRST_]->GetParameter(j));
          _F_[i]->SetParError(j,_F_[_FIRST_]->GetParError(j));
        }
      }
    }
    s+=n;
  }

  mChi = _CHI2_;
  mNDF = _NP_ - m->GetNumFreePars();
  //cout <<"Chi = "<<mChi<<"  NDF = "<<mNDF<<"  Chi/NDF = "<<mChi/mNDF<<endl;
  print();
}
void TPeakFit::draw(TVirtualPad* pad)
{
  if(!mHist) return;
  if(pad) pad->cd();
  int i,j,npar,s,n,ierr;
  float p,pmin,pmax;
  int i0,i1,nb;
  if(mSum) { delete mSum; mSum = NULL;}
  i0 = mHist->FindBin(mFitMin);
  i1 = mHist->FindBin(mFitMax);
  nb = (i1-i0)*5;
  mSum = new TH1F("totalFit","",nb,mFitMin,mFitMax);
  gROOT->RecursiveRemove(mSum);

  if(getBack())
  {
    getBack()->SetLineWidth(2);
    getBack()->SetLineColor(3);
    getBack()->Draw("same");
    mSum->Add(getBack(),1);
  }
  for(i = 0;i<mNP;i++) if(getPeak(i+1))
  {
    getPeak(i+1)->SetLineWidth(2);
    getPeak(i+1)->SetLineColor(4);
    getPeak(i+1)->Draw("same");
    mSum->Add(getPeak(i+1),1);
  }

  mSum->SetLineColor(2);
  mSum->SetLineWidth(2);
  mSum->Draw("sameL");
  if(pad) pad->Update();
}
void TPeakFit::print()
{
  int n,i,j;
  TString l;
  Double_t p[10],e[10],p1[10],p2[10];
  float a,a1,a2,b;
  char line[100];
  log(10,"\n--------------------------------------------------------------");
  log(10,"Results from last fit");
  log(10,"");
  log(10,"Number of peaks = %d  Background type = %d",mNP,mBackDegree);
  log(10,"Fit Min = %f  Fit Max = %f",mFitMin,mFitMax);
  log(10,"Chi = %f  NDF = %f  Chi/NDF = %f",mChi,mNDF,mChi/mNDF);
  log(10,"");
  if(getBack())
  {
    TF1 *f = getBack();
    log(10,"Background parameters");
    n = f->GetNpar();
    for(i=0;i<n;i++)
      log(10,"P%02d      = %7.4e +- %7.4e",i,f->GetParameter(i),f->GetParError(i));
  }
  log(10,"");
  log(10,"Peak parameters");
  for(j=0;j<mNP;j++) if(getPeak(j+1))
  {
    log(10,"-------- Peak number %d",j);
    TF1 *f = getPeak(j+1);
    n = f->GetNpar();
    for(i=0;i<n;i++)
    {
      if(i==0) l = "AMPLITUDE";
      if(i==1) l = "PEAK POS ";
      if(i==2) l = "WIDTH    ";
      if(i==3) l = "ASYMMETRY";
      p[i] = f->GetParameter(i);
      e[i] = f->GetParError(i);
      p1[i] = p[i]+e[i];
      p2[i] = p[i]-e[i];
      log(10,"%s = %7.4e +- %7.4e",l.Data(),p[i],e[i]);
    }
    l = "Integral ";
    a2 = f->Integral(mFitMin,mFitMax,p2);
    a1 = f->Integral(mFitMin,mFitMax,p1);
    a  = f->Integral(mFitMin,mFitMax,p);
    log(10,"%s = %7.4e +- %7.4e",l.Data(),a,fabs(a2-a1)/2.);
    if(mHist)
    {
      b = mHist->GetBinWidth(mHist->FindBin(p[1]));
      l = "Counts   ";
      log(10,"%s = %7.4e +- %7.4e (histogram bin width = %5.2e)",l.Data(),a/b,fabs(a2-a1)/(2.*b),b);
    }
  }
}


ROOT page - Class index - Class Hierarchy - Top of the page

This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.