/* ======================================================================== *\
!
! *
! * 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): Markus Gaug  09/2003 <mailto:markus@ifae.es>
!
!   Copyright: MAGIC Software Development, 2000-2001
!
!
\* ======================================================================== */

//////////////////////////////////////////////////////////////////////////////
//                                                                          //
//   MExtractSignal                                                         //
//                                                                          //
//////////////////////////////////////////////////////////////////////////////

#include "MExtractSignal.h"

#include "MExtractedSignalCam.h"
#include "MExtractedSignalPix.h"

#include "MPedestalCam.h"
#include "MPedestalPix.h"

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

#include "MParList.h"
#include "MH.h"

#include "MRawRunHeader.h"
#include "MRawEvtData.h"       // MRawEvtData::GetNumPixels
#include "MRawEvtPixelIter.h"

#include "TMath.h"

ClassImp(MExtractSignal);

using namespace std;
// --------------------------------------------------------------------------
//
// Default constructor. 
//
MExtractSignal::MExtractSignal(const char *name, const char *title)
  : fSaturationLimit(250),
    fConversionHiLo(10.)
{

    fName  = name  ? name  : "MExtractSignal";
    fTitle = title ? title : "Task to extract the signal from the FADC slices";

    AddToBranchList("MRawEvtData.*");
}

// --------------------------------------------------------------------------
//
// The PreProcess searches for the following input containers:
//  - MRawEvtData
//  - MPedestalCam
//
// The following output containers are also searched and created if
// they were not found:
//
//  - MExtractedSignalCam
//
Int_t MExtractSignal::PreProcess(MParList *pList)
{

    fRawEvt = (MRawEvtData*)pList->FindObject("MRawEvtData");
    if (!fRawEvt)
    {
        *fLog << dbginf << "MRawEvtData not found... aborting." << endl;
        return kFALSE;
    }

    const MRawRunHeader *runheader = (MRawRunHeader*)pList->FindObject("MRawRunHeader");
    if (!runheader)
        *fLog << warn << dbginf << "Warning - cannot check file type, MRawRunHeader not found." << endl;


    fSignals = (MExtractedSignalCam*)pList->FindCreateObj("MExtractedSignalCam");
    if (!fSignals)
        return kFALSE;

    fPedestals = (MPedestalCam*)pList->FindObject("MPedestalCam");
    if (!fPedestals)
      {
        *fLog << err << dbginf << "Cannot find MPedestalCam ... aborting" << endl;
        return kFALSE;
      }
    
    return kTRUE;
}


// --------------------------------------------------------------------------
//
// The ReInit searches for the following input containers:
//  - MRawRunHeader
//
Bool_t MExtractSignal::ReInit(MParList *pList )
{
 
    fRunHeader = (MRawRunHeader*)pList->FindObject("MRawRunHeader");
    if (!fRunHeader)
    {
        *fLog << dbginf << "MRawRunHeader not found... aborting." << endl;
        return kFALSE;
    }

    fNumHiGainSamples =  fRunHeader->GetNumSamplesHiGain();
    fNumLoGainSamples =  fRunHeader->GetNumSamplesLoGain();
    fSqrtHiGainSamples =  TMath::Sqrt((float)fNumHiGainSamples);
    fSqrtLoGainSamples =  TMath::Sqrt((float)fNumLoGainSamples);

    //
    // FIXME: The next statement simply does not work: 
    //        fRawEvt->GetNumPixels() returns always 0
    //

    fSignals->InitSize(577);    
    // fExtractedSignals->InitSize(fRawEvt->GetNumPixels());

    return kTRUE;
}


// --------------------------------------------------------------------------
//
// Calculate the integral of the FADC time slices and store them as a new
// pixel in the MExtractedSignalCam container.
//
Int_t MExtractSignal::Process()
{

    MRawEvtPixelIter pixel(fRawEvt);
    fSignals->Clear();

    while (pixel.Next())
      {

        UShort_t satHi = 0;
        UShort_t satLo = 0;
	Float_t  sum   = 0.;
	Float_t sumerr = 0.;

        const Int_t pixid = pixel.GetPixelId();
        const MPedestalPix  &ped = (*fPedestals)[pixid]; 
	MExtractedSignalPix &pix = (*fSignals)[pixid];

        const Float_t pedes   = ped.GetPedestal();
        const Float_t pedrms  = ped.GetPedestalRms();

        //
        // FIXME: This is preliminary, we will change to pedestals per slice!!!
        // Assume pedestals per time slice ==> multiply with number of slices
        //

        UInt_t max  = pixel.GetMaxHiGainSample();

	if (max < fSaturationLimit)  // take Hi Gain, no saturation
	  {
	    sum = (float)pixel.GetSumHiGainSamples() - pedes*fNumHiGainSamples;  
	    sumerr = pedrms*fSqrtHiGainSamples; 
	  }
	else 	                      // Lo Gain
	  {

	    satHi++;

	    sum = (float)pixel.GetSumLoGainSamples() - pedes*fNumLoGainSamples ;
	    sum *= fConversionHiLo; 

	    sumerr = pedrms*fSqrtLoGainSamples; 

            max = pixel.GetMaxLoGainSample();

	    if (max > fSaturationLimit)
	      {
		*fLog << err << dbginf 
		      << "Warning: Saturation of Lo Gain reached in pixel: " 
		      << pixid << " " << "   sum = " << sum << endl;
		satLo++;
	      }

	  }

	pix.SetGainSaturation((satHi),(satHi),(satLo));
	pix.SetExtractedSignal(sum,sumerr);

      } /* while (pixel.Next()) */

    fSignals->SetReadyToSave();

    return kTRUE;
}

Int_t MExtractSignal::PostProcess()
{

  return kTRUE;

}
