using namespace std;
#include "TRandom.h"
#include "TDirectory.h"
#include <time.h>
#include "htofdigitizer.h"
#include "tofdef.h"
#include "hdebug.h"
#include "hades.h"
#include "hiterator.h"
#include "hruntimedb.h"
#include "hspectrometer.h"
#include "htofdetector.h"
#include "hgeanttof.h"
#include "hgeantkine.h"
#include "hlinearcategory.h"
#include "htofrawsim.h"
#include "hevent.h"
#include "hcategory.h"
#include "hlocation.h"
#include "htofdigipar.h"
#include "htofcalpar.h"
#include "htofwalkpar.h"
#include "htofrawsimfilter.h"
#include <iostream> 
#include <iomanip>
HTofDigitizer*  HTofDigitizer::pTofDigi=NULL;
Float_t HTofDigitizer::timeResZero = 0.240;  
Bool_t HTofDigitizer::initParContainer() {
    fDigiPar=(HTofDigiPar *)gHades->getRuntimeDb()->getContainer("TofDigiPar");
    if(!fDigiPar){
	Error("initParContainer()","Could not retrieve HTofDigiPar !");
	return kFALSE;
    }
    fTofCalPar=(HTofCalPar *)gHades->getRuntimeDb()->getContainer("TofCalPar");
    if(!fTofCalPar){
	Error("initParContainer()","Could not retrieve HTofCalPar !");
	return kFALSE;
    }
    fTofWalkPar=(HTofWalkPar *)gHades->getRuntimeDb()->getContainer("TofWalkPar");
    if(!fTofWalkPar){
	Error("initParContainer()","Could not retrieve HTofWalkPar !");
	return kFALSE;
    }
    return kTRUE;
}
HTofDigitizer::HTofDigitizer(const Text_t *name,const Text_t *title) :
HReconstructor(name,title) {
    fGeantCat=0;
    fGeantKineCat=0;
    fRawCat=0;
    fRawCatTmp=0;
    fDigiPar=0;
    fLoc.set(3,0,0,0);
    iterGeant=0;
    iterTofRaw=0;
    iterTofRawTmp=0;
    storeFirstTrack=2;
    debug          =kFALSE;
    out            =NULL;
    outFile        =NULL;
    pTofDigi       =this;
    useOld         =kFALSE;
}
HTofDigitizer::~HTofDigitizer(void) {
    if(iterGeant)    { delete iterGeant    ; iterGeant     = 0;}
    if(iterTofRaw)   { delete iterTofRaw   ; iterTofRaw    = 0;}
    if(iterTofRawTmp){ delete iterTofRawTmp; iterTofRawTmp = 0;}
}
Bool_t HTofDigitizer::init(void) {
    time_t curtime;
    if(!initParContainer()) return kFALSE;
    fGeantCat = gHades->getCurrentEvent()->getCategory(catTofGeantRaw);
    if (!fGeantCat) {
	fGeantCat = gHades->getSetup()->getDetector("Tof")->buildCategory(catTofGeantRaw);
	if (!fGeantCat) return kFALSE;
	else gHades->getCurrentEvent()->addCategory(catTofGeantRaw,fGeantCat,"Tof");
    }
    fGeantKineCat=(HLinearCategory*)gHades->getCurrentEvent()->getCategory(catGeantKine);
    if(!fGeantKineCat){
	Error("HTofDigitizer::init()","No catGeantKine in input!");
	return kFALSE;
    }
    fRawCat = gHades->getCurrentEvent()->getCategory(catTofRaw);
    if (!fRawCat) {
	HTofDetector* tof=(HTofDetector*)(gHades->getSetup()->getDetector("Tof"));
	fRawCat=tof->buildMatrixCategory("HTofRawSim",0.5F);
	if (!fRawCat) return kFALSE;
	else gHades->getCurrentEvent()->addCategory(catTofRaw,fRawCat,"Tof");
    }
    fRawCatTmp = gHades->getCurrentEvent()->getCategory(catTofRawTmp);
    if (!fRawCatTmp) {
	HTofDetector* tof=(HTofDetector*)(gHades->getSetup()->getDetector("Tof"));
	fRawCatTmp=tof->buildMatrixCategory("HTofRawSimTmp",0.5F);
	if (!fRawCatTmp) return kFALSE;
	else gHades->getCurrentEvent()->addCategory(catTofRawTmp,fRawCatTmp,"Tof");
	fRawCatTmp->setPersistency(kFALSE);
    }
    iterGeant = (HIterator *)fGeantCat->MakeIterator("native");
    iterTofRaw = (HIterator *)fRawCat->MakeIterator("native");
    iterTofRawTmp = (HIterator *)fRawCatTmp->MakeIterator("native");
    time(&curtime);
    return kTRUE;
}
Int_t HTofDigitizer::executeOld(void) {
    const Float_t deg2rad = 0.017453293; 
    const Float_t quantEff = 0.24;       
    const Float_t photYield = 11100.0;   
    const Float_t relAmplResol = 0.08;   
    const Float_t minEnerRelease = 1.8;  
    HGeantTof* geant = 0;
    HTofRawSim* raw = 0;
    HTofRawSimFilter fRawFilter;
    Float_t hl, al, ar, vg, slopeTDCl, slopeTDCr;
    Int_t thrCFDl, thrCFDr, thrADCl, thrADCr;
    Int_t   numTrack, numTrack1 = -1, numTrack2 = -1;      
    Float_t trackLen;
    Float_t timeL, timeR, chargeL, chargeR;
    Int_t timeCh, chargeCh;
    Float_t prevTimeL, prevTimeR, prevChargeL, prevChargeR;
    Float_t timeResol,amplResol, chargeRef;
    Float_t geaTof = 0.;
    Float_t geaTof1[6][8][8];
    Float_t geaTof2[6][8][8];
    Float_t geaEner = 0.;
    Float_t geaX = 0.;
    Float_t geaY = 0.;     
    Float_t geaMom = 0.;
    iterGeant->Reset();   
    
    while ((geant=(HGeantTof *)iterGeant->Next())!=0) {
	fLoc[1] = geant->getModule();
	if (fLoc[1] > 21 || fLoc[1] < 14) continue;   
	fLoc[1] = 21 - fLoc[1];       
	fLoc[0] = geant->getSector();
	fLoc[2] = geant->getCell();
	fLoc[2] = 7 - fLoc[2];        
	raw = (HTofRawSim*) fRawCat->getObject(fLoc);   
	if(raw) {
	    raw->incNHit();  
	    numTrack1 = raw->getNTrack1();
	    numTrack2 = raw->getNTrack2();
	    prevTimeL = raw->getLeftTime();
	    prevTimeR = raw->getRightTime();
	    prevChargeL = raw->getLeftCharge();
	    prevChargeR = raw->getRightCharge();
	}
	else {
	    prevTimeL = prevTimeR = 100000.;
	    prevChargeL = prevChargeR = 0.;
	    raw = (HTofRawSim*) fRawCat->getNewSlot(fLoc);  
	    if(!raw) continue;
	    raw = new(raw) HTofRawSim;
	    raw->setNHit(1);
	}
	HTofDigiParCell& cell=(*fDigiPar)[fLoc[0]][fLoc[1]][fLoc[2]];
	hl = cell.getHalfLen();
	al = cell.getAttenLen();
	ar = cell.getAngleRef();
	vg = cell.getGroupVel();
	slopeTDCl = cell.getLeftTDCSlope();
	slopeTDCr = cell.getRightTDCSlope();
	thrCFDl = cell.getLeftCFDThreshold();
	thrCFDr = cell.getRightCFDThreshold();
	thrADCl = cell.getLeftADCThreshold();
	thrADCr = cell.getRightADCThreshold();
	geant->getHit(geaEner,geaX,geaY,geaTof,geaMom,trackLen);
	numTrack=geant->getTrack();
	if((vg!=0.0) && (al!=0.0))  {
	    timeL = geaTof + (hl - geaX)/vg;
	    
	    
	    timeR = geaTof + (hl + geaX)/vg;
	    
	    
	    timeCh = (Int_t) (timeL/slopeTDCl);
	    if (timeCh < 0) timeCh = 0;
	    if (timeCh > 4095) timeCh = 4095;
	    timeL = ( Float_t ) (timeCh) + 0.5;
	    timeCh = (Int_t) (timeR/slopeTDCr);
	    if (timeCh < 0) timeCh = 0;
	    if (timeCh > 4095) timeCh = 4095;
	    timeR = ( Float_t ) (timeCh) + 0.5;
	    if(raw->getNHit()>1){
		if(geaTof < geaTof1[fLoc[0]][fLoc[1]][fLoc[2]]){
		    numTrack2=numTrack1;
		    numTrack1=numTrack;
		    geaTof2[fLoc[0]][fLoc[1]][fLoc[2]]=geaTof1[fLoc[0]][fLoc[1]][fLoc[2]];
		    geaTof1[fLoc[0]][fLoc[1]][fLoc[2]]=geaTof;
		} else {
		    if(geaTof < geaTof2[fLoc[0]][fLoc[1]][fLoc[2]]){
			numTrack2=numTrack;
			geaTof2[fLoc[0]][fLoc[1]][fLoc[2]]=geaTof;
		    }
		}
	    }
	    if(timeL > prevTimeL) timeL = prevTimeL;
	    if(timeR > prevTimeR) timeR = prevTimeR;
	    chargeL = geaEner*photYield*quantEff*0.5*(1 - cos(ar*deg2rad))*exp(-(hl-geaX)/al);
	    amplResol = chargeL*relAmplResol;
	    chargeL = gRandom->Gaus(chargeL,amplResol);
	    chargeR = geaEner*photYield*quantEff*0.5*(1 - cos(ar*deg2rad))*exp(-(hl+geaX)/al);
	    amplResol = chargeR*relAmplResol;
	    chargeR = gRandom->Gaus(chargeR,amplResol);
	    chargeRef = photYield*quantEff*0.5*(1-cos(ar*deg2rad))*minEnerRelease*exp(-hl/al);
	    if(fLoc[1] <= 3) chargeRef *= 3.;
	    if(fLoc[1]>3 && fLoc[1]<=7) chargeRef *= 2.;
	    chargeCh = (Int_t) ((chargeL/chargeRef)*256. + prevChargeL);
	    if (chargeCh < 0) chargeCh = 0;
	    if (chargeCh > MAXCHRGCH)  chargeCh = MAXCHRGCH;
	    chargeL = (Float_t)chargeCh;
	    chargeCh = (Int_t) ((chargeR/chargeRef)*256. + prevChargeR);
	    if (chargeCh < 0) chargeCh = 0;
	    if (chargeCh > MAXCHRGCH)  chargeCh = MAXCHRGCH;
	    chargeR = (Float_t)chargeCh;
	} else {
	    timeL = 4095.;
	    timeR = 4095.;
	    chargeL = MAXCHRGCH;
	    chargeR = MAXCHRGCH;
	}
	raw->setLeftTime(timeL);
	raw->setRightTime(timeR);
	raw->setLeftCharge(chargeL);
	raw->setRightCharge(chargeR);
	raw->setSector((Char_t) fLoc[0]);
	raw->setModule((Char_t) fLoc[1]);
	raw->setCell((Char_t) fLoc[2]);
	if(raw->getNHit()>1){
	    raw->setNTrack1(numTrack1);
	    raw->setNTrack2(numTrack2);
	} else {
	    raw->setNTrack1(numTrack);
	    raw->setNTrack2(-1);
	    geaTof1[fLoc[0]][fLoc[1]][fLoc[2]]=geaTof;
	    geaTof2[fLoc[0]][fLoc[1]][fLoc[2]]=100000.;
	}
    }
    
    
    
    iterTofRaw->Reset();
    while ( (raw=(HTofRawSim *)iterTofRaw->Next())!=NULL) {
	fLoc[0] = raw->getSector();
	fLoc[1] = raw->getModule();
	fLoc[2] = raw->getCell();
	timeL=raw->getLeftTime();
	timeR=raw->getRightTime();
	chargeL=raw->getLeftCharge();
	chargeR=raw->getRightCharge();
	HTofDigiParCell& cell=(*fDigiPar)[fLoc[0]][fLoc[1]][fLoc[2]];
	hl = cell.getHalfLen();
	al = cell.getAttenLen();
	thrCFDl = cell.getLeftCFDThreshold();
	thrCFDr = cell.getRightCFDThreshold();
	thrADCl = cell.getLeftADCThreshold();
	thrADCr = cell.getRightADCThreshold();
	slopeTDCl = cell.getLeftTDCSlope();
	slopeTDCr = cell.getRightTDCSlope();
	timeResol = timeResZero*exp(hl/(2.*al))/slopeTDCl;
	raw->setLeftTime(gRandom->Gaus(timeL,timeResol));
	timeResol = timeResZero*exp(hl/(2.*al))/slopeTDCr;
	raw->setRightTime(gRandom->Gaus(timeR,timeResol));
	if(((Int_t)timeL)<0) raw->setLeftTime(0.0);
	if(((Int_t)timeR)<0) raw->setRightTime(0.0);
	
	if(((Int_t)timeL)>=4095) raw->setLeftTime(0.0);
	if(((Int_t)timeR)>=4095) raw->setRightTime(0.0);
	
	if(((Int_t)chargeL)<thrCFDl){
	    raw->setLeftTime(0.0);
	    if(((Int_t)chargeL)<thrADCl){
		raw->setLeftCharge(0.0);
	    }
	}
	if(((Int_t) chargeR)<thrCFDr){
	    raw->setRightTime(0.0);
	    if(((Int_t) chargeR)<thrADCr){
		raw->setRightCharge(0.0);
	    }
	}
    }
    fRawCat->filter(fRawFilter);
    return 0;
}
Int_t HTofDigitizer::execute(void) {
    if(useOld) return executeOld();
    Int_t embeddingmode=gHades->getEmbeddingMode(); 
    HTofRawSimFilter fRawFilter;
    
    
    
    
    
    
    if(embeddingmode>0){
	HTofRawSim* raw = 0;
	iterTofRaw->Reset();
	while ((raw=(HTofRawSim *)iterTofRaw ->Next())!=0) {
	    raw->setNHit(1); 
	    raw->setLeftNTrack(gHades->getEmbeddingRealTrackId());
	    raw->setRightNTrack(gHades->getEmbeddingRealTrackId());
	}
    }
    
    
    
    
    fillArray();
    
    
    
    
    
    doFinalCheckOnArray();
    
    if(embeddingmode==0)
    {
	
	
        
	
	
	fillOutput();
	
	
	
	
	
	
	
	fRawCat->filter(fRawFilter);
	
    } else {
	fRawCatTmp->filter(fRawFilter);
    }
    return 0;
}
void HTofDigitizer::fillArray()
{
    
    
    
    const Float_t deg2rad = 0.017453293; 
    const Float_t quantEff = 0.24;       
    const Float_t photYield = 11100.0;   
    const Float_t relAmplResol = 0.08;   
    const Float_t minEnerRelease = 1.8;  
    HGeantTof* geant = 0;
    HTofRawSim* raw = 0;
    Float_t hl, al, ar, vg, slopeTDCl, slopeTDCr;
    Int_t   numTrack, numTrack1 = -1, numTrack2 = -1;      
    Float_t trackLen;
    Float_t timeL, timeR, chargeL, chargeR;
    Int_t timeCh, chargeCh;
    Float_t prevTimeL, prevTimeR, prevChargeL, prevChargeR;
    Float_t amplResol, chargeRef;
    Float_t geaTof  = 0.;
    Float_t geaEner = 0.;
    Float_t geaX    = 0.;
    Float_t geaY    = 0.;     
    Float_t geaMom  = 0.;
    iterGeant->Reset();   
    
    while ((geant=(HGeantTof *)iterGeant->Next())!=0) {
	fLoc[1] = geant->getModule();
	if (fLoc[1] > 21 || fLoc[1] < 14) continue;   
	fLoc[1] = 21 - fLoc[1];       
	fLoc[0] = geant->getSector();
	fLoc[2] = geant->getCell();
	fLoc[2] = 7 - fLoc[2];        
	
	
	
	
	raw = (HTofRawSim*) fRawCatTmp->getObject(fLoc);   
	if(raw) {
	    
	    raw->incNHit();  
	    numTrack1 = raw->getLeftNTrack();
	    numTrack2 = raw->getRightNTrack();
	    prevTimeL = raw->getLeftTime();
	    prevTimeR = raw->getRightTime();
	    prevChargeL = raw->getLeftCharge();
	    prevChargeR = raw->getRightCharge();
	}
	else {
	    prevTimeL = prevTimeR = 100000.;
	    prevChargeL = prevChargeR = 0.;
	    raw = (HTofRawSim*) fRawCatTmp->getNewSlot(fLoc);  
	    if(!raw) {
		Error("execute()","Could not retrieve new Slot in Category catTofRawTmp!");
		continue;
	    }
	    raw = new(raw) HTofRawSim;
	    raw->setNHit(1);
	}
	
	
	
	HTofDigiParCell& cell=(*fDigiPar)[fLoc[0]][fLoc[1]][fLoc[2]];
	hl = cell.getHalfLen();
	ar = cell.getAngleRef();
	al = cell.getAttenLen();
	vg = cell.getGroupVel();
	slopeTDCl = cell.getLeftTDCSlope();
	slopeTDCr = cell.getRightTDCSlope();
	
	
	
	geant->getHit(geaEner,geaX,geaY,geaTof,geaMom,trackLen);
	numTrack=geant->getTrack();
	
	
	
	
	HGeantTof* pOld=geant;
	HGeantTof* pNew=geant;
	Int_t tempTrack=0;
	Int_t count    =0;
	tempTrack=findFirstHitInTof(pOld,&pNew,&count);
	if(out)   fillNtuple       (pOld, pNew, count);
	numTrack =tempTrack;
	
	if(raw->getNHit()==1){
	    
	    
	    numTrack2=numTrack;
	    numTrack1=numTrack;
	}
	
	if((vg!=0.0) && (al!=0.0))  {
	    
	    
	    timeL = geaTof + (hl - geaX)/vg;
	    timeR = geaTof + (hl + geaX)/vg;
	    timeCh = (Int_t) (timeL/slopeTDCl);
	    if (timeCh < 0) timeCh = 0;
	    if (timeCh > 4095) timeCh = 4095;
	    timeL = ( Float_t ) (timeCh) + 0.5;
	    timeCh = (Int_t) (timeR/slopeTDCr);
	    if (timeCh < 0) timeCh = 0;
	    if (timeCh > 4095) timeCh = 4095;
	    timeR = ( Float_t ) (timeCh) + 0.5;
	    
	    
	    
	    
	    
	    
	    if(raw->getNHit()>1){
		
		
		if(timeL < prevTimeL){
		    
		    numTrack1=numTrack;
		}
		if(timeR < prevTimeR){
		    
		    numTrack2=numTrack;
		}
	    }
	    
	    
	    if(timeL > prevTimeL) {timeL = prevTimeL;}
	    if(timeR > prevTimeR) {timeR = prevTimeR;}
	    
	    
	    
	    chargeL = geaEner*photYield*quantEff*0.5*(1 - cos(ar*deg2rad))*exp(-(hl-geaX)/al);
	    amplResol = chargeL*relAmplResol;
	    chargeL = gRandom->Gaus(chargeL,amplResol);
	    chargeR = geaEner*photYield*quantEff*0.5*(1 - cos(ar*deg2rad))*exp(-(hl+geaX)/al);
	    amplResol = chargeR*relAmplResol;
	    chargeR = gRandom->Gaus(chargeR,amplResol);
	    chargeRef = photYield*quantEff*0.5*(1-cos(ar*deg2rad))*minEnerRelease*exp(-hl/al);
	    if(fLoc[1] <= 3) chargeRef *= 3.;
	    if(fLoc[1]>3 && fLoc[1]<=7) chargeRef *= 2.;
	    chargeCh = (Int_t) ((chargeL/chargeRef)*256. + prevChargeL);
	    if (chargeCh < 0) chargeCh = 0;
	    if (chargeCh > MAXCHRGCH)  chargeCh = MAXCHRGCH;
	    chargeL = (Float_t)chargeCh;
	    chargeCh = (Int_t) ((chargeR/chargeRef)*256. + prevChargeR);
	    if (chargeCh < 0) chargeCh = 0;
	    if (chargeCh > MAXCHRGCH)  chargeCh = MAXCHRGCH;
	    chargeR = (Float_t)chargeCh;
	    
	} else {
	    
	    
	    timeL = 4095.;
	    timeR = 4095.;
	    chargeL = MAXCHRGCH;
	    chargeR = MAXCHRGCH;
	    
	}
	
	
	raw->setLeftTime(timeL);
	raw->setRightTime(timeR);
	raw->setLeftCharge(chargeL);
	raw->setRightCharge(chargeR);
	raw->setSector((Char_t) fLoc[0]);
	raw->setModule((Char_t) fLoc[1]);
	raw->setCell((Char_t) fLoc[2]);
	raw->setLeftNTrack(numTrack1);
	raw->setRightNTrack(numTrack2);
	
    } 
}
void HTofDigitizer::doFinalCheckOnArray()
{
    
    
    
    
    HTofRawSim* raw = 0;
    Float_t hl, al, slopeTDCl, slopeTDCr;
    Int_t thrCFDl, thrCFDr, thrADCl, thrADCr;
    Float_t timeL, timeR, chargeL, chargeR;
    Float_t timeResol;
    Float_t subCl,subCr,depE;
    iterTofRawTmp->Reset();
    while ( (raw=(HTofRawSim *)iterTofRawTmp->Next())!=NULL) {
	fLoc[0] = raw->getSector();
	fLoc[1] = raw->getModule();
	fLoc[2] = raw->getCell();
	timeL=raw->getLeftTime();
	timeR=raw->getRightTime();
	chargeL=raw->getLeftCharge();    
	chargeR=raw->getRightCharge();   
	raw->setLeftCharge (fTofWalkPar->scaleGeantToData(chargeL));
	raw->setRightCharge(fTofWalkPar->scaleGeantToData(chargeR));
	HTofDigiParCell& cell=(*fDigiPar)[fLoc[0]][fLoc[1]][fLoc[2]];
	subCl = (raw->getLeftCharge());    
	subCr = (raw->getRightCharge());   
	depE = (*fTofCalPar)[fLoc[0]][fLoc[1]][fLoc[2]].getEdepK()  * (TMath::Sqrt(subCl*subCr));
        
        
        
	Int_t tr1 = raw->getNTrack1();
	Int_t tr2 = raw->getNTrack2();
	HGeantKine* kine1 = 0;
	HGeantKine* kine2 = 0;
	HGeantKine* kine  = 0;
	if(tr1>0) kine1 = (HGeantKine*)fGeantKineCat ->getObject(tr1-1);
	if(tr2>0) kine2 = (HGeantKine*)fGeantKineCat ->getObject(tr2-1);
        Double_t beta = 0;
        kine = kine1;
	if      (tr1 == tr2)   { kine = kine1;}
	else if (tr2 == -1 )   { kine = kine1;}
	else if (tr2 != tr1 )  {  
	    if        (kine2->getParentTrack()==0 && kine1->getParentTrack()>0)  { 
		kine = kine2;
	    } else if (kine2->getParentTrack()==0 && kine1->getParentTrack()==0) {  
		kine = kine1;
	    } else if (kine2->getParentTrack()>0  && kine1->getParentTrack()>0)  {  
		kine = kine1;
	    } else if (kine2->getParentTrack()>0  && kine1->getParentTrack()==0) {  
		kine = kine1;
	    }
	}
	Double_t mass   = HPhysicsConstants::mass(kine->getID());
	Double_t p      = kine->getTotalMomentum();
	if(mass > 0) {
	    beta = sqrt(1. / (((mass*mass)/(p*p)) + 1.));
	}
	
	Float_t sigma  = fTofWalkPar->getDxSigmaDigi(fLoc[0], fLoc[1], fLoc[2],depE,cell.getGroupVel(),beta) ;   
	timeResZero = sigma / cell.getGroupVel() * 1.41421;
	hl = cell.getHalfLen();
	al = cell.getAttenLen();
	thrCFDl = cell.getLeftCFDThreshold();
	thrCFDr = cell.getRightCFDThreshold();
	thrADCl = cell.getLeftADCThreshold();
	thrADCr = cell.getRightADCThreshold();
	slopeTDCl = cell.getLeftTDCSlope();
	slopeTDCr = cell.getRightTDCSlope();
	timeResol = timeResZero*exp(hl/(2.*al))/slopeTDCl;
	raw->setLeftTime(gRandom->Gaus(timeL,timeResol));
	timeResol = timeResZero*exp(hl/(2.*al))/slopeTDCr;
	raw->setRightTime(gRandom->Gaus(timeR,timeResol));
	if(((Int_t)timeL)<0) raw->setLeftTime(0.0);
	if(((Int_t)timeR)<0) raw->setRightTime(0.0);
	
	if(((Int_t)timeL)>=4095) raw->setLeftTime(0.0);
	if(((Int_t)timeR)>=4095) raw->setRightTime(0.0);
	
	if(((Int_t)chargeL)<thrCFDl){
	    raw->setLeftTime(0.0);
	    if(((Int_t)chargeL)<thrADCl){
		raw->setLeftCharge(0.0);
	    }
	}
	if(((Int_t) chargeR)<thrCFDr){
	    raw->setRightTime(0.0);
	    if(((Int_t) chargeR)<thrADCr){
		raw->setRightCharge(0.0);
	    }
	}
    }
    
}
void HTofDigitizer::fillOutput()
{
    
    
    Int_t embeddingmode=gHades->getEmbeddingMode(); 
    Int_t   numTrack1 = -1, numTrack2 = -1;            
    Float_t timeL, timeR, chargeL, chargeR;
    Int_t   numTrack1Out = -1, numTrack2Out = -1;      
    Float_t timeLOut, timeROut, chargeLOut, chargeROut;
    HTofRawSim* raw = 0;
    HTofRawSim * rawOut;
    iterTofRawTmp->Reset();
    while ( (raw=(HTofRawSim *)iterTofRawTmp->Next())!=NULL) {
	fLoc[0] = raw->getSector();
	fLoc[1] = raw->getModule();
	fLoc[2] = raw->getCell();
	timeL     = raw->getLeftTime();
	timeR     = raw->getRightTime();
	chargeL   = raw->getLeftCharge();
	chargeR   = raw->getRightCharge();
	numTrack1 = raw->getLeftNTrack();
	numTrack2 = raw->getRightNTrack();
	rawOut = (HTofRawSim*) fRawCat->getObject(fLoc);   
	if(rawOut)
	{
	    if(embeddingmode>0)
	    {
		
		raw->incNHit();  
		numTrack1Out = rawOut->getLeftNTrack();
		numTrack2Out = rawOut->getRightNTrack();
		timeLOut     = rawOut->getLeftTime();
		timeROut     = rawOut->getRightTime();
		chargeLOut   = rawOut->getLeftCharge();
		chargeROut   = rawOut->getRightCharge();
		
		
		
		
		
		
		
		
		if(timeL < timeLOut) {
		    numTrack1Out = numTrack1;
		    timeLOut     = timeL;
		}
		if(embeddingmode==2) numTrack1Out = numTrack1; 
		if(timeR < timeROut) {
		    numTrack2Out = numTrack2;
		    timeROut     = timeR;
		}
		if(embeddingmode==2) numTrack2Out = numTrack2; 
		
		rawOut->setLeftNTrack(numTrack1Out);
		rawOut->setRightNTrack(numTrack2Out);
		rawOut->setLeftTime(timeLOut);
		rawOut->setRightTime(timeROut);
		rawOut->setLeftCharge (chargeLOut+chargeL);
		rawOut->setRightCharge(chargeROut+chargeR);
	    }
	    else
	    {
		Error("fillOutput()","Slot was used before. This case should never happen in sim mode! Will overwrite object!");
		rawOut = new(rawOut) HTofRawSim(*raw);
	    }
	}
	else
	{
	    rawOut = (HTofRawSim*) fRawCat->getNewSlot(fLoc);  
	    if(!raw)
	    {
		Error("execute()","Could not retrieve new Slot in Category catTofRaw!");
		continue;
	    }
	    rawOut = new(rawOut) HTofRawSim(*raw);
	}
	
    }
    
}
Bool_t HTofDigitizer::finalize()
{
    TDirectory* saveDir=gDirectory;
    if(out)
    {
	outFile->cd();
	out->Write();
	outFile->Save();
	outFile->Close();
    }
    saveDir->cd();
    return kTRUE;
}
Int_t HTofDigitizer::findFirstHitInTof(HGeantTof* poldTof,HGeantTof** pnewTof,Int_t* count)
{
    
    
    
    
    
    
    
    
    
    Int_t numTrack=poldTof->getTrack();
    if(numTrack<=0) return numTrack; 
    HGeantKine* kine=0;
    *count=0;
    
    
    
    
    
    if(storeFirstTrack==0) return numTrack;
    
    
    if(storeFirstTrack==1)
    {   
	
	kine=(HGeantKine*)fGeantKineCat->getObject(numTrack-1);
	Int_t parent=kine->getParentTrack();
	kine=HGeantKine::getPrimary(numTrack,fGeantKineCat);
	if(parent>0)(*count)--; 
	if(debug)
	{
	    
	    
	    return (*count)*200;
	}
	else return kine->getTrack();
    }
    
    
    kine=(HGeantKine*)fGeantKineCat->getObject(numTrack-1);
    if(kine->getParentTrack()==0){return numTrack;} 
    Int_t s,m,c;
    s= poldTof->getSector();
    m= 21-poldTof->getModule();
    c= 7 -poldTof->getCell();
    Int_t first=0;
    Int_t tempTrack=numTrack;
    while((kine=kine->getParent(tempTrack,fGeantKineCat))!=0)
    {
	first=kine->getFirstTofHit();
	if(first!=-1)
	{
	    
	    
	    HGeantTof* gtof=(HGeantTof*)fGeantCat->getObject(first);
	    Int_t s1,m1,c1;
	    s1=m1=c1=0;
	    m1 = 21-gtof->getModule();
	    if(m1>=0)
	    {
		
		s1= gtof->getSector();
		c1= 7-gtof->getCell();
		if(storeFirstTrack==2&&
		   s==s1)
		{   
		    tempTrack  =kine->getTrack();
		    (*pnewTof)=gtof;
		    (*count)--;
		}
		if(storeFirstTrack==3&&
		   s==s1&&m==m1)
		{   
		    tempTrack  =kine->getTrack();
		    (*pnewTof)=gtof;
		    (*count)--;
		}
		else if(storeFirstTrack==4&&
			s==s1&&m==m1&&c==c1)
		{   
		    tempTrack  =kine->getTrack();
		    (*pnewTof)=gtof;
		    (*count)--;
		}
		else {
		    
		    
		    break;
		}
	    } else {
		
		break;
	    }
	}
	else {
	    
	    
	    
	    break;
	}
    }
    if(debug&&(*count)<0)
    {   
	
	return (*count)*200;
    }
    else return tempTrack;
}
void HTofDigitizer::setOutputFile(TString outname)
{
    
    
    TString outName;
    if(outname.CompareTo("")==0){
	outName ="tofdigiNtuple.root";
	Info("HTofDigitizer::setOutputFile()","No name speciefied use Output file : %s ",outName.Data());
    }
    else
    {
	outName=outname;
	Info("HTofDigitizer::setOutputFile()","Output file : %s ",outName.Data());
    }
    TDirectory* saveDir=gDirectory;
    outFile=new TFile(outName.Data(),"RECREATE");
    if(outFile)
    {
	outFile->cd();
	out=new TNtuple("ntuple","ntuple","s:m:c:" 
			"s1:m1:c1:"                
			"gE:gE2:"                  
			"gX:gX1:gY:gY1:"           
			"gTof:gTof1:"              
			"gMom:gMom1:"              
			"gLen:gLen1:"              
			"trackOld:trackNew:"       
			"parentOld:parentNew:"     
			"count");                  
	if(!out)
	{
	    Error("HTofDigitizer::setOutputFile()","Could not create Ntuple!");
	    exit(1);
	}
    } else {
	Error("HTofDigitizer::setOutputFile()","Could not create Output File!");
	exit(1);
    }
    saveDir->cd();
}
void HTofDigitizer::fillNtuple(HGeantTof* pold,HGeantTof* pnew,Int_t count)
{
    
    HGeantKine* kine=0;
    Int_t parentOld,parentNew;
    Int_t trackOld,trackNew;
    Float_t geaEner,geaX,geaY,geaTof,geaMom,trackLen ;
    pold->getHit(geaEner,geaX,geaY,geaTof,geaMom,trackLen);
    kine=(HGeantKine*)fGeantKineCat->getObject(pold->getTrack()-1);
    parentOld=kine->getParentTrack();
    trackOld =kine->getTrack();
    
    Float_t geaEner1,geaX1,geaY1,geaTof1,geaMom1,trackLen1 ;
    pnew->getHit(geaEner1,geaX1,geaY1,geaTof1,geaMom1,trackLen1);
    kine=(HGeantKine*)fGeantKineCat->getObject(pnew->getTrack()-1);
    parentNew=kine->getParentTrack();
    trackNew =kine->getTrack();
    Float_t dat[23]={0};
    dat[0] = pold->getSector();
    dat[1] = 21-pold->getModule();
    dat[2] = 7-pold->getCell();
    dat[3] = pnew->getSector();
    dat[4] = 21-pnew->getModule();
    dat[5] = 7-pnew->getCell();
    dat[6] = geaEner;
    dat[7] = geaEner1;
    dat[8] = geaX;
    dat[9] = geaX1;
    dat[10]= geaY;
    dat[11]= geaY1;
    dat[12]= geaTof;
    dat[13]= geaTof1;
    dat[14]= geaMom;
    dat[15]= geaMom1;
    dat[16]= trackLen;
    dat[17]= trackLen1;
    dat[18]= trackOld;
    dat[19]= trackNew;
    dat[20]= parentOld;
    dat[21]= parentNew;
    dat[22]= count;
    out->Fill(dat);
}
ClassImp(HTofDigitizer)