#ifndef HMDCDITIZER_H
#define HMDCDITIZER_H
using namespace std;
#include "hreconstructor.h"
#include "hcategory.h"
#include "TRandom.h"
#include "TNtuple.h"
#include "TVector2.h"
#include <vector>
#include <map>
#include <iostream> 
#include <iomanip>
#include <stdlib.h>
#include <cmath>
#include "hlocation.h"
#include "hmdccal1sim.h"
class HIterator;
class HMdcLayerGeomPar;
class HMdcDigitPar;
class HMdcCal2ParSim;
class HMdcCal1Sim;
class HMdcCellEff;
class HMdcWireStat;
class HMdcDeDx2;
class HMdcTimeCut;
class HMdcGeomStruct;
class HMdcSizesCells;
class HMdcGeantCell;
class HGeantKine;
class TFile;
class TGraph;
#define  NMAXHITS 15
class HMdcDigiLayEff {
public:
    Int_t trackNum;
    Float_t eff[6][4][6];
    Int_t   ct [6][4][6];
    
    Int_t   cmin[6][4][6];       
    Int_t   cmax[6][4][6];       
    Float_t Lmin[6][4][6];       
    Float_t Lmax[6][4][6];       
    HMdcDigiLayEff(Int_t tr=-1){
	trackNum = tr;
	fill();
	memset(&ct [0][0][0],0,6*4*6*sizeof(Int_t));
    }
    void clear(){
        trackNum = -1;
        memset(&eff[0][0][0],0,6*4*6*sizeof(Float_t));
        memset(&ct [0][0][0],0,6*4*6*sizeof(Int_t));
    }
    void fill(){
	for(Int_t s=0;s<6;s++){
	    for(Int_t m=0;m<4;m++){
		for(Int_t l=0;l<6;l++){
		    eff[s][m][l] = gRandom->Rndm();
		}
	    }
	}
    }
};
class HMdcDigitizer : public HReconstructor {
private:
  HCategory*        fGeantMdcCat;  
  HCategory*        fGeantKineCat; 
  HLocation         loc;           
  HLocation         locnoise;      
  HCategory*        fGeantCellCat; 
  HCategory*        fCalCat;       
  HMdcGeantCell*    hit;           
  HMdcGeantCell*    hitReal;       
  HMdcLayerGeomPar* fDigitGeomPar; 
  HMdcDigitPar*     fDigitPar;     
  HMdcCal2ParSim*   fCal2ParSim;   
  HMdcCellEff*      fCellEff;      
  HMdcWireStat*     fWireStat;     
  HMdcTimeCut*      fTimeCut;      
  HMdcSizesCells*   fsizescells;   
  HMdcDeDx2*        fdEdX;         
  HMdcGeomStruct*   geomstruct;    
  HMdcCal1Sim*      fCal;          
  HMdcCal1Sim*      fCalnoise;     
  HMdcGeantCell*    fCell;         
  HIterator*        iterin;        
  HIterator*        itercell;      
  HIterator*        itercal1;      
  Int_t             fEventId;      
  Float_t           yDist;         
  Float_t           pi;            
  Int_t    modetdc;                
  Int_t    setup[6][4];            
  Float_t  time1;                  
  Float_t  time1Error;             
  Float_t  time2;                  
  Float_t  time2Error;             
  Float_t  myalpha;                
  Bool_t   useError;               
  Bool_t   useWireOffset;          
  Bool_t   useDeDx2;               
  Bool_t   useTimeCut;             
  TFile*   myoutput;               
  TNtuple* distance_time;          
  Bool_t   fntuple;                
  Bool_t   useTof;                 
  Float_t  offsets[4];             
  Bool_t   useOffsets;             
  TGraph*  fbetadEdx;              
  Float_t  fBetaLow;               
  Bool_t   useDeDxScaling;         
  Bool_t   useDeDxTimeScaling;     
  Float_t  effLevel[4];            
  Bool_t   useCellEff;             
  Bool_t   useWireStat;            
  Bool_t   useWireStatEff;         
  Bool_t   useWireStatOffset;      
  Bool_t   useLayerThickness;      
  Bool_t   useDeltaElectrons;      
  Bool_t   useDeltaMomSelection;   
  Int_t    ionID;                  
  Float_t  fProbDeltaAccepted;     
  Float_t  t1minDeltaElec;         
  Float_t  t1maxDeltaElec;         
  Float_t  momMaxDeltaElecCut;     
  Float_t  momMinDeltaCut[6];      
  map<HGeantKine*,Float_t> mDeltaTrackT0;    
  map<HGeantKine*,Float_t>::iterator itDelta;
  Bool_t   hasPrinted;             
  Float_t  noiseLevel[4];          
  Bool_t   useNoise;               
  Int_t    arrayNoise[5];          
  Int_t    noiseRangeLo[4];        
  Int_t    noiseRangeHi[4];        
  Float_t  time1noise;             
  Float_t  time2noise;             
  Int_t    noisemode;              
  Int_t    firstHit;               
  Int_t    secondHit;              
  Float_t  firstTime2;             
  Int_t    endList1;               
  Int_t    firstsec;
  Int_t    firstmod;
  Int_t    firstlay;
  Int_t    firstcell;
  Float_t  noisebandwidth;                 
  Float_t  noisewhitewidth;                
  Float_t  noisewhiteratio;                
  static  Float_t dTime              [NMAXHITS]; 
  static  Float_t dTime2             [NMAXHITS]; 
  static  Float_t dTimeErr           [NMAXHITS]; 
  static  Float_t dTime2Err          [NMAXHITS]; 
  static  Float_t minimumdist        [NMAXHITS]; 
  static  Int_t track                [NMAXHITS]; 
  static  Float_t timeOfFlight       [NMAXHITS]; 
  static  Float_t angle              [NMAXHITS]; 
  static  Int_t statusflag           [NMAXHITS]; 
  static  Float_t fractionOfmaxCharge[NMAXHITS]; 
  static  Bool_t cutEdge             [NMAXHITS]; 
  static  Float_t wireOffset         [NMAXHITS]; 
  static  Float_t efficiency         [NMAXHITS]; 
  static  Float_t theta              [NMAXHITS]; 
  Float_t time1Real;                 
  Float_t time2Real;                 
  Int_t   nHitsReal;                 
  Int_t   embeddingmode;             
  Float_t signalSpeed;               
  Float_t scaleError[4];             
  Float_t scaleErrorMIPS[4];         
  Float_t rndmoffsets[6][4][6][220]; 
  Float_t sigmaoffsets;              
  Bool_t  createoffsets;             
  Bool_t  offsetsCreated;            
  Float_t scaletime;                 
  vector< HMdcDigiLayEff > vLayEff;  
  HMdcDigiLayEff           layEff;   
  Float_t effLayerThickness(Float_t xcoor,Float_t ycoor,Float_t th,Float_t ph,Int_t s,Int_t m,Int_t l) ;
  Int_t findTrack(Int_t trk);
public:
  HMdcDigitizer(void);
  HMdcDigitizer(const Text_t* name,const Text_t* title);
  HMdcDigitizer(const Text_t* name,const Text_t* title,Int_t,Bool_t);
  ~HMdcDigitizer(void);
  void    setOffsets            (Float_t off0,Float_t off1,Float_t off2,Float_t off3,Int_t on_off = 1);
  void    setEffLevel           (Float_t eff0,Float_t eff1,Float_t eff2,Float_t eff3,Int_t on_off = 1);
  void    setEffScaling         (Float_t betalow,Bool_t usescaling) {fBetaLow = betalow, useDeDxScaling = usescaling;}
  void    setTimeErrScaling     (Bool_t usescaling) { useDeDxTimeScaling = usescaling;}
  
