#include "EEQuickPi0Finder.h"

#include <iostream>
#include <TString.h>
#include <TF1.h>
#include <TCanvas.h>
#include <TPad.h>
#include <TGaxis.h>
#include <TLine.h>

#include "EEezPi0nCandidate.h"
#include "EEezCluster.h"
#include "StEEmcUtil/EEfeeRaw/EEmcEventHeader.h"
#include "StEEmcUtil/EEmcSmdMap/EEmcSmdMap.h"
#include "StEEmcUtil/EEmcGeom/EEmcGeomDefs.h"

ClassImp(EEQuickPi0Finder);
ClassImp(EEPi0TreeItem); 

/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////

 EEQuickPi0Finder::EEQuickPi0Finder( const Char_t *name )
  : TDirectory(name,"EEMC Quick Pi0 Finder") 
{
  // Class Constructor
  mEzUtils = EEezUtils::instance();
  mSmdMap  = EEmcSmdMap::instance();
  mSmdSeedThreshold = 5.0;

  //-- TTree for storing pi0 events (with header and trigger info too) --
  mPi0Tree = new TTree("mPi0Tree","EEMC Quick and Dirty Pi0 Finder"); 
  mPi0TreeItem = new EEPi0TreeItem(); 
  mPi0Tree -> Branch("pi0fit", "EEPi0TreeItem",   &mPi0TreeItem, 8000, 1); 
  mPi0Tree -> Branch("trig",   "EEstarTrig",      &mEETrig,      8000, 1);
  mPi0Tree -> Branch("head",   "EEmcEventHeader", &mEEHead,      8000, 1);
  
}

/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////

 Int_t EEQuickPi0Finder::Find( EEezCluster *cluster )
{
  // Returns true if the cluster is likely a pi0n, i.e. it
  // has two peaks in SMD with appropriate mass, etc...
    //

  EEezTower *seed = cluster -> getSeedTower();
  mPi0TreeItem -> eCluster = cluster -> getEnergy();
  mPi0TreeItem -> eSeed    = seed    -> getEnergy(); 
  mPi0TreeItem -> sector   = seed    -> getSector();
  mPi0TreeItem -> subsector = seed   -> getSubSector();
  mPi0TreeItem -> etabin    = seed   -> getEtabin(); 

  //-- Create a new pi0 candidate based on the cluster
  EEezPi0nCandidate *candidate = new EEezPi0nCandidate();
  candidate -> addCluster( cluster );

  //-- Require 3 or 4 SMD seeds --
  Int_t nSeedU = candidate -> numberSmdSeeds(0,10.0);
  Int_t nSeedV = candidate -> numberSmdSeeds(1,10.0);
  if ( nSeedU + nSeedV < 3 && nSeedU + nSeedV > 4 ) return 0;

  cd();

  //-- Name for cloning histograms
  TString name = cluster -> getSeedTower() -> getName();
  name += "_";
  name += mEEHead -> getEventNumber();

  mProfileU = (TH1F *)candidate -> profileU() -> Clone(name+"_Uplane");
  mProfileV = (TH1F *)candidate -> profileV() -> Clone(name+"_Vplane");

  //-- Count number of seeds --
  Int_t nu = candidate -> numberSmdSeeds( 0, mSmdSeedThreshold );
  Int_t nv = candidate -> numberSmdSeeds( 1, mSmdSeedThreshold );

  //-- No pi0 if neither plane has a seed --
  if ( nu < 1 ) return 0;
  if ( nv < 1 ) return 0;


  //-- Fit to a single peak first --
  doSinglePeakFit( cluster );

  //-- Now do double-peak fitting --
  doDoublePeakFit( cluster );

  //-- Compute kinematics
  doKinematics( cluster );
  
  //-- And fill the tree
  mPi0Tree -> Fill();

  //-- Done --
  cd (".."); return 1;

}

