/* ======================================================================== *\
!
! *
! * 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): Nicola Galante, 2003 <mailto:nicola.galante@pi.infn.it>
!
!   Copyright: MAGIC Software Development, 2000-2003
!
!
\* ======================================================================== */

/////////////////////////////////////////////////////////////////////////////
//
// MHMcTriggerLvl2
//
// This class contains histograms for the Trigger Level2 image parameters
//
/////////////////////////////////////////////////////////////////////////////

#include "MHMcTriggerLvl2.h"

#include <math.h>

#include <TH1.h>
#include <TF1.h>
#include <TPad.h>
#include <TStyle.h>
#include <TCanvas.h>
#include <TPaveLabel.h>

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

#include "MParList.h"

#include "MMcTriggerLvl2.h"
#include "MGeomCam.h"
#include "MBinning.h"

/*
 Please, DON'T USE IFDEFS IN SUCH A CONTEXT, Thomas.
 --------------------------------------------------
#ifndef COLOR_LINELPS
#define COLOR_LINELPS Int_t colorlps = 1
COLOR_LINELPS;
#endif

#ifndef COLOR_LINESBC
#define COLOR_LINESBC Int_t colorsbc = 1
COLOR_LINESBC;
#endif

#ifndef COLOR_LINEPS
#define COLOR_LINEPS Int_t colorps = 1
COLOR_LINEPS;
#endif
*/

/* Use this insteadif you want to have some value which is the same for all
 your instances of MHMcTriggerLvl2, if not define the values in the constructor
 and remove the 'static'
 */

Int_t MHMcTriggerLvl2::fColorLps = 1;
Int_t MHMcTriggerLvl2::fColorSbc = 1;
Int_t MHMcTriggerLvl2::fColorPs = 1;

ClassImp(MHMcTriggerLvl2);

// --------------------------------------------------------------------------
//
// Setup three histograms for fLutPseudoSize, fPseudoSize, fSizeBiggerCell
//
MHMcTriggerLvl2::MHMcTriggerLvl2(const char *name, const char *title)
{
    //
    //   set the name and title of this object
    //
    fName  = name  ? name  : "MHMcTriggerLvl2";
    fTitle = title ? title : "Trigger L2 image parameters";

    fHistLutPseudoSize  = new TH1F("fHistLutPseudoSize",  "number of compact pixels in one lut",                13,   0, 12);
    fHistPseudoSize     = new TH1F("fHistPseudoSize",   "Multiplicity of the cluster identified by the L2T",    41,   0, 40);
    fHistSizeBiggerCell  = new TH1F("fHistSizeBiggerCell",   "Number of fired pixel in bigger cell",            37,   0, 36);

    fHistLutPseudoSizeNorm  = new TH1F("fHistLutPseudoSizeNorm",  "Normalized Number of compact pixels in one lut",                13,   0, 12);
    fHistPseudoSizeNorm     = new TH1F("fHistPseudoSizeNorm",   "Normalized Multiplicity of the cluster identified by the L2T",    41,   0, 40);
    fHistSizeBiggerCellNorm  = new TH1F("fHistSizeBiggerCellNorm",   "Normalized Number of fired pixel in bigger cell",            37,   0, 36);

    fHistLutPseudoSize->SetDirectory(NULL);
    fHistLutPseudoSizeNorm->SetDirectory(NULL);
    fHistPseudoSize->SetDirectory(NULL);
    fHistPseudoSizeNorm->SetDirectory(NULL);
    fHistSizeBiggerCell->SetDirectory(NULL);
    fHistSizeBiggerCellNorm->SetDirectory(NULL);

    fHistLutPseudoSize->SetXTitle("Number of Pixels");
    fHistLutPseudoSizeNorm->SetXTitle("Number of Pixels");
    fHistPseudoSize->SetXTitle("Number of Pixels");
    fHistPseudoSizeNorm->SetXTitle("Number of Pixels");
    fHistSizeBiggerCell->SetXTitle("Number of Pixels");
    fHistSizeBiggerCellNorm->SetXTitle("Number of Pixels");

    fHistLutPseudoSize->SetYTitle("Counts");
    fHistLutPseudoSizeNorm->SetYTitle("Counts/Total Counts");
    fHistPseudoSize->SetYTitle("Counts");
    fHistPseudoSizeNorm->SetYTitle("Counts/Total Counts");
    fHistSizeBiggerCell->SetYTitle("Counts");
    fHistSizeBiggerCellNorm->SetYTitle("Counts/Total Counts");

    fFNorm = new TF1("FNorm", "1", -1, 40);
}

// --------------------------------------------------------------------------
//
// Delete the histograms
//
MHMcTriggerLvl2::~MHMcTriggerLvl2()
{
    delete fHistLutPseudoSize;
    delete fHistPseudoSize;
    delete fHistSizeBiggerCell;
    delete fHistLutPseudoSizeNorm;
    delete fHistPseudoSizeNorm;
    delete fHistSizeBiggerCellNorm;

    delete fFNorm;
}

// --------------------------------------------------------------------------
//
// Fill the histograms with data from a MMcTriggerLvl2-Container.
// Be careful: Only call this with an object of type MMcTriggerLvl2
//
Bool_t MHMcTriggerLvl2::Fill(const MParContainer *par, Double_t w)
{
  const MMcTriggerLvl2 &h = *(MMcTriggerLvl2 *)par;
 
  fHistLutPseudoSize->Fill(h.GetLutPseudoSize());
  fHistPseudoSize->Fill(h.GetPseudoSize());
  fHistSizeBiggerCell->Fill(h.GetSizeBiggerCell());

  return kTRUE;
}


