/**************************************************************************/
/*   A CLASS TO MAKE CUTS ON EVENTS                                       */
/*   PATRICIA VAHLE                                                       */
/*   DECEMBER 14, 2001                                                    */
/**************************************************************************/

#ifndef CUTTER_H
#define CUTTER_H

#include <string>
#include <map>
#include <set>
#include "JobControl/JobCModule.h"
#include "TH1.h"
#include "TCanvas.h"

class JobCResult;
class MomNavigator;
class RawRecord;

#include "CalDetSI/CandCalDetSIHandle.h"
#include "CalDetSI/Helpers.h"
const int fNCuts = 19;  //evil and vile, quick fix.  Must be incremented when new cuts are added

class Cutter : public JobCModule
{

public:

     typedef bool (Cutter::* CP)() const;
     
     Cutter();  //constructor
     ~Cutter(); //destructor
     
     //JobCResults methods
     virtual JobCResult Get(MomNavigator* mom);          //gets the data from mom
     virtual JobCResult Ana(const MomNavigator* mom);    //runs the cutters  
     virtual void HandleCommand(JobCommand *cmd);

     const Registry& DefaultConfig() const;
     void            Config(const Registry& r);

     
     void SetCuts();

     //Cutters should return true if the event passes the cut, false otherwise
     //ie. true if we want to analyze the event

     //A method that cuts out sparsification errors
     bool SparseErrorCutter() const;
     
     //A method that cuts out faf errors
     bool FafErrorCutter() const;
     
     //A method that cuts on the trigger (ie plane trigger)
     bool TriggerCutter() const;
     
     //A method that cuts out events with trigger PMT signal
     bool TrigPMTCutter() const;
     
     //A method that cuts out events with cosmic counter signal
     bool CosmicCounterCutter() const;
     
     //A method that cuts out dead chips
     bool DeadChipCutter() const;
     
     //A method that cuts out over shoot chips
     bool OverShootCutter() const;
     
     //A method that cuts on events that have a Cerenkov hit
     bool KovCutter() const;
     
     //A method that cuts on events that have a non-zero TDC reading
     bool TOFCutter() const;

     //A method that cuts on events that have a TOF trigger  
     bool TOFTrigCutter() const;

     //A method that cuts on events that have a Cer1 trigger
     bool Kov1TrigCutter() const; 

     //A method that cuts on events that have a Cer2 trigger
     bool Kov2TrigCutter() const;

     //A method that cuts on events that have a Cer3 trigger
     bool Kov3TrigCutter() const;

     //A method that cuts on events that have a Cer trigger
     bool KovORTrigCutter() const;

     //A method that cuts on events that have both a CER1 and CER2 trigger
     bool AllKovTrigCutter() const;

     //A method to veto LI events
     bool LITrigCutter() const;

     //A method to accept TOF or any kov trigger
     bool PIDOrTrigCutter() const;

     //A method to cut events with dead cerenkov chips
     bool DeadKovCutter() const;

// A method to cut events with ND errors
bool NDErrorCutter() const;

     //a dummy cut so that others can be skipped
     bool DummyCutter() const {return true;}
     
     //Other Cutters go here
     
     //The Getters
     int GetDCPlaneCut() const {return fDCPlaneCut;}   //get the plane cut on dead chips
     int GetMinOST() const {return fMinOST;}           //get the minimum overshoot time
     const TH1F *GetCutHistogram() const {return &fCutHistogram;} //get the cut Histogram
     
     //Methods to draw and write the cut histogram
     void DrawCutHistogram();
     void WriteCutHistogram();

private:
     bool fSparseErrCut;   //execute sparsification error cut?
     bool fFafErrCut;     //execute Faf error cut?
     bool fTrigCut;       //execute trigger cut?
     bool fTPMTCut;       //execute trigger pmt cut?
     bool fCCCut;         //execute cosmic counter cut?
     bool fDCCut;         //execute dead chip cut?
     bool fOSCut;         //execute overshoot time cut?
     bool fKovCut;        //execute kov cut?
     bool fTOFCut;        //execute TOF cut?
     bool fTOFTrigCut;    //execute TOF trigger cut?
     bool fKov1TrigCut;   //execute Kov1 trigger cut?
     bool fKov2TrigCut;   //execute kov2 trigger cut?
     bool fKov3TrigCut;
     bool fKovORTrigCut;
     bool fAllKovTrigCut; //execute both kov trigger cut?
     bool fLITrigCut;  //  execute LI trig cut?
     bool fPIDOrTrigCut;
     bool fDeadKovCut;
     bool fNDErrorCut; // execute NDErrorCutter

     bool fDrawHist;      //draw the histogram?
     bool fWriteHist;     //write the histogram to a file?
     bool fWait;          //wait for display after an event that passes all cuts?

     bool fCutsSet;   //are the cuts set?
     // static const int fNCuts;          //number of cuts to perform
     int fKovADCCutLow1;     //lower limit on passisng Kov adc
     int fKovADCCutHigh1;    //upper limit on passing Kov adc
     int fKovADCCutLow2;     //lower limit on passisng Kov adc
     int fKovADCCutHigh2;    //upper limit on passing Kov adc
     int fKovADCCutLow3;     //lower limit on passisng Kov adc
     int fKovADCCutHigh3;    //upper limit on passing Kov adc

     int fDCPlaneCut;    //a plane less than which there should be no dead chips
     int fMinOST;        //a minumum allowable overshoot time