  void    setNoiseLevel         (Float_t noise0,Float_t noise1,Float_t noise2,Float_t noise3,Int_t on_off = 1);
  void    setNoiseRange         (Int_t rangeLo0,Int_t rangeLo1,Int_t rangeLo2,Int_t rangeLo3,
				 Int_t rangeHi0,Int_t rangeHi1,Int_t rangeHi2,Int_t rangeHi3);
  void    setNoiseBandWidth     (Float_t w)              {noisebandwidth    = w;     }
  void    setNoiseWhiteWidth    (Float_t w)              {noisewhitewidth   = w;     }
  void    setNoiseWhiteRatio    (Float_t w)              {noisewhiteratio   = w;     }
  Float_t getNoiseBandWidth     ()                       {return noisebandwidth;     }
  Float_t getNoiseWhiteWidth    ()                       {return noisewhitewidth;    }
  Float_t getNoiseWhiteRatio    ()                       {return noisewhiteratio;    }
  
  void    setErrorUse           (Bool_t use)             {useError          = use;   }
  void    setTofUse             (Bool_t use)             {useTof            = use;   }
  void    setWireOffsetUse      (Bool_t use)             {useWireOffset     = use;   }
  void    setOffsetsUse         (Bool_t use)             {useOffsets        = use;   }
  void    setCellEffUse         (Bool_t use)             {useCellEff        = use;   }
  void    setWireStatUse        (Bool_t use)             {useWireStat       = use;   }
  void    setNoiseUse           (Bool_t use)             {useNoise          = use;   }
  void    setDeDxUse            (Bool_t use)             {useDeDx2          = use;   }
  void    setTimeCutUse         (Bool_t use)             {useTimeCut        = use;   }
  Bool_t  getErrorUse           ()                       {return useError;           }
  Bool_t  getTofUse             ()                       {return useTof;             }
  Bool_t  getWireOffsetUse      ()                       {return useWireOffset;      }
  Bool_t  getOffsetsUse         ()                       {return useOffsets;         }
  Bool_t  getCellEffUse         ()                       {return useCellEff;         }
  Bool_t  getWireStatUse        ()                       {return useWireStat;        }
  Bool_t  getNoiseUse           ()                       {return useNoise;           }
  Bool_t  getDeDxUse            ()                       {return useDeDx2;           }
  Bool_t  getTimeCutUse         ()                       {return useTimeCut;         }
  
