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

/////////////////////////////////////////////////////////////////////////////
//
// MFEventSelector
//
// This is a filter to make a selection of events from a file. At the
// present implementation you can only use a random selection.
//
// If you want to fill only 50% of your events into a histogram please use:
//   MFEventSelector sel;
//   sel.SetSelectionRatio(0.5);
//   MFillH filler(...);
//   filler.SetFilter(&sel);
//   tlist.AddToList(&sel);
//   tlist.AddToList(&filler);
//
// To get around 2000 events from all events use (Remark: This will only
// work if the parlist has an entry called MTaskList which has a task
// MRTeadTree inheriting from MReadTree):
//   MFEventSelector sel;
//   sel.SetNumSelectEvents(2000);
//   MFillH filler(...);
//   filler.SetFilter(&sel);
//   tlist.AddToList(&sel);
//   tlist.AddToList(&filler);
//
// If you don't have MReadTree available you have to set the number of
// total events manually, using sel.SetNumTotalEvts(10732);
//
// The random number is generated using gRandom->Uniform(). You may
// control this procedure using the global object gRandom.
//
// Because of the random numbers this works best for huge samples...
//
// Don't try to use this filter for the reading task: This won't work!
//
// Remark: You can also use the filter together with MContinue
//
/////////////////////////////////////////////////////////////////////////////
#include "MFEventSelector.h"

#include <TRandom.h>

#include "MParList.h"
#include "MTaskList.h"
#include "MReadTree.h"

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

ClassImp(MFEventSelector);

static const TString gsDefName  = "MFEventSelector";
static const TString gsDefTitle = "Filter to select events";

// --------------------------------------------------------------------------
//
// Default Constructor. Don't use.
//
/*
MFEventSelector::MFEventSelector()
    : fNumTotalEvts(-1), fNumSelectEvts(-1), fSelRatio(-1), fNumSelectedEvts(0)
{
    fName  = gsDefName.Data();
    fTitle = gsDefTitle.Data();
}
*/
// --------------------------------------------------------------------------
//
// Constructor. For the text describing the filter rule please see
// the class description above.
//
MFEventSelector::MFEventSelector(const char *name, const char *title)
: fNumTotalEvts(-1), fNumSelectEvts(-1), fSelRatio(-1), fNumSelectedEvts(0)
{
    fName  = name  ? name  : gsDefName.Data();
    fTitle = title ? title : gsDefTitle.Data();
}

// --------------------------------------------------------------------------
//
// Destructor. Delete filters.
//
MFEventSelector::~MFEventSelector()
{
}

// --------------------------------------------------------------------------
//
// PreProcess all filters.
//
Bool_t MFEventSelector::PreProcess(MParList *plist)
{
    fNumSelectedEvts = 0;
    if (fSelRatio>0)
        return kTRUE;

    if (fNumTotalEvts<0)
    {
        MTaskList *tlist = (MTaskList*)plist->FindObject("MTaskList");
        if (!tlist)
        {
            *fLog << err << dbginf << "Sorry can't determin total number of events... no MTaskList." << endl;
            return kFALSE;
        }
        MReadTree *read = (MReadTree*)tlist->FindObject("MReadTree");
        if (!read)
            read = (MReadTree*)tlist->FindObject("MReadMarsFile");
        if (!read)
        {
            *fLog << err << dbginf << "Sorry can't determin total number of events from 'MReadTree/MReadMarsFile'." << endl;
            return kFALSE;
        }
        fNumTotalEvts = read->GetEntries();
    }

    return kTRUE;
}

// --------------------------------------------------------------------------
//
// Process all filters.
//
Bool_t MFEventSelector::Process()
{
    Float_t evt = gRandom->Uniform();

    if (fNumSelectEvts>0)
        fResult = evt*fNumTotalEvts < fNumSelectEvts;
    else
        fResult = evt < fSelRatio;

    if (fResult)
        fNumSelectedEvts++;

    return kTRUE;
}

// --------------------------------------------------------------------------
//
//  Postprocess all filters.
//
Bool_t MFEventSelector::PostProcess()
{
    return kTRUE;
}

void MFEventSelector::StreamPrimitive(ofstream &out) const
{
    /*
    out << "   MF " << GetUniqueName();

    if (!fFilter)
    {
        out << ";" << endl;
        return;
    }

    out << "(\"" << fFilter->GetRule() << "\"";
        if (fName!=gsDefName || fTitle!=gsDefTitle)
    {
        out << "(\"" << fName << "\"";
        if (fTitle!=gsDefTitle)
            out << ", \"" << fTitle << "\"";
    }
    out << ");" << endl;
    */

}