     int fFrequency;      //freqency of histogram update
     int fCounter;        //to keep track of how many events have been processed
     std::string fFileName;    //filename in which to save cut histogram
     int fRunNumber;
     std::string fBinLabel[fNCuts+1]; //list of bin labels
     RawRecord* fRR; //pointer to the current raw record
     CandCalDetSIHandle *fCCDH; //pointer to candidate caldetSI handle
     TH1F fCutHistogram; //a histogram to store cut statistics
     TCanvas fCanvas;    //a canvas to draw the histogram on
     CP fCutList[fNCuts]; //list of cuts to perform
     std::set<RawChannelId> fChipsToCut; // a set of deadchips with plane<fDCPlaneCut
     bool fFilledChipsToCut; // true if fFilledChipsToCut has been filled
     void FillChipsToCut();
};

//A method that cuts out errors
inline bool Cutter::SparseErrorCutter() const
{
  if(fCCDH->GetSparseErr()){ //true if there are sparse errs
    return false;
  }

  return true; //if we get here, no errors, passes cut
}//end SparseErrorCutter()

//--------------------------------------------------------------------------------------

//A method that cuts out faf errors
inline bool Cutter::FafErrorCutter() const
{

  if(fCCDH->GetFafErr()){ //true if there is a faf error
    return false;
  }

  return true; //if we get here, no errors, passes cut
}//end FafErrorCutter()

//------------------------------------------------------------------------------------

//A method that cuts on the trigger (ie plane trigger)
inline bool Cutter::TriggerCutter() const
{

  // cout<<hex<<fCCDH->GetTrigSource()<<dec<<endl;
  if(fCCDH->GetTrigSource()&0x04){ //plane trigger
    if((fCCDH->GetTrigSource()>>8)>1){
      //cout<<"PASSED TRIGGER CUT"<<endl;
      return true; //2/3 plane trigger
    }
    else{
      return false;
    }
  }
  else{ //otherwise it fails
    return false;
  }

}//End TriggerCutter()

//-------------------------------------------------------------------------------------

//A method that cuts out events with trigger PMT signal
inline bool Cutter::TrigPMTCutter() const
{
  
  if(fCCDH->GetTriggerPMT()){ //true if there is a trigger pmt signal
    return false;
  }

  return true;

} //end TrigPMTCutter

//-------------------------------------------------------------------------------------

//A method that cuts out events with cosmic counter signal
inline bool Cutter::CosmicCounterCutter() const
{

  if(fCCDH->GetCosmicCnt()){//true if there is a cosmic cnt signal
    return false;
  }
  return true;

}//end CosmicCntCutter

//------------------------------------------------------------------------------------

inline bool Cutter::KovCutter() const
{

  if((fCCDH->GetKovADC1()>fKovADCCutLow1&&fCCDH->GetKovADC1()<fKovADCCutHigh1)
     ||(fCCDH->GetKovADC2()>fKovADCCutLow2&&fCCDH->GetKovADC2()<fKovADCCutHigh2)||(fCCDH->GetKovADC3()>fKovADCCutLow3&&fCCDH->GetKovADC3()<fKovADCCutHigh3)){//if there is non-zero adc on cernekov, there was a hit in kov
    return true;
  }
  return false;

} //end KovCutter

//______________________________________________________________________

inline bool Cutter::TOFCutter() const
{

  if(fCCDH->GetTofTDC0()>0||fCCDH->GetTofTDC1()>0||fCCDH->GetTofTDC2()>0){
    return true;
  }

  return false;

}//end TOFCut

//_____________________________________________________________________

inline bool Cutter::TOFTrigCutter() const
{

  if(fCCDH->GetTrigSource()&0x08){
    return true;
  }

  return false;
}//end TOFTrigCutter()

//_____________________________________________________________________

inline bool Cutter::Kov1TrigCutter() const
{

  if(fCCDH->GetTrigSource()&0x10){
    return true;
  }

  return false;
}//end Kov1TrigCutter()

//_____________________________________________________________________

inline bool Cutter::Kov2TrigCutter() const
{

  if(fCCDH->GetTrigSource()&0x20){
    return true;
  }
 
  return false;
}//end Kov2TrigCutter()

//_____________________________________________________________________
inline bool Cutter::Kov3TrigCutter() const
{

  if(fCCDH->GetTrigSource()&0x40){
    return true;
  }
 
  return false;
}//end Kov3TrigCutter()

//_____________________________________________________________________

inline bool Cutter::KovORTrigCutter() const
{

  if(fCCDH->GetTrigSource()&0x10||fCCDH->GetTrigSource()&0x20
     ||fCCDH->GetTrigSource()&0x40){
    return true;
  }
 
  return false;
}//end KovORTrigCutter()

//_____________________________________________________________________


inline bool Cutter::AllKovTrigCutter() const
{

  if((fCCDH->GetTrigSource()&0x10)&&(fCCDH->GetTrigSource()&0x20)
&&fCCDH->GetTrigSource()&0x40){
    return true;
  }

  return false;
}//end AllKovTrigCutter()

//_____________________________________________________________________
inline bool Cutter::LITrigCutter() const
{

  if(fCCDH->GetTrigSource()&0x02){
    return false;
  }
  
  return true;
}//end LITrigCutter()

//_____________________________________________________________________

inline bool Cutter::PIDOrTrigCutter() const
{

  if(fCCDH->GetTrigSource()&0x08
     ||fCCDH->GetTrigSource()&0x10
     ||fCCDH->GetTrigSource()&0x20
     ||fCCDH->GetTrigSource()&0x40){
    return true;
  }

  return false;
}//end PIDOrTrigCutter
//__________________________________________________________________________



#endif //CUTTER_H














