/* ======================================================================== *\
!
! *
! * 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): Wolfgang Wittek, 04/2003 <mailto:wittek@mppmu.mpg.de>
!   Author(s): Thomas Bretz, 04/2003 <mailto:tbretz@astro.uni-wuerzburg.de>
!
!   Copyright: MAGIC Software Development, 2000-2003
!
!
\* ======================================================================== */

/////////////////////////////////////////////////////////////////////////////
//
//  MFSoftwareTrigger
//
//  This is a class to evaluate a software trigger
//
//  to be called after the calibration (when the number of photons is
//               available for all pixels)
//
// require 2 neighboring pixels (which are not in the outermost ring),
//                       each having at least 'fNumMinPhotons' photons
//
//
/////////////////////////////////////////////////////////////////////////////
#include "MFSoftwareTrigger.h"

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

#include "MParList.h"

#include "MGeomPix.h"
#include "MGeomCam.h"

#include "MCerPhotEvt.h"

ClassImp(MFSoftwareTrigger);

using namespace std;

// --------------------------------------------------------------------------
//
// Default constructor.
//
MFSoftwareTrigger::MFSoftwareTrigger(const char *name, const char *title)
    : fNumMinPhotons(0), fNumNeighbors(2)
{
    fName  = name  ? name  : "MFSoftwareTrigger";
    fTitle = title ? title : "Filter for software trigger";
}

// --------------------------------------------------------------------------
//
// Software trigger
// 
// require 2 neighboring pixels (which are not in the outermost ring), 
//                       each having at least 'fNumMinPhotons' photons
// 
Bool_t MFSoftwareTrigger::SwTrigger() const
{
    const Int_t entries = fEvt->GetNumPixels();
 
    for (Int_t i=0; i<entries; i++)
    {
        const MCerPhotPix &pix = (*fEvt)[i];
        if (!pix.IsPixelUsed())
            continue;

        if (pix.GetNumPhotons()<fNumMinPhotons)
            continue;

        // this pixel is used and has the required no.of photons
        // check whether this is also true for a neigboring pixel
        MGeomPix &gpix = (*fCam)[pix.GetPixId()];
        if (gpix.IsInOutermostRing())
            continue;

        Int_t num = 1;

        const Int_t nneighbors = gpix.GetNumNeighbors();
        for (Int_t n=0; n<nneighbors; n++)
        {
            const Int_t id = gpix.GetNeighbor(n);
            if (!fEvt->IsPixelUsed(id))
                continue;

            if ((*fCam)[id].IsInOutermostRing())
                continue;

            const Double_t photons = fEvt->GetPixById(id)->GetNumPhotons();
            if (photons >= fNumMinPhotons)
                if (++num==fNumNeighbors)
                    return kTRUE;
        }
    }
    return kFALSE;
}

// --------------------------------------------------------------------------
//
// Request pointer to MCerPhotEvt and MGeomCam from paremeter list
//
Int_t MFSoftwareTrigger::PreProcess(MParList *pList)
{
    fEvt = (MCerPhotEvt*)pList->FindObject("MCerPhotEvt");
    if (!fEvt)
    {
        *fLog << err << "MCerPhotEvt not found... aborting." << endl;
        return kFALSE;
    }

    fCam = (MGeomCam*)pList->FindObject("MGeomCam");
    if (!fCam)
    {
        *fLog << err << "MGeomCam not found... aborting." << endl;
        return kFALSE;
    }

    memset(fCut, 0, sizeof(fCut));

    return kTRUE;
}

// --------------------------------------------------------------------------
//
// Evaluate software trigger
//
Int_t MFSoftwareTrigger::Process()
{
    fResult = SwTrigger();

    fCut[fResult ? 0 : 1]++;
    return kTRUE;
}

// --------------------------------------------------------------------------
//
//  Prints some statistics about the Basic selections.
//
Int_t MFSoftwareTrigger::PostProcess()
{
    if (GetNumExecutions()==0)
        return kTRUE;

    *fLog << inf << endl;
    *fLog << GetDescriptor() << " execution statistics:" << endl;
    *fLog << dec << setfill(' ');

    *fLog << " " << setw(7) << fCut[1] << " (" << setw(3) ;
    *fLog << (int)(fCut[1]*100/GetNumExecutions()) ;
    *fLog << "%) Evts skipped due to: Software trigger not fullfilled" ;
    *fLog << " (NumPhotons>=" << fNumMinPhotons << ", NumNeighbors>=";
    *fLog << fNumNeighbors << ")" << endl;

    *fLog << " " << fCut[0] << " (" << (int)(fCut[0]*100/GetNumExecutions()) ;
    *fLog << "%) Evts survived software trigger!" << endl;
    *fLog << endl;

    return kTRUE;
}
