/* ======================================================================== *\
!
! *
! * This file is part of MARS, the MAGIC Analysis and Reconstruction
! * Software. It is distributed to you in the hope that it can be a useful
! * and timesaving tool in analysing Data of imaging Cerenkov telescopes.
! * It is distributed WITHOUT ANY WARRANTY.
! *
! * Permission to use, copy, modify and distribute this software and its
! * documentation for any purpose is hereby granted without fee,
! * provided that the above copyright notice appear in all copies and
! * that both that copyright notice and this permission notice appear
! * in supporting documentation. It is provided "as is" without express
! * or implied warranty.
! *
!
!
!   Author(s): Markus Gaug 02/2004 <mailto:markus@ifae.es>
!
!   Copyright: MAGIC Software Development, 2000-2004
!
!
\* ======================================================================== */

//////////////////////////////////////////////////////////////////////////////
//
//  MHCalibrationChargePix
//
//  Histogram class for charge calibration analysis. Holds the histogrammed
//  summed FADC slices and some rough absolute timing. Calculates the mean 
//  sum of FADC slices and its sigma
//
//////////////////////////////////////////////////////////////////////////////
#include "MHCalibrationChargePix.h"

#include <TH1.h>
#include <TF1.h>

#include <TVirtualPad.h>
#include <TCanvas.h>
#include <TPad.h>
#include <TGraph.h>

#include "MH.h"

#include "MLog.h"
#include "MLogManip.h"

ClassImp(MHCalibrationChargePix);

using namespace std;

const Int_t   MHCalibrationChargePix::fgChargeNbins     = 2000;
const Axis_t  MHCalibrationChargePix::fgChargeFirst     = -0.5;
const Axis_t  MHCalibrationChargePix::fgChargeLast      = 1999.5;
const Int_t   MHCalibrationChargePix::fgAbsTimeNbins    = 15;
const Axis_t  MHCalibrationChargePix::fgAbsTimeFirst    = -0.5;
const Axis_t  MHCalibrationChargePix::fgAbsTimeLast     = 14.5;

const Int_t   MHCalibrationChargePix::fgPulserFrequency = 200;
// --------------------------------------------------------------------------
//
// Default Constructor. 
//
MHCalibrationChargePix::MHCalibrationChargePix(const char *name, const char *title)
    : fHAbsTime()
{ 
  
  fName  = name  ? name  : "MHCalibrationChargePix";
  fTitle = title ? title : "Fill the FADC sums of calibration events and perform the fits";

  SetChargeNbins();
  SetChargeFirst();
  SetChargeLast();

  SetAbsTimeNbins();
  SetAbsTimeFirst();
  SetAbsTimeLast();

  fHAbsTime.UseCurrentStyle();
  fHAbsTime.SetDirectory(NULL); 

  Clear();
  
  SetPulserFrequency();
}

void MHCalibrationChargePix::Init()
{

  fHGausHist.SetName("HCalibrationCharge");
  fHGausHist.SetTitle("Distribution of Summed FADC slices Pixel");  
  fHGausHist.SetXTitle("Sum FADC Slices");
  fHGausHist.SetYTitle("Nr. of events");
  fHGausHist.SetBins(fChargeNbins,fChargeFirst,fChargeLast);
  fHGausHist.Sumw2();

  fHAbsTime.SetName("HAbsTimePixel");
  fHAbsTime.SetTitle("Distribution of Absolute Arrival Times Pixel ");  
  fHAbsTime.SetXTitle("Absolute Arrival Time [FADC slice nr]");
  fHAbsTime.SetYTitle("Nr. of events");
  fHAbsTime.SetBins(fAbsTimeNbins,fAbsTimeFirst,fAbsTimeLast);

}

    

void MHCalibrationChargePix::Clear(Option_t *o)
{

  fPixId = -1;
  
  SetMeanTimeInFirstBin( kFALSE );
  SetMeanTimeInLastBin(  kFALSE );  

  MHGausEvents::Clear();
  return;
}


void MHCalibrationChargePix::Reset()
{
}


void MHCalibrationChargePix::ChangeHistId(Int_t id)
{

  fPixId = id;

  fHGausHist.SetName(Form("%s%d", fHGausHist.GetName(), id));
  fHGausHist.SetTitle(Form("%s%d", fHGausHist.GetTitle(), id));

  fHAbsTime.SetName(Form("%s%d", fHAbsTime.GetName(), id));
  fHAbsTime.SetTitle(Form("%s%d", fHAbsTime.GetTitle(), id));
}

void MHCalibrationChargePix::SetMeanTimeInFirstBin(const Bool_t b)
{
  b ? SETBIT(fFlags,kMeanTimeInFirstBin) : CLRBIT(fFlags,kMeanTimeInFirstBin);
}

void MHCalibrationChargePix::SetMeanTimeInLastBin(const Bool_t b)
{
  b ? SETBIT(fFlags,kMeanTimeInLastBin) : CLRBIT(fFlags,kMeanTimeInLastBin);
}

const Bool_t MHCalibrationChargePix::IsMeanTimeInFirstBin() const
{
  return TESTBIT(fFlags,kMeanTimeInFirstBin);
}

const Bool_t MHCalibrationChargePix::IsMeanTimeInLastBin() const
{
  return TESTBIT(fFlags,kMeanTimeInLastBin);
}


const Float_t MHCalibrationChargePix::GetIntegral() const 
{ 
   return fHGausHist.Integral("width");  
}

const Float_t MHCalibrationChargePix::GetAbsTimeMean() const 
{
  return fHAbsTime.GetMean();
}

const Float_t MHCalibrationChargePix::GetAbsTimeRms()  const 
{
  return fHAbsTime.GetRMS();
}

void  MHCalibrationChargePix::SetPulserFrequency(Float_t f)
{
  SetEventFrequency(f);
}

Bool_t MHCalibrationChargePix::FillAbsTime(Float_t t)
{
  return fHAbsTime.Fill(t) > -1;
}


void MHCalibrationChargePix::Draw(const Option_t *opt)
{

  TString option(opt);
  option.ToLower();
  
  Int_t win = 1;
  
  TVirtualPad *pad = gPad ? gPad : MH::MakeDefCanvas(this,600, 600);

  pad->SetTicks();
  pad->SetBorderMode(0);
    
  if (option.Contains("time"))
    win++;

  pad->SetTicks();
  pad->SetBorderMode(0);
  pad->Divide(1,win);
  pad->cd(1);

  if (!IsEmpty())
    pad->SetLogy();

  MHGausEvents::Draw(opt);

  if (win > 1)
    {
      pad->cd(2);
      fHAbsTime.Draw(opt);
    }
}

void MHCalibrationChargePix::BypassFit()
{

  //
  // In case, we do not obtain reasonable values 
  // with the fit, we take the histogram values
  //
  SetMean(fHGausHist.GetMean());
  SetMeanErr(fHGausHist.GetRMS()/fHGausHist.GetEntries());
  SetSigma(fHGausHist.GetRMS());
  SetSigmaErr(fHGausHist.GetRMS()/fHGausHist.GetEntries()/2.);
}

