#ifndef HMDCOFFSET_H
#define HMDCOFFSET_H
#include "hreconstructor.h"
#include "hstartdef.h"
#include "hmdctimecut.h"
#include "hlocation.h"
typedef Int_t   MyInt;
typedef Float_t MyFloat;
typedef TH1F    MyHist;
class TFile;
class HCategory;
class HIterator;
class HMdcCalPar;
class HMdcCalParRaw;
class HMdcLookupGeom;
class HMdcLookupRaw;
class HMdcTimeCut;
class HMdcSizesCells;
class TH2F;
class TNtuple;
class TF1;
class TString;
typedef MyInt MyField[6][4][16][96][2048];
class HMdcOffset : public HReconstructor {
protected:
    static const Int_t nbin;            
    static const Int_t nbinm1;          
    static const Int_t nbinp1;          
    static const Int_t nSubEvents;      
    HCategory*         rawCat;          
    HCategory*         hitStartCat;     
    HCategory*         clusCat;         
    HIterator*         iter;            
    HIterator*         iter_start;      
    HIterator*         iter_clus;       
    HLocation          locraw;          
    HMdcCalParRaw*     calparraw;       
    HMdcTimeCut*       timecut;         
    HMdcLookupGeom*    lookupgeom;      
    HMdcLookupRaw*     lookupraw;       
    HMdcSizesCells*    sizescells;      
    Float_t   signalspeed;              
    Int_t     eventcounter;
    Int_t     skipcounter;
    Int_t     nSkipEvents;              
    Int_t     nStep;                    
    Float_t   validRange;               
    Bool_t    isPulserFile;             
    Bool_t    noStart;                  
    Bool_t    useTimeCuts;              
    Bool_t    useClusters;              
    Bool_t    useWireOffset;            
    Bool_t    useTof;                   
    Bool_t    fillHistsOnly;            
    Bool_t    readHists;                
    Bool_t    perMBO;                   
    Bool_t    perMBOafterSingle;        
    Float_t   filterwindow1;            
    Float_t   filterwindow2;            
    Int_t     filenumber;               
    Char_t*   fNameAsciiOffset;         
    Char_t*   fNameRootOffset;          
    FILE*     ferrorlog;                
    TNtuple*  offsetTuple;              
    TNtuple*  offsetPulserTuple;        
    Float_t   minfitthreshold;          
    Float_t   maxfitthreshold;          
    Int_t     offsetfitNoise;           
    Int_t     widthfitNoise;            
    Bool_t    fitNoise;                 
    Int_t     rangeGauss;               
    Int_t     cleanThreshold;           
    Float_t   cutT1L [4];                
    Float_t   cutT1R [4];                
    Float_t   cutT12 [4];                
    Bool_t    useCuts;                  
    MyField*  hreverse;                 
    MyHist*   hinv;                     
    MyHist*   hint;                     
    MyHist*   htime1temp;               
    TH2F*     htime1_mbo        [16];   
    TH2F*     htime1_lay         [6];   
    TH2F*     htime1_lay_inv_norm[6];   
    TH2F*     htime1_lay_int     [6];   
    TH2F*     htime1_lay_int_norm[6];   
    TF1*      toffunc         [4][6];   
    MyFloat   yequalzero;               
    MyFloat   crosspointX;              
    MyFloat   fitpar0;                  
    MyFloat   fitpar0error;             
    MyFloat   fitpar1;                  
    MyFloat   fitpar1error;             
    MyFloat   fitparNoise0;             
    MyFloat   fitparNoise0error;        
    MyFloat   fitparNoise1;             
    MyFloat   fitparNoise1error;        
    MyFloat   totalsigma;               
    MyFloat   fitGaussMean;             
    MyFloat   fitGaussSigma;            
    Float_t   meanhOffset;
    Float_t   offsets     [6][4][16][96];
    Float_t   offsetErr   [6][4][16][96];
    Float_t   offset1     [6][4][16][96];
    Int_t     integral    [6][4][16][96];
    Float_t   fitslope1   [6][4][16][96];
    Float_t   fitslope2   [6][4][16][96];
    Float_t   offsetpulser[6][4][16][96][5];
    Float_t   myoffset;
    Float_t   myerror;
    Bool_t    debug;                     
public:
    HMdcOffset();
    HMdcOffset(const Text_t* name,const Text_t* title);
    ~HMdcOffset();
    