  void    setNTuple             (Bool_t ntuple)          {fntuple           = ntuple;}
  void    setTdcMode            (Int_t mode)             {modetdc           = mode;  }
  void    setNoiseMode          (Int_t mode)             {noisemode         = mode;  }
  void    setEmbeddingMode      (Int_t mode)             {embeddingmode     = mode;  }
  Bool_t  getNTuple             ()                       {return fntuple;            }
  Int_t   getTdcMode            ()                       {return modetdc;            }
  Int_t   getNoiseMode          ()                       {return noisemode;          }
  Int_t   getEmbeddingMode      ()                       {return embeddingmode;      }
  
  void    setSignalSpeed        (Float_t speed)          {signalSpeed       = speed; }
  Float_t getSignalSpeed        ()                       {return signalSpeed;        }
  
  void    setScaleTime          (Float_t scale)          {scaletime         = scale; }
  Float_t getScaleTime          ()                       {return scaletime;}
  void    setScalerTime1Err     (Float_t m0 = 0,Float_t m1 = 0,Float_t m2 = 0,Float_t m3 = 0);
  
  void    setWireStatOffsetUse  (Bool_t use)             {useWireStatOffset = use;   }
  Bool_t  getWireStatOffsetUse  ()                       {return useWireStatOffset;  }
  void    initOffsets           (TString filename = "");
  void    setSigmaOffsets       (Float_t sig)            {sigmaoffsets      = sig;   }
  void    setCreateOffsets      (Bool_t create = kTRUE)  {createoffsets     = create;}
  Float_t getSigmaOffsets       ()                       {return sigmaoffsets;}
  Bool_t  getCreateOffsets      ()                       {return createoffsets;}
  