/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////

 void EEQuickPi0Finder::doSinglePeakFit( EEezCluster *cluster )
{
  // Perform single peak fit for initialization purposes

  EEezTower *seed = cluster -> getSeedTower();
  Int_t sec,sub,eta;
  sec = seed -> getSector();
  sub = seed -> getSubSector();
  eta = seed -> getEtabin();

  Int_t umin,umax,vmin,vmax;
  mSmdMap -> getRangeU(sec,sub,eta, umin,umax);
  mSmdMap -> getRangeV(sec,sub,eta, vmin,vmax);
  


  //-------------------------------------------------------
  //--
  //-- Fit to single peak
  //--
  Option_t *opts = "RLQ";
  TCanvas *canvas = new TCanvas("mSingleFitCanvas","Fit to Pi0 Mass",600,300);
  canvas -> Divide(2);
  canvas -> Draw();
  
  //-- Fit the SMD U and V histograms to a single shower shape
  canvas -> cd(1);
  mProfileU -> Draw();
  Float_t ymin = mProfileU -> GetMinimum();
  Float_t ymax = mProfileU -> GetMaximum();
  TF1 *fitUsingle = mEzUtils -> fitSmdSingle ( mProfileU, opts, umin, umax );
  TLine *line = new TLine((Float_t)umin,ymin,(Float_t)umin,ymax);
  line -> SetLineColor(2);
  line -> Draw();
  line = new TLine((Float_t)umax,ymin,(Float_t)umax,ymax);
  line -> SetLineColor(2);
  line -> Draw();
  //-- Integrals on either side of peak
  Float_t u1mean = fitUsingle -> GetParameter(1);
  Float_t u1sigma = fitUsingle -> GetParameter(2);
  Float_t profileUmin = mProfileU -> GetXaxis() -> GetXmin();
  Float_t profileUmax = mProfileU -> GetXaxis() -> GetXmax();
  /*
  mProfileU -> GetXaxis() -> SetRangeUser( profileUmin, u1mean - 5.0*u1sigma );  
  Float_t uSumL = mProfileU -> Integral();
  mProfileU -> GetXaxis() -> SetRangeUser( u1mean + 5.0*u1sigma, profileUmax );
  Float_t uSumR = mProfileU -> Integral();
  mProfileU -> GetXaxis() -> UnZoom();
  */
  Float_t uSumL = Integrate( mProfileU, profileUmin, u1mean - 3.0*u1sigma );
  Float_t uSumR = Integrate( mProfileU, u1mean + 3.0*u1sigma, profileUmax ); 
  mPi0TreeItem -> usuml = uSumL;
  mPi0TreeItem -> usumr = uSumR; 

 

  canvas -> cd(2);
  mProfileV -> Draw();
  TF1 *fitVsingle = mEzUtils -> fitSmdSingle ( mProfileV, opts, vmin, vmax );
  ymin = mProfileV -> GetMinimum();
  ymax = mProfileV -> GetMaximum();
  line = new TLine((Float_t)vmin,ymin,(Float_t)vmin,ymax);
  line -> SetLineColor(2);
  line -> Draw();
  line = new TLine((Float_t)vmax,ymin,(Float_t)vmax,ymax);
  line -> SetLineColor(2);
  line -> Draw();
  Float_t v1mean = fitVsingle -> GetParameter(1);
  Float_t v1sigma = fitVsingle -> GetParameter(2);
  Float_t profileVmin = mProfileV -> GetXaxis() -> GetXmin();
  Float_t profileVmax = mProfileV -> GetXaxis() -> GetXmax();
  //-- Integrals on either side of peak
  /*
  mProfileV -> GetXaxis() -> SetRangeUser( profileVmin, v1mean - 5.0*v1sigma );  
  Float_t vSumL = mProfileV -> Integral();
  mProfileV -> GetXaxis() -> SetRangeUser( v1mean + 5.0*v1sigma, profileVmax );
  Float_t vSumR = mProfileV -> Integral();
  mProfileV -> GetXaxis() -> UnZoom();
  */
  Float_t vSumL = Integrate( mProfileV, profileVmin, v1mean - 3.0*v1sigma );
  Float_t vSumR = Integrate( mProfileV, v1mean + 3.0*v1sigma, profileVmax ); 
  mPi0TreeItem -> vsuml = vSumL;
  mPi0TreeItem -> vsumr = vSumR; 


  mSingleFitCanvas = canvas;


  //-------------------------------------------------------
  //--
  //-- Range to attempt to fit residuals over based on 
  //-- left vs right integrals
  //--
  Float_t uumin, uumax;
  if ( uSumL > uSumR ) {
    uumin=mProfileU -> GetXaxis() -> GetXmin();
    uumax=u1mean - 5.0*u1sigma;
  }
  else {
    uumin=u1mean + 5.0*u1sigma;
    uumax=mProfileU -> GetXaxis() -> GetXmax();
  }

  Float_t vvmin, vvmax;
  if ( vSumL > vSumR ) {
    vvmin=mProfileV -> GetXaxis() -> GetXmin();
    vvmax=v1mean - 5.0*v1sigma;
  }
  else {
    vvmin=v1mean + 5.0*v1sigma;
    vvmax=mProfileV -> GetXaxis() -> GetXmax();
  }


  //-------------------------------------------------------
  //--
  //-- Residual fit to single peak
  //--
  canvas = new TCanvas("mResidualFitCanvas","Fit to Pi0 Mass",600,300);
  canvas -> Divide(2);
  canvas -> Draw();

  canvas->cd(1);
  TString name = mProfileU -> GetName();
  mResidualU = (TH1F *)mProfileU -> Clone( name+"_residual" );
  mResidualU -> Add ( fitUsingle, -1.0 );
  TF1 *fitUresidual = mEzUtils -> fitSmdSingle( mResidualU, opts, uumin, uumax );
  ymin = mResidualU -> GetMinimum();
  ymax = mResidualU -> GetMaximum();
  line = new TLine( uumin, ymin, uumin, ymax ); line -> SetLineColor(4); line -> Draw();
  line = new TLine( uumax, ymin, uumax, ymax ); line -> SetLineColor(4); line -> Draw();

  canvas->cd(2);
  name = mProfileV -> GetName();
  mResidualV = (TH1F *)mProfileV -> Clone( name+"_residual" );
  mResidualV -> Add ( fitVsingle, -1.0 );

  TF1 *fitVresidual = mEzUtils -> fitSmdSingle( mResidualV, opts, vvmin, vvmax );
  ymin = mResidualV -> GetMinimum();
  ymax = mResidualV -> GetMaximum();
  line = new TLine( vvmin, ymin, vvmin, ymax ); line -> SetLineColor(4); line -> Draw();
  line = new TLine( vvmax, ymin, vvmax, ymax ); line -> SetLineColor(4); line -> Draw();

  std::cout << "mProfileU integral: " << std::endl;
  std::cout << "histogram: " << mProfileU -> Integral() << std::endl;
  std::cout << "fit:       " << fitUsingle -> GetParameter(0) << std::endl;
  std::cout << "fit resid: " << fitUresidual -> GetParameter(0) << std::endl;
  
  std::cout << "mProfileV integral: " << std::endl;
  std::cout << "histogram: " << mProfileV -> Integral() << std::endl;
  std::cout << "fit:       " << fitVsingle -> GetParameter(0) << std::endl;
  std::cout << "fit resid: " << fitVresidual -> GetParameter(0) << std::endl;

  mUinit[0].yield  = fitUsingle -> GetParameter(0);
  mUinit[0].mean   = fitUsingle -> GetParameter(1);
  mUinit[0].sigma  = fitUsingle -> GetParameter(2);
  mUinit[0].ryield = fitUsingle -> GetParameter(3);
  mUinit[0].rsigma = fitUsingle -> GetParameter(4);
  mUinit[0].min    = umin;
  mUinit[0].max    = umax;

  mPi0TreeItem -> umin1 = umin;
  mPi0TreeItem -> umax1 = umax;

  mVinit[0].yield  = fitVsingle -> GetParameter(0);
  mVinit[0].mean   = fitVsingle -> GetParameter(1);
  mVinit[0].sigma  = fitVsingle -> GetParameter(2);
  mVinit[0].ryield = fitVsingle -> GetParameter(3);
  mVinit[0].rsigma = fitVsingle -> GetParameter(4);
  mVinit[0].min    = vmin;
  mVinit[0].max    = vmax;

  mPi0TreeItem -> vmin1 = vmin;
  mPi0TreeItem -> vmax1 = vmax;

  mUinit[1].yield  = fitUresidual -> GetParameter(0);
  mUinit[1].mean   = fitUresidual -> GetParameter(1);
  mUinit[1].sigma  = fitUresidual -> GetParameter(2);
  mUinit[1].ryield = fitUresidual -> GetParameter(3);
  mUinit[1].rsigma = fitUresidual -> GetParameter(4);
  mUinit[1].min    = uumin;
  mUinit[1].max    = uumax;

  mPi0TreeItem -> umin2 = uumin;
  mPi0TreeItem -> umax2 = uumax;
  
  mVinit[1].yield  = fitVresidual -> GetParameter(0);
  mVinit[1].mean   = fitVresidual -> GetParameter(1);
  mVinit[1].sigma  = fitVresidual -> GetParameter(2);
  mVinit[1].ryield = fitVresidual -> GetParameter(3);
  mVinit[1].rsigma = fitVresidual -> GetParameter(4);
  mVinit[1].min    = vvmin;
  mVinit[1].max    = vvmax; 

  mPi0TreeItem -> vmin2 = vvmin;
  mPi0TreeItem -> vmax2 = vvmax;
  
}