    Bool_t           init();
    Bool_t           reinit();
    Bool_t           finalize();
    Int_t            execute();
    void             setSignalSpeed     (Float_t speed)             { signalspeed     = speed; }
    void             setCounter         (Int_t size)                { nStep           = size; }
    void             setOutputAscii     (const Char_t*);
    void             setOutputRoot      (const Char_t*);
    void             setPulserFile      ()                          { isPulserFile    = kTRUE; }
    void             setNotUseStart     (Bool_t nouse)              { noStart         = nouse; }
    void             setUseClusters     (Bool_t use)                { useClusters     = use; }
    void             setUseWireOffset   (Bool_t use)                { useWireOffset   = use; }
    void             setUseTof          (TString inp);
    void             setFillHistsOnly   (Bool_t fill)               { fillHistsOnly   = fill; }
    void             setReadHists       (TString inp,Bool_t print=kFALSE);
    void             setFillPerMBO      (Bool_t fillPerMBO)         { perMBO          = fillPerMBO; }
    void             setFillPerMBOafterSingle(Bool_t fillPerMBO)    { perMBOafterSingle = fillPerMBO; }
    void             setFilterWindow1   (Float_t window)            { filterwindow1   = window;}
    void             setFilterWindow2   (Float_t window)            { filterwindow2   = window;}
    void             setNSkipEvents     (Int_t nskipevents)         { nSkipEvents     = nskipevents; }
    void             setValidOffsetRange(Float_t range)             { validRange      = range; }
    void             setUseTimeCuts     (Bool_t cut)                { useTimeCuts     = cut; }
    void             setNoiseOffset     (Int_t i)                   { offsetfitNoise  = i; }
    void             setNoiseWidth      (Int_t i)                   { widthfitNoise   = i; }
    void             setThresholdMin    (Float_t f)                 { minfitthreshold = f; }
    void             setThresholdMax    (Float_t f)                 { maxfitthreshold = f; }
    void             setNoise           (Int_t o, Int_t w)          { offsetfitNoise  = o; widthfitNoise = w; }
    void             setFitNoise        (Bool_t fit)                { fitNoise        = fit;}
    void             setThreshold       (Float_t min, Float_t max)  { minfitthreshold = min; maxfitthreshold = max; }
    void             setRangeGauss      (Int_t i)                   { rangeGauss      = i; }
    void             setDebug           ()                          { debug           = kTRUE; }
    void             setCleanThreshold  (Int_t thresh)              { cleanThreshold  = thresh; }
    void             setCuts(Float_t c1l[],Float_t c1r[],Float_t c12[]){
	for(Int_t i=0;i<4;i++){
	    cutT1L[i]=c1l[i];
	    cutT1R[i]=c1r[i];
	    cutT12[i]=c12[i];
	}
	useCuts = kTRUE;
    }
protected:
    Int_t            executeRaw         ();
    Int_t            executeClus        ();
    void             setDefault         ();
    ofstream*        openAsciiFile      ();
    TDirectory*      Mkdir              (TDirectory *,const Char_t *, Int_t, Int_t p=1);
    void             createHist         (TFile*,Int_t, Int_t, Int_t, Int_t, Bool_t = kFALSE);
    void             createHist_2D      (Int_t, Int_t, Bool_t = kFALSE);
    void             fillHist           (Int_t, Int_t, Int_t, Int_t);
    void             fillHist_2D        (Int_t, Int_t, Int_t, Int_t);
    Int_t            fitHist            (Int_t, Int_t, Int_t, Int_t);
    void             writeHist          (TFile*);
    void             writeHist_2D       (Int_t s, Int_t m);
    void             deleteHist         ();
    void             deleteHist_2D      ();
    void             fillNTuples        (Int_t, Int_t, Int_t, Int_t);
    Float_t          getstarttime       ();
    void             writeAscii         (ofstream&, Int_t, Int_t, Int_t, Int_t);
    void             initVariables      ();
    void             findMultiplePeaks  (Int_t,Int_t,Int_t,Int_t);
    void             initMemory         ()
    {
	for(Int_t s = 0;s < 6; s ++){
	    for(Int_t m = 0; m < 4; m ++){
		for(Int_t mb = 0; mb < 16; mb ++){
		    for(Int_t t = 0; t <96; t ++){
			for(Int_t bin = 0; bin < 2048; bin ++){
			    (*hreverse) [s][m][mb][t][bin] = 0;
			}
		    }
		}
	    }
	}
    }
    void              initArrays         ()
    {
	for(Int_t s = 0; s < 6; s ++){
	    for(Int_t mo = 0; mo < 4; mo ++){
		for(Int_t mb = 0; mb < 16; mb ++){
		    for(Int_t t = 0; t < 96; t ++){
			offsets  [s][mo][mb][t] = 0;
			offsetErr[s][mo][mb][t] = 0;
			offset1  [s][mo][mb][t] = 0;
			integral [s][mo][mb][t] = 0;
                        fitslope1[s][mo][mb][t] = 0;
                        fitslope2[s][mo][mb][t] = 0;
			for(Int_t j = 0; j < 5; j ++)
			{
			    offsetpulser[s][mo][mb][t][j] = 0;
			}
		    }
		}
	    }
	}
    }
    Bool_t            testTimeCuts       (Int_t s, Int_t m,Float_t t1,Float_t t2)
    {
	if(useCuts)
	{
	    if(t1>=cutT1L[m] && t1<=cutT1R[m] && fabs(t2-t1)>cutT12[m]) return kTRUE;
            else                                               return kFALSE;
	} else {
	    if(timecut->cutTime1   (s,m,t1)  &&
	       timecut->cutTime2   (s,m,t2)  &&
	       timecut->cutTimesDif(s,m,t2,t1)){ return kTRUE; }
	    else { return kFALSE; }
	}
    }
    void             fillArrays          (TH1F*,Int_t, Int_t, Int_t, Int_t);
    void             fillCalParRaw       (TH1F*,Int_t, Int_t, Int_t, Int_t);
    void             printStatus         ();
public: 
    ClassDef(HMdcOffset, 0)  
};
#endif /* !HMDCOFFSET_H */