// --------------------------------------------------------------------------
//
// This is the private function member which draw a clone of a histogram. 
// This method is called by the DrawClone method.
//
TObject *MHMcTriggerLvl2::DrawHist(TH1 &hist, TH1 &histNorm, const TString &canvasname, Int_t &col) const
{
    col++;

    TCanvas *c = (TCanvas*)gROOT->FindObject(canvasname);

    Bool_t same = kTRUE;
    if (!c)
    {
        c = MakeDefCanvas(canvasname,canvasname, 800, 610);
        c->Divide(2,1);
        same = kFALSE;
    }

    c->cd(1);
    hist.SetLineColor(col);
    hist.DrawCopy(same?"same":"");

    c->cd(2);
    histNorm.SetLineColor(col);
    histNorm.DrawCopy(same?"same":"");

    return c;
}


// --------------------------------------------------------------------------
//
// Draw a clone of a data member histogram. So that the object can be deleted
// and the histogram is still visible in the canvas.
// The cloned object are deleted together with the canvas if the canvas is
// destroyed. If you want to handle dostroying the canvas you can get a
// pointer to it from this function
// Possible options are:
//      "lps" for the fLutPseudoSize histogram;
//      "sbc" for the fSizeBiggerCell histogram;
//      "ps" for the fPseudoSize histogram;
//      default: "ps"
//
TObject *MHMcTriggerLvl2::DrawClone(Option_t *opt) const
{
    TString str(opt);

    if (str.IsNull())
        str = "ps";

    if (!str.Contains("lps", TString::kIgnoreCase) &&
        !str.Contains("sbc", TString::kIgnoreCase) &&
        !str.Contains("ps",  TString::kIgnoreCase))
    {
        *fLog << "ARGH!@! Possible options are \"lps\", \"sbc\", \"ps\" or NULL!" <<endl;
        return NULL;
    }

    TH1 *hist=NormalizeHist(fHistLutPseudoSizeNorm, fHistLutPseudoSize);

    if (!hist)
        return NULL;

    if (str.Contains("lps",TString::kIgnoreCase))
        return DrawHist(*fHistLutPseudoSize, *hist, "CanvasLPS", fColorLps);

    if (str.Contains("sbc",TString::kIgnoreCase))
        return DrawHist(*fHistSizeBiggerCell, *hist, "CanvasSBC", fColorSbc);

    if (str.Contains("ps",TString::kIgnoreCase))
        return DrawHist(*fHistPseudoSize, *hist, "CanvasPS", fColorPs);

    return NULL;
}



// --------------------------------------------------------------------------
//
// Creates a new canvas and draws the three histograms into it.
// Be careful: The histograms belongs to this object and won't get deleted
// together with the canvas.
//
void MHMcTriggerLvl2::Draw(Option_t *)
{
  MakeDefCanvas("c","L2T Parameters", 720, 810);
  
  TPad* pad1 = new TPad("pad1","Pad with fLutPseudoSize", 0.003, 0.7, 0.4, 0.997);
  TPad* pad2 = new TPad("pad2","Pad with fSizeBiggerCell", 0.403, 0.7, 0.997, 0.997);
  TPad* pad3 = new TPad("pad3","Pad with fPseudoSize", 0.003, 0.003, 0.997, 0.697);
  pad1->Draw();
  pad2->Draw();
  pad3->Draw();
  
  pad1->cd();
  fHistLutPseudoSize->Draw();
  
  pad2->cd();
  fHistSizeBiggerCell->Draw();
  
  pad3->cd();
  fHistPseudoSize->Draw();
}



// --------------------------------------------------------------------------
//
//  Return the histogram by its name
//
TH1 *MHMcTriggerLvl2::GetHistByName(const TString name)
{
    if (name.Contains("fHistLutPseudoSize", TString::kIgnoreCase))
      return fHistLutPseudoSize;
    if (name.Contains("fHistSizeBiggerCell", TString::kIgnoreCase))
        return fHistSizeBiggerCell;
    if (name.Contains("fHistPseudoSize", TString::kIgnoreCase))
        return fHistPseudoSize;

    if (name.Contains("fHistLutPseudoSizeNorm", TString::kIgnoreCase))
      return fHistLutPseudoSizeNorm;
    if (name.Contains("fHistSizeBiggerCellNorm", TString::kIgnoreCase))
        return fHistSizeBiggerCellNorm;
    if (name.Contains("fHistPseudoSizeNorm", TString::kIgnoreCase))
        return fHistPseudoSizeNorm;

    return NULL;
}



// --------------------------------------------------------------------------
//
// Normalize the histogram on its integral, i.e.  normalize the
// values of the histogram on the statistics. This method creates
// a copy (histNorm) of the histogram to normalize (hist) and normalize
// the copy (histNorm) on its integral. It returns histNorm.
//
TH1 *MHMcTriggerLvl2::NormalizeHist(TH1 *histNorm, TH1 *hist) const
{
  if (histNorm == hist){
    *fLog << "ARGH!@! You cannot pass the same histogram into each argument!" << endl;
    return NULL;
  }

  if ((hist == NULL) || (hist->Integral() == (Stat_t)0)){
    *fLog << "ARGH!@! You are trying to normalize the histogram to 0!" << endl;
    return NULL;
  }
  
  histNorm->Reset("ICE");
  histNorm->Add(hist, 1);
  histNorm->Divide(fFNorm, (Double_t)(hist->Integral()));

  return histNorm;
}