/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////

 void EEQuickPi0Finder::doDoublePeakFit( EEezCluster *cluster )
{
    // Perform double-peak fit 
    mDoubleFitCanvas = new TCanvas("mDoubleFitCanvas","EEMC pi0 fit",600,300);
    mDoubleFitCanvas -> Divide(2);

    //-- U first -- 
    
    TString name = mProfileU -> GetName(); 
    TH1F *uhisto = (TH1F *)mProfileU -> Clone(name+"_dblefit");  
    TF1 *ufit = new TF1("eeDoublePeak",eeDoublePeak,0,288,10);
    ufit -> SetLineColor(2);
    ufit -> SetFillStyle(0); 
    ufit -> FixParameter(0, mUinit[0].yield );
    ufit -> FixParameter(1, mUinit[0].mean );
    ufit -> FixParameter(2, mUinit[0].sigma );
    ufit -> FixParameter(3, mUinit[0].ryield );
    ufit -> FixParameter(4, mUinit[0].rsigma );
    ufit -> FixParameter(5, mUinit[1].yield );
    ufit -> SetParameter(6, mUinit[1].mean);
    ufit -> FixParameter(7, mUinit[1].sigma );
    ufit -> FixParameter(8, mUinit[1].ryield );
    ufit -> FixParameter(9, mUinit[1].rsigma ); 
    
    mDoubleFitCanvas -> cd(1); 
    ufit -> SetParLimits( 6, mUinit[1].min, mUinit[1].max ); 
    
    uhisto -> Fit ( ufit, "RLQ" ); 


    //-- V next --  
    name = mProfileV -> GetName(); 
    TH1F *vhisto = (TH1F *)mProfileV -> Clone(name+"_dblefit");  
    TF1 *vfit = new TF1("eeDoublePeak",eeDoublePeak,0,288,10);
    vfit -> SetLineColor(2);
    vfit -> SetFillStyle(0); 
    vfit -> FixParameter(0, mVinit[0].yield );
    vfit -> FixParameter(1, mVinit[0].mean );
    vfit -> FixParameter(2, mVinit[0].sigma );
    vfit -> FixParameter(3, mVinit[0].ryield );
    vfit -> FixParameter(4, mVinit[0].rsigma );
    vfit -> FixParameter(5, mVinit[1].yield );
    vfit -> SetParameter(6, mVinit[1].mean);
    vfit -> FixParameter(7, mVinit[1].sigma );
    vfit -> FixParameter(8, mVinit[1].ryield );
    vfit -> FixParameter(9, mVinit[1].rsigma ); 
    
    mDoubleFitCanvas -> cd(2); 
    vfit -> SetParLimits( 6, mVinit[1].min, mVinit[1].max ); 
    
    vhisto -> Fit ( vfit, "RLQ" ); 


    //-- Save in TTree -------------------------------------
    //
    mPi0TreeItem -> u1yield  = ufit -> GetParameter(0); 
    mPi0TreeItem -> u1mean   = ufit -> GetParameter(1); 
    mPi0TreeItem -> u1sigma  = ufit -> GetParameter(2); 
    mPi0TreeItem -> u1ryield = ufit -> GetParameter(3);
    mPi0TreeItem -> u1rsigma = ufit -> GetParameter(4); 

    mPi0TreeItem -> u2yield  = ufit -> GetParameter(5); 
    mPi0TreeItem -> u2mean   = ufit -> GetParameter(6); 
    mPi0TreeItem -> u2sigma  = ufit -> GetParameter(7); 
    mPi0TreeItem -> u2ryield = ufit -> GetParameter(8);
    mPi0TreeItem -> u2rsigma = ufit -> GetParameter(9); 

    mPi0TreeItem -> uchi2   = ufit -> GetChisquare(); 
    mPi0TreeItem -> undf    = ufit -> GetNDF(); 

    mPi0TreeItem -> v1yield  = vfit -> GetParameter(0); 
    mPi0TreeItem -> v1mean   = vfit -> GetParameter(1); 
    mPi0TreeItem -> v1sigma  = vfit -> GetParameter(2); 
    mPi0TreeItem -> v1ryield = vfit -> GetParameter(3);
    mPi0TreeItem -> v1rsigma = vfit -> GetParameter(4); 

    mPi0TreeItem -> v2yield  = vfit -> GetParameter(5); 
    mPi0TreeItem -> v2mean   = vfit -> GetParameter(6); 
    mPi0TreeItem -> v2sigma  = vfit -> GetParameter(7); 
    mPi0TreeItem -> v2ryield = vfit -> GetParameter(8);
    mPi0TreeItem -> v2rsigma = vfit -> GetParameter(9); 

    mPi0TreeItem -> vchi2   = vfit -> GetChisquare(); 
    mPi0TreeItem -> vndf    = vfit -> GetNDF(); 

    mPi0TreeItem -> uprofile = uhisto; 
    mPi0TreeItem -> vprofile = vhisto; 

}

