/* ======================================================================== *\
!
! *
! * 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/2002 <mailto:tbretz@uni-sw.gwdg.de>
!   Author(s): Wolfgang Wittek 1/2002 <mailto:wittek@mppmu.mpg.de>
!
!   Copyright: MAGIC Software Development, 2000-2002
!
!
\* ======================================================================== */

/////////////////////////////////////////////////////////////////////////////
//
// MEnergyEstimate
//
// Task to estimate the energy by a rule, eg:
//
// MEnergyEstimate est;
// est.SetRule("0.5 + (1.1*MHillas.fLength) + (2.2*MHillasSrc.fDist) + (3.3*MHillas.fSize) +"
//             "(4.4*MHillas.fSize*MHillas.fLength) + (5.5*MHillasSrc.fDist*MHillas.fLength)");
//
// For description of rules, see MDataChain.
//
// The default rule is "MMcEvt.fEnergy"
//
// Output:
//   MEnergyEst
//
/////////////////////////////////////////////////////////////////////////////
#include "MEnergyEstimate.h"

#include "MParList.h"

#include "MDataChain.h"
#include "MParameters.h"

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

ClassImp(MEnergyEstimate);

using namespace std;

// --------------------------------------------------------------------------
//
// Default constructor. Initialize fData with default rule "MMcEvt.fEnergy"
//
MEnergyEstimate::MEnergyEstimate(const char *name, const char *title)
    : fData(0), fEnergy(0)
{
    fName  = name  ? name  : "MEnergyEstimate";
    fTitle = title ? title : "Task to estimate the energy by a rule";

    fData = new MDataChain("MMcEvt.fEnergy");
}

// --------------------------------------------------------------------------
//
// delete fData
//
MEnergyEstimate::~MEnergyEstimate()
{
    delete fData;
}

// --------------------------------------------------------------------------
//
// Delete fData. Initialize a new MDataChain with rule.
// Returns if fData->IsValid()
//
Bool_t MEnergyEstimate::SetRule(const char *rule)
{
    delete fData;
    fData = new MDataChain(rule);

    return fData->IsValid();
}

// --------------------------------------------------------------------------
//
// Forwards SetVariables to fData to allow optimizations.
//
void MEnergyEstimate::SetVariables(const TArrayD &arr)
{
    fData->SetVariables(arr);
}

// --------------------------------------------------------------------------
//
// FindCreate "MEnergyEst"
// PreProcess fData.
//
Int_t MEnergyEstimate::PreProcess(MParList *plist)
{
    fEnergy = (MParameterD*)plist->FindCreateObj("MParameterD", "MEnergyEst");
    if (!fEnergy)
        return kFALSE;

    *fLog << inf << "Rule for energy estimation: " << fData->GetRule() << endl;

    if (!fData->PreProcess(plist))
        return kFALSE;

    return kTRUE;
}

// --------------------------------------------------------------------------
//
// Get value from fData and set it to fEnergy. SetReadyToSave for fEnergy.
// Return kCONTINUE if value is NaN (Not a Number)
//
Int_t MEnergyEstimate::Process()
{
    const Double_t val = fData->GetValue();
    if (TMath::IsNaN(val))
        return kCONTINUE;

    fEnergy->SetVal(val);
    fEnergy->SetReadyToSave();
    return kTRUE;
}

// --------------------------------------------------------------------------
//
// Print the rule used for energy estimation
//
void MEnergyEstimate::Print(Option_t *o) const
{
    *fLog << all << GetDescriptor() << ":";
    if (!fData)
        *fLog << " <n/a>" << endl;
    else
        *fLog << endl << fData->GetRule() << endl;
}

// --------------------------------------------------------------------------
//
// Check for corresponding entries in resource file and setup filters.
// Avoid trailing 0's!
//
// Example:
//   test.C:
//     MEnergyEstimate est("MyEstimator");
//
//   test.rc:
//     MyEstimator.Rule: {0} + {1}
//     MyEstimator.0: log10(MHillas.fSize)
//     MyEstimator.1: 5.5
//
// For more details see MDataChain::ReadEnv
//
Int_t MEnergyEstimate::ReadEnv(const TEnv &env, TString prefix, Bool_t print)
{
    MDataChain *f = new MDataChain;
    f->SetName(fName);

    const Bool_t rc = f->ReadEnv(env, prefix, print);
    if (rc!=kTRUE)
    {
        delete f;
        return rc;
    }

    delete fData;
    fData = f;

    if (!fData->IsValid())
    {
        *fLog << err << "MEnergyEst::ReadEnv - ERROR: Inavlid rule from resource file." << endl;
        return kERROR;
    }

    return kTRUE;
}