  void    setWireStatEffUse     (Bool_t use)             {useWireStatEff    = use;   }
  Bool_t  getWireStatEffUse     ()                       {return useWireStatEff;     }
  void    setLayerThicknessEffUse(Bool_t use)            {useLayerThickness = use;   }
  Bool_t  getLayerThicknessEffUse()                      {return useLayerThickness;  }
  
  void   setDeltaElectronUse(Bool_t use, Bool_t useDeltaMomSel=kFALSE, Int_t ionId=109,Float_t t1min=-950.,Float_t t1max=400.,Float_t momCut=20.,Float_t probDelta=2.){  useDeltaElectrons = use;useDeltaMomSelection = useDeltaMomSel; ionID=ionId; t1minDeltaElec = t1min;  t1maxDeltaElec = t1max; momMaxDeltaElecCut = momCut; fProbDeltaAccepted = probDelta;}
  Bool_t getDeltaElectronUse() { return useDeltaElectrons;}
  void   setDeltaElectronMinMomCut(Float_t s0=2.,Float_t s1=2.,Float_t s2=4.5,Float_t s3=2.,Float_t s4=2.,Float_t s5=4.5) { momMinDeltaCut[0]=s0; momMinDeltaCut[1]=s1; momMinDeltaCut[2]=s2;  momMinDeltaCut[3]=s3;  momMinDeltaCut[4]=s4; momMinDeltaCut[5]=s5; }
  void   printStatus           ();
  void setTimeCutFlags(HMdcCal1Sim* cal1);
   
  Bool_t  init                  (void);
  Bool_t  reinit                (void);
  Int_t   execute               (void);
  Bool_t  finalize              ();
protected:
  void    setParContainers      ();
  void    initVariables         ();
  Bool_t  transform             (Float_t,Float_t,Float_t,Float_t,Float_t,Int_t);
  void    storeCell             (Float_t,Float_t,Float_t,Int_t,Bool_t,Float_t,Float_t,Float_t);
  void    select                (Int_t);
  
  void    fillNoise             (Int_t, Int_t, Int_t, Int_t,Int_t, Int_t, Int_t, Int_t);
  void    handleOverFlow        (Int_t, Int_t, Int_t, Int_t);
  void    setLoopVariables      (Int_t,Int_t,Int_t,Int_t,Bool_t check = kFALSE);
  Float_t fillTime1Noise        (Int_t);
  Float_t fillTime2Noise        (Int_t);
  void    fillNoiseLists        (HMdcCal1Sim* cal1,Int_t,Int_t);
  void    fillNoiseToGeantCells (Int_t,HMdcCal1Sim* p);
  
  void    fillNTuple            (Int_t ,Int_t ,Int_t ,Int_t , Int_t, HMdcGeantCell* ,TNtuple*);
  void    fillNTuple            (Int_t, Int_t, Int_t, Int_t, Float_t, Float_t, Int_t);
  void    setNTuples            (void);
  Bool_t  evalWireStat          (Int_t, Int_t, Int_t, Int_t);
  
  void    initArrays            ();
  void    fillArrays            (Int_t,Int_t,Int_t,HMdcGeantCell*);
  void    fillArraysReal        (Int_t i);
  void    resetListVariables    ();
  void    resetCal1Real         ();
  void    setTime1Real          (Float_t t1)             {time1Real = t1;  }
  void    setTime2Real          (Float_t t2)             {time2Real = t2;  }
  void    setNHitsReal          (Int_t i)                {nHitsReal = i;   }
  Float_t getTime1Real          ()                       {return time1Real;}
  Float_t getTime2Real          ()                       {return time2Real;}
  Int_t   getNHitsReal          ()                       {return nHitsReal;}
  void    getCal1Real           ();
  void    setEfficiencyFlags    (Int_t,Int_t,Int_t,Int_t);
  void    setTimeCutFlags       (Int_t,Int_t,Int_t,Int_t);
  void    fillTrackList         (HMdcCal1Sim*);
  void    findFirstValidHit     ();
  void    findSecondValidHit    ();
  Int_t   findNonValidHit       ();
  void    getMdcSetup           ();
  Bool_t  testMdcSetup          (Int_t s, Int_t m);
  void    setTime1Noise         (Float_t time)           {time1noise = time; }
  void    setTime2Noise         (Float_t time)           {time2noise = time; }
  Float_t getTime1Noise         ()                       {return time1noise; }
  Float_t getTime2Noise         ()                       {return time2noise; }
  void    setFirstHit           (Int_t hit1)             {firstHit   = hit1; }
  void    setSecondHit          (Int_t hit2)             {secondHit  = hit2; }
  void    setFirstTime2         (Float_t time2)          {firstTime2 = time2;}
  void    setEndList1           (Int_t end)              {endList1   = end;  }
  Int_t   getFirstHit           ()                       {return firstHit;   }
  Int_t   getSecondHit          ()                       {return secondHit;  }
  Float_t getFirstTime2         ()                       {return firstTime2; }
  Int_t   getEndList1           ()                       {return endList1;   }
  
