/* ======================================================================== *\
!
! *
! * 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): Thomas Bretz  07/2001 <mailto:tbretz@uni-sw.gwdg.de>
!
!   Copyright: MAGIC Software Development, 2000-2001
!
!
\* ======================================================================== */

//////////////////////////////////////////////////////////////////////////////
//                                                                          //
//  MH                                                                      //
//                                                                          //
//  This is a base tasks for mars histograms. It defines a common interface //
//  for filling the histograms with events (MH::Fill) which is used by a    //
//  common 'filler' And a SetupFill member function which may be used       //
//  by MFillH. The idea is:                                                 //
//   1) If your Histogram can become filled by one single container         //
//      (like MHHillas) you overload MH::Fill and it gets called with       //
//      a pointer to the container with which it should be filled.          //
//                                                                          //
//   2) You histogram needs several containers to get filled. Than you      //
//      have to overload MH::SetupFill and get the necessary objects from   //
//      the parameter list. Use this objects in Fill to fill your           //
//      histogram.                                                          //
//                                                                          //
//  If you want to create your own histogram class the new class must be    //
//  derived from MH (instead of the base MParContainer) and you must        //
//  the fill function of MH. This is the function which is called to fill   //
//  the histogram(s) by the data of a corresponding parameter container.    //
//                                                                          //
//////////////////////////////////////////////////////////////////////////////

#include "MH.h"

#include <TH1.h>
#include <TCanvas.h>

#include "MBinning.h"

ClassImp(MH);

// --------------------------------------------------------------------------
//
// Default Constructor. It sets name and title only. Typically you won't
// need to change this.
//
MH::MH(const char *name, const char *title)
{
    //
    //   set the name and title of this object
    //
    fName  = name  ? name  : "MH" ;
    fTitle = title ? title : "Base class for Mars histograms" ;
}

// --------------------------------------------------------------------------
//
// This is a function which should replace the creation of default
// canvases like root does. Because this is inconvinient in some aspects.
// need to change this.
// You can specify a name for the default canvas and a title. Also
// width and height can be given.
// MakeDefCanvas looks for a canvas with the given name. If now name is
// given the DefCanvasName of root is used. If no such canvas is existing
// it is created and returned. If such a canvas already exists a new canvas
// with a name plus anumber is created (the number is calculated by the
// number of all existing canvases plus one)
//
TCanvas *MH::MakeDefCanvas(const char *name, const char *title,
                           const UInt_t w, const UInt_t h)
{
    const TList *list = (TList*)gROOT->GetListOfCanvases();

    const char *def = name ? name : gROOT->GetDefCanvasName();

    TCanvas *c;
    if (list->FindObject(def))
    {
        const char *n = StrDup(Form("%s <%d>", def, list->GetSize()+1));
        c = new TCanvas(n, title, w, h);
        delete [] n;
    }
    else
        c = new TCanvas(def, title, w, h);

    return c;
}

// --------------------------------------------------------------------------
//
// This function works like MakeDefCanvas(name, title, w, h) but name
// and title are retrieved from the given TObject.
//
TCanvas *MH::MakeDefCanvas(const TObject *obj,
                           const UInt_t w, const UInt_t h)
{
    return MakeDefCanvas(obj->GetName(), obj->GetTitle(), w, h);
}

void MH::SetBinning(TH1 *h, const MBinning *binsx)
{
    //
    // This is a necessary workaround if one wants to set
    // non-equidistant bins after the initialization
    // TH1D::fNcells must be set correctly.
    //
    h->SetBins(binsx->GetNumBins(), 0, 1);

    //
    // Set the binning of the current histogram to the binning
    // in one of the two given histograms
    //
    h->GetXaxis()->Set(binsx->GetNumBins(), binsx->GetEdges());
}

void MH::SetBinning(TH1 *h, const MBinning *binsx, const MBinning *binsy)
{
    //
    // This is a necessary workaround if one wants to set
    // non-equidistant bins after the initialization
    // TH1D::fNcells must be set correctly.
    //
    h->SetBins(binsx->GetNumBins(), 0, 1,
               binsy->GetNumBins(), 0, 1);

    //
    // Set the binning of the current histogram to the binning
    // in one of the two given histograms
    //
    h->GetXaxis()->Set(binsx->GetNumBins(), binsx->GetEdges());
    h->GetYaxis()->Set(binsy->GetNumBins(), binsy->GetEdges());
}

void MH::SetBinning(TH1 *h, const MBinning *binsx, const MBinning *binsy, const MBinning *binsz)
{
    //
    // This is a necessary workaround if one wants to set
    // non-equidistant bins after the initialization
    // TH1D::fNcells must be set correctly.
    //
    h->SetBins(binsx->GetNumBins(), 0, 1,
               binsy->GetNumBins(), 0, 1,
               binsz->GetNumBins(), 0, 1);

    //
    // Set the binning of the current histogram to the binning
    // in one of the two given histograms
    //
    h->GetXaxis()->Set(binsx->GetNumBins(), binsx->GetEdges());
    h->GetYaxis()->Set(binsy->GetNumBins(), binsy->GetEdges());
    h->GetZaxis()->Set(binsz->GetNumBins(), binsz->GetEdges());
}

void MH::SetBinning(TH1 *h, const TArrayD *binsx)
{
    MBinning bx;
    bx.SetEdges(*binsx);
    SetBinning(h, &bx);
}

void MH::SetBinning(TH1 *h, const TArrayD *binsx, const TArrayD *binsy)
{
    MBinning bx;
    MBinning by;
    bx.SetEdges(*binsx);
    by.SetEdges(*binsy);
    SetBinning(h, &bx, &by);
}

void MH::SetBinning(TH1 *h, const TArrayD *binsx, const TArrayD *binsy, const TArrayD *binsz)
{
    MBinning bx;
    MBinning by;
    MBinning bz;
    bx.SetEdges(*binsx);
    by.SetEdges(*binsy);
    bz.SetEdges(*binsz);
    SetBinning(h, &bx, &by, &bz);
}

void MH::SetBinning(TH1 *h, const TAxis *binsx)
{
    MBinning bx;
    bx.SetEdges(*((TAxis*)binsx)->GetXbins()); // FIXME: Root!
    SetBinning(h, &bx);
}

void MH::SetBinning(TH1 *h, const TAxis *binsx, const TAxis *binsy)
{
    MBinning bx;
    MBinning by;
    bx.SetEdges(*((TAxis*)binsx)->GetXbins()); // FIXME: Root!
    by.SetEdges(*((TAxis*)binsy)->GetXbins()); // FIXME: Root!
    SetBinning(h, &bx, &by);
}

void MH::SetBinning(TH1 *h, const TAxis *binsx, const TAxis *binsy, const TAxis *binsz)
{
    MBinning bx;
    MBinning by;
    MBinning bz;
    bx.SetEdges(*((TAxis*)binsx)->GetXbins()); // FIXME: Root!
    by.SetEdges(*((TAxis*)binsy)->GetXbins()); // FIXME: Root!
    bz.SetEdges(*((TAxis*)binsz)->GetXbins()); // FIXME: Root!
    SetBinning(h, &bx, &by, &bz);
}

