#include "MImgCleanStd.h"

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

#include "MParList.h"
#include "MCerPhotPix.h"
#include "MCerPhotEvt.h"
#include "MCamNeighbor.h"

ClassImp(MImgCleanStd)

MImgCleanStd::MImgCleanStd(const char *name, const char *title)
{
    //
    //   the default constructor
    //
  
    *fName  = name  ? name  : "MImgCleanStd";
    *fTitle = name  ? name  : "Task which does a standard image cleaning";
}

void MImgCleanStd::CleanLevel1()
{
    //
    //  This method looks for all pixels with an entry (photons)
    //  that is three times bigger than the noise of the pixel
    //

    const Int_t entries = fEvt->GetNumPixels();

    //
    // check the number of all pixels against the noise level and
    // set them to 'unused' state if necessary
    //
    for (Int_t il=0; il<entries; il++ )
    {
        MCerPhotPix &pix = (*fEvt)[il];

        const Float_t entry = pix.GetNumPhotons();
        const Float_t noise = pix.GetErrorPhot();

        if (entry < 3 * noise )
            pix.SetPixelUnused();
    }
}

void MImgCleanStd::CleanLevel2()
{
    //
    //  check if the  survived pixel have a neighbor, that also
    //  survived
    //

    const Int_t entries = fEvt->GetNumPixels();

    for (Int_t il=0; il<entries; il++)
    {
        //
        // get entry il from list
        //
        MCerPhotPix &pix = (*fEvt)[il];

        //
        // check if pixel is in use, if not goto next pixel in list
        //
        if (!pix.IsPixelUsed())
            continue;

        //
        // get pixel id of this entry
        //
        const Int_t id = pix.GetPixId() ;

        //
        // count number of next neighbors of this pixel which
        // state is 'used'
        //
        Int_t itest = 0 ;
        for (Int_t in=0 ; in < 6; in++ )
        {
            const Int_t id2 = fNN.GetNN(id, in) ;

            if (id2 < 0)
                continue;

            if (fEvt->IsPixelUsed(id2))
                itest++ ;
        }

        //
        // check if no next neighbor has the state 'used'
        // set this pixel to 'unused', too.
        //
        if (itest==0)
            pix.SetPixelUnused();
    }

    //
    // now we declare all pixels that survive as CorePixels
    //
    for (Int_t il=0; il<entries; il++)
    {
        MCerPhotPix &pix = (*fEvt)[il];

        if (pix.IsPixelUsed())
            pix.SetCorePixel();
    }

} 

void MImgCleanStd::CleanLevel3()
{
    //
    //   Look for the boundary pixels around the core pixels
    //   if a pixel has more than 2.5 sigma, and a core neigbor
    //   it is declared as used.
    //
    const Int_t entries = fEvt->GetNumPixels();

    for (Int_t il=0; il<entries; il++)
    {
        //
        // get pixel as entry il from list
        //
        MCerPhotPix &pix = (*fEvt)[il];

        //
        // if pixel is a core pixel go to the next pixel
        //
        if (pix.IsCorePixel())
            continue;

        //
        // check the num of photons against the noise level
        //
        const Float_t entry = pix.GetNumPhotons();
        const Float_t noise = pix.GetErrorPhot();

        if (entry <= 2.5 * noise )
            continue;

        //
        // get pixel id of this entry
        //
        const Int_t id = pix.GetPixId();

        //
        // check if the pixel's next neighbor is a core pixel.
        // if it is a core pixel set pixel state to: used.
        //
        for (Int_t in=0; in<6 ; in++)
        {
            const Int_t id2 = fNN.GetNN(id, in);

            if (id2 <0)
                continue;

            if (!fEvt->IsPixelCore(id2))
                continue;

            pix.SetPixelUsed();

            break ;
        }
    }
}

Bool_t MImgCleanStd::PreProcess (MParList *pList)
{
    //
    //  check if MEvtHeader exists in the Parameter list already.
    //  if not create one and add them to the list
    //
    fEvt = (MCerPhotEvt*)pList->FindObject("MCerPhotEvt");
    if (fEvt)
        return kTRUE;

    *fLog << dbginf << "MCerPhotEvt not found... aborting." << endl;
    return kFALSE;
}
    
Bool_t MImgCleanStd::Process()
{
    CleanLevel1();
    CleanLevel2();
    CleanLevel3();

    return kTRUE;
}