  void    setDTime1             (Int_t i,Float_t time)   {dTime              [i] = time;   }
  void    setDTime2             (Int_t i,Float_t time)   {dTime2             [i] = time;   }
  void    setDTime1Err          (Int_t i,Float_t timeErr){dTimeErr           [i] = timeErr;}
  void    setDTime2Err          (Int_t i,Float_t timeErr){dTime2Err          [i] = timeErr;}
  void    setMinimumDist        (Int_t i,Float_t dist)   {minimumdist        [i] = dist;   }
  void    setTrackN             (Int_t i,Int_t number)   {track              [i] = number; }
  void    setTof                (Int_t i,Float_t tof)    {timeOfFlight       [i] = tof;    }
  void    setAngle              (Int_t i,Float_t a)      {angle              [i] = a;      }
  void    setStatus             (Int_t i,Int_t stat)     {statusflag         [i] = stat;   }
  void    setFractionOfmaxCharge(Int_t i,Float_t f)      {fractionOfmaxCharge[i] = f;      }
  void    setCutEdge            (Int_t i,Bool_t cut)     {cutEdge            [i] = cut;    }
  void    setWireOffset         (Int_t i,Float_t off)    {wireOffset         [i] = off;    }
  void    setEfficiency         (Int_t i,Float_t eff)    {efficiency         [i] = eff;    }
  void    setTheta              (Int_t i,Float_t th)     {theta              [i] = th;    }
  Float_t getDTime1             (Int_t i)                {return dTime              [i];   }
  Float_t getDTime2             (Int_t i)                {return dTime2             [i];   }
  Float_t getDTime1Err          (Int_t i)                {return dTimeErr           [i];   }
  Float_t getDTime2Err          (Int_t i)                {return dTime2Err          [i];   }
  Float_t getMinimumDist        (Int_t i)                {return minimumdist        [i];   }
  Int_t   getTrackN             (Int_t i)                {return track              [i];   }
  Float_t getTof                (Int_t i)                {return timeOfFlight       [i];   }
  Float_t getAngle              (Int_t i)                {return angle              [i];   }
  Int_t   getStatus             (Int_t i)                {return statusflag         [i];   }
  Float_t getFractionOfmaxCharge(Int_t i)                {return fractionOfmaxCharge[i];   }
  Bool_t  getCutEdge            (Int_t i)                {return cutEdge            [i];   }
  Float_t getWireOffset         (Int_t i)                {return wireOffset         [i];   }
  Float_t getEfficiency         (Int_t i)                {return efficiency         [i];   }
  Float_t getTheta              (Int_t i)                {return theta              [i];   }
  Float_t getCellEffLevel       (Int_t i)                {return effLevel           [i];   }
  Float_t getNoiseLevel         (Int_t i)                {return noiseLevel         [i];   }
  Float_t getOffset             (Int_t i)                {return offsets            [i];   }
  Int_t   getNoiseRangeHi       (Int_t i)                {return noiseRangeHi       [i];   }
  Int_t   getNoiseRangeLo       (Int_t i)                {return noiseRangeLo       [i];   }
  ClassDef(HMdcDigitizer,0) 
};
#endif