/* ======================================================================== *\
!
! *
! * 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  1/2009 <mailto:tbretz@astro.uni-wuerzburg.de>
!
!   Copyright: Software Development, 2000-2009
!
!
\* ======================================================================== */

//////////////////////////////////////////////////////////////////////////////
//
//  MSpline3
//
// This is a extension of TSpline3. In addition to TSpline3 it allows access
// to Xmin, Xman and Np. The construction is a bit simplified because no
// title hase to be given (it can be given later by SetTitle anyway)
// and is provides constructors which allow to scale the x-values by
// pre-defined multiplier (e.g. frequency) to create the spline.
//
//////////////////////////////////////////////////////////////////////////////
#include "MSpline3.h"

#include <TF1.h>

ClassImp(MSpline3);

using namespace std;

// --------------------------------------------------------------------------
//
//  Constructor.
//
MSpline3::MSpline3(const TF1 &f, const char *opt, Double_t valbeg, Double_t valend)
    : TSpline3("MSpline3", f.GetXmin(), f.GetXmax(), &f, f.GetNpx(), opt, valbeg, valend)
{
}

// --------------------------------------------------------------------------
//
//  This is a helper to convert the x-values by multiplying with freq
// before initializing the spline
//
TGraph *MSpline3::ConvertSpline(const TSpline &s, Float_t freq) const
{
    const UInt_t npx = s.GetNpx();

    // WARNING: This is a stupid workaround because the TSpline3-
    // constructor takes a pointer as input! It is not thread-safe!
    static TGraph g;
    g.Set(npx);

    for (UInt_t i=0; i<npx; i++)
    {
        Double_t x, y;
        s.GetKnot(i, x, y);
        g.SetPoint(i, x*freq, y);
    }

    return &g;
}

// --------------------------------------------------------------------------
//
//  This is a helper to convert the x-values by multiplying with freq
// before initializing the spline
//
TGraph *MSpline3::ConvertGraph(const TGraph &s, Float_t freq) const
{
    const UInt_t npx = s.GetN();

    // WARNING: This is a stupid workaround because the TSpline3-
    // constructor takes a pointer as input! It is not thread-safe!
    static TGraph g;
    g.Set(npx);

    for (UInt_t i=0; i<npx; i++)
    {
        Double_t x, y;
        s.GetPoint(i, x, y);
        g.SetPoint(i, x*freq, y);
    }

    return &g;
}

// --------------------------------------------------------------------------
//
//  This is a helper to convert the x-values by multiplying with freq
// before initializing the spline. The conversion from the function to
// a discrete binning is done similar to the constructor of TSpline
//
TGraph *MSpline3::ConvertFunc(const TF1 &f, Float_t freq) const
{
    const UInt_t npx = f.GetNpx();

    // WARNING: This is a stupid workaround because the TSpline3-
    // constructor takes a pointer as input! It is not thread-safe!
    static TGraph g;
    g.Set(npx);

    const Double_t step = (f.GetXmax()-f.GetXmin())/(npx-1);

    for (UInt_t i=0; i<npx; ++i)
    {
        const Double_t x = f.GetXmin() + i*step;
        g.SetPoint(i, x*freq, f.Eval(x));
    }

    return &g;
}