/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////

 void EEQuickPi0Finder::doKinematics(EEezCluster *cluster)
{
  // Calculate pi0 kinematics
  
  //-- Zero out the kinematics entries in the tree item

  mPi0TreeItem -> zggu = 0.;
  mPi0TreeItem -> dggu = 0.;
  mPi0TreeItem -> zggv = 0.;
  mPi0TreeItem -> dggv = 0.;

  mPi0TreeItem -> zgg   = -1.;
  mPi0TreeItem -> dgg   = -1.;
  mPi0TreeItem -> phigg = -1.;
  mPi0TreeItem -> mass  = -1.;
  mPi0TreeItem -> xf    = -1.;
  mPi0TreeItem -> pt    = -1.;
  mPi0TreeItem -> eta   = -1.;
  mPi0TreeItem -> phi   = -1.;

  //-- Energy sharing --
  Float_t udiff = mPi0TreeItem -> u1yield - mPi0TreeItem -> u2yield;
  Float_t usum  = mPi0TreeItem -> u1yield + mPi0TreeItem -> u2yield;
  if ( usum > 0. )
    mPi0TreeItem -> zggu = TMath::Abs(udiff)/usum;

  Float_t vdiff = mPi0TreeItem -> v1yield - mPi0TreeItem -> v2yield;
  Float_t vsum  = mPi0TreeItem -> v1yield + mPi0TreeItem -> v2yield;
  if ( vsum > 0. )
    mPi0TreeItem -> zggv = TMath::Abs(vdiff)/vsum;

  Float_t zgg = ( mPi0TreeItem ->zggu + mPi0TreeItem ->zggv ) / 2.0;
  mPi0TreeItem -> zgg = zgg;

  //-- Distance between photons --

  Float_t dggu = mPi0TreeItem -> u1mean - mPi0TreeItem -> u2mean;
  Float_t dggv = mPi0TreeItem -> v1mean - mPi0TreeItem -> v2mean;
  Float_t dgg  = TMath::Sqrt( dggu*dggu + dggv*dggv );
  //-- Divide by 2 to get into cm
  dggu /= 2.;
  dggv /= 2.;
  dgg  /= 2.;
  mPi0TreeItem -> dggu = dggu;
  mPi0TreeItem -> dggv = dggv;
  mPi0TreeItem -> dgg  = dgg;
  
  //-- Opening angle between the photons
  Float_t phigg = dgg / kEEmcZSMD;
  mPi0TreeItem -> phigg = dgg / kEEmcZSMD;

  //-- NOTE: This is for 200 GeV! --
  Float_t eCluster = cluster -> getEnergy();
  mPi0TreeItem -> xf = eCluster / 200.0;
  
  Float_t mass2 = 0.5 * eCluster * eCluster * ( 1.0 - zgg ) * ( 1.0 + zgg ) *
    TMath::Sin( phigg / 2.0 ) * TMath::Sin( phigg / 2.0 );
  Float_t mass = TMath::Sqrt(mass2);

  mPi0TreeItem -> mass = mass;
}

/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////

 Float_t EEQuickPi0Finder::Integrate( TH1F *h, Float_t min, Float_t max )
{
    // A method to integrate histogram contents between min and 
    // max... assumes bin width = 1.0.  Eliminates single-strip
    // (i.e. stale pedestal) bins. 

    Int_t minBin = h -> FindBin(min);
    Int_t maxBin = h -> FindBin(max);
    Float_t sum = 0.; 
    for ( Int_t i = minBin; i <= maxBin; i++ ) {
	Float_t y = h -> GetBinContent(i);
	if ( h->GetBinContent(i+1) > 0. && h->GetBinContent(i-1) > 0. ) sum += y;
    }
    return sum; 
}

/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////


ROOT page - Class index - 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.