using namespace std;
#include "hmdc12fit.h"
#include "hdebug.h"
#include "hevent.h"
#include "hiterator.h"
#include "hspectrometer.h"
#include "hmatrixcategory.h"
#include <iostream>
#include <iomanip>
#include "hmdcsizescells.h"
#include "hgeomvector.h"
#include "hmdcsegsim.h"
#include "hmdchitsim.h"
#include "hmdcgetcontainers.h"
#include "hmdcclussim.h"
#include "hmdcdetector.h"
#include "hmdctrackfittera.h"
#include "hmdctrackfitterb.h"
#include "hmdctrackdset.h"
#include "hmdcclusinfsim.h"
#include "hruntimedb.h"
#include "hmdc34clfinder.h"
#include "hmdctrkcand.h"
#include "hmdcgeanttrack.h"
#include "hmdcclusfitsim.h"
#include "hmdclistcells.h"
ClassImp(HMdc12Fit)
ClassImp(HMdcFittersArray)
HMdcFittersArray::HMdcFittersArray(void) {
  nObj      = 0;
  fitAuthor = 1;
  fitpar    = 0;
  size      = 100;
  fitterArr = new HMdcTrackFitter* [size];
  for(Int_t i=0;i<size;i++) fitterArr[i] = 0;
}
HMdcFittersArray::~HMdcFittersArray(void) {
  if(fitterArr) {
    for(Int_t i=0;i<size;i++) if(fitterArr[i]!=0) delete fitterArr[i];
    delete [] fitterArr;
    fitterArr = NULL;
  }
}
void HMdcFittersArray::init(Int_t fitAut, HMdcTrackFitInOut* fpar) {
  fitpar    = fpar;
  fitAuthor = fitAut;
}
void HMdcFittersArray::expand(void) {
  Int_t newSize=size+50;
  HMdcTrackFitter** fitterArrOld=fitterArr;
  fitterArr=new HMdcTrackFitter* [newSize];
  for(Int_t i=0;i<size;i++) fitterArr[i]=fitterArrOld[i];
  for(Int_t i=size;i<newSize;i++) fitterArr[i]=0;
  size=newSize;
  delete [] fitterArrOld;
}
HMdcTrackFitter* HMdcFittersArray::getNewFitter(void) {
  if(nObj == size) expand();
  HMdcTrackFitter* fitter = fitterArr[nObj];
  if(fitter == NULL) {
    if(fitAuthor == 2) fitter = (HMdcTrackFitter*) new HMdcTrackFitterB(fitpar);
    else               fitter = (HMdcTrackFitter*) new HMdcTrackFitterA(fitpar);
    fitterArr[nObj]=fitter;
  }
  fitter->getInitParam()->setOneSecData();
  fitter->getFinalParam()->setOneSecData();
  nObj++;
  return fitter;
}
HMdc12Fit::HMdc12Fit(Int_t type,Int_t ver,Int_t dp,Bool_t hst,Bool_t prnt) {
  HMdcTrackDSet::setMdc12Fit(type,ver,dp,hst,prnt);
  setParContainers();
}
HMdc12Fit::HMdc12Fit(const Text_t *name,const Text_t *title,Int_t type,
    Int_t ver,Int_t dp,Bool_t hst, Bool_t prnt) : HReconstructor(name,title) {
  HMdcTrackDSet::setMdc12Fit(type,ver,dp,hst,prnt);
  setParContainers();
}
HMdc12Fit::HMdc12Fit() {
  setParContainers();
}
HMdc12Fit::HMdc12Fit(const Text_t *name,const Text_t *title)
    : HReconstructor(name,title) {
  setParContainers();
}
HMdc12Fit::~HMdc12Fit() {
  HMdcSizesCells::deleteCont();
  HMdcTrackDSet::clearP12Fit();
  if(iterClus){delete iterClus;iterClus=0;}
}
void HMdc12Fit::setParContainers(void) {
  HMdcTrackDSet::set12Fit(this);
  prntSt             = kFALSE;
  fSegCat            = NULL; 
  iterClus           = NULL;
  fHitCat            = NULL;
  fClusFitCat        = NULL;
  modForSeg[0]       = 1;
  modForSeg[1]       = 3;
  fitpar.setWeightCut(0.01);
  fitpar.setSignalSpeed(0.0);
  notFillByClus      = kFALSE;
  isCosmicData       = kFALSE;
  fillHitSeg         = kTRUE;
  pTrackInfSim       = NULL;
  useFitted          = kFALSE;
  useFittedTrPar     = kFALSE;
  findOffVertTrk     = kFALSE;
  nLayersCutOVT      = 0;
  nWiresCutOVT       = 0;
  
  setFakeSupprStep1Par(0, 4,3,4, 8);
  setFakeSupprStep1Par(1, 4,3,5,10);
  Float_t cutRealS0[8] = { 0.0, 0.1, 0.5 , 0.7, 1.0, 1.1, 1.3, 1.6};  
  Float_t cutFakeS0[8] = { 0.1, 0.1, 0.5 , 0.8, 1.1, 1.2, 1.5, 1.7};  
  setFakeSupprStep2Par(0, cutRealS0,cutFakeS0);
  Float_t cutRealS1[8] = { 0.0, 0.1, 0.5 , 0.8, 1.1, 1.2, 1.3, 1.5};  
  Float_t cutFakeS1[8] = { 0.1, 0.1, 0.65, 1.1, 1.2, 1.4, 1.5, 1.6};  
  setFakeSupprStep2Par(1, cutRealS1,cutFakeS1);
}
void HMdc12Fit::setFakeSupprStep1Par(UInt_t seg,Int_t n1,Int_t n2,Int_t n3,Int_t n4) {
  if(seg>1) return;
  nSharedLayersCut[seg] = n1;
  nLayerOrientCut[seg]  = n2;
  nDCellsMinCut[seg]    = n3;
  nDCellsCut[seg]       = n4;
}
void HMdc12Fit::setFakeSupprStep2Par(UInt_t seg,Float_t *cutReal,Float_t *cutFake) {
  
  if(seg>1) return;
  for(Int_t i=0;i<8;i++) {
    cutForReal[seg][i] = cutReal[i];
    cutForFake[seg][i] = cutFake[i];
  }
}
Bool_t HMdc12Fit::init(void) {
  HMdcGetContainers* fGetCont = HMdcGetContainers::getObject();
  fClusCat = fGetCont->getCatMdcClus();
  if( !fClusCat ) return kFALSE;
  iterClus=(HIterator *)fClusCat->MakeIterator();
  
  if(!fitpar.init()) return kFALSE;
  isGeant = fitpar.isGeant();
  HMdcDetector* fMdcDet = fGetCont->getMdcDetector();
  modForSeg[0] = HMdcTrackDSet::getModForSeg1();
  modForSeg[1] = HMdcTrackDSet::getModForSeg2();
  if(fillHitSeg) {
    if(modForSeg[0]>=0 && modForSeg[1]>0) {
      fSegCat = gHades->getCurrentEvent()->getCategory(catMdcSeg);
      if(!fSegCat) {
        if(isGeant) fSegCat = fMdcDet->buildMatrixCategory("HMdcSegSim",0.5F);
        else        fSegCat = fMdcDet->buildCategory(catMdcSeg);
        if (!fSegCat) return kFALSE;
        gHades->getCurrentEvent()->addCategory(catMdcSeg,fSegCat,"Mdc");
      }
    }
    fHitCat = gHades->getCurrentEvent()->getCategory(catMdcHit);
    if (!fHitCat) {
      if(isGeant) fHitCat = fMdcDet->buildMatrixCategory("HMdcHitSim",0.5F);
      else        fHitCat = fMdcDet->buildCategory(catMdcHit);
      if (!fHitCat) return kFALSE;
      gHades->getCurrentEvent()->addCategory(catMdcHit,fHitCat,"Mdc");
    }
  }
  if(isCosmicData) {
    fTrkCandCat = 0;
    fClusInfCat = 0;
  } else {
    fTrkCandCat = fGetCont->getCatMdcTrkCand(kTRUE);
    if(!fTrkCandCat) return kFALSE;
    fClusInfCat = fGetCont->getCatMdcClusInf(kTRUE);
    if(!fClusInfCat) return kFALSE;
    findOffVertTrk = HMdcTrackDSet::getFindOffVertTrkFlag();
  }
  locClInf.set(1,0);
  locSeg.set(2,0,0);
  locHit.set(2,0,0);
  locTrkCand.set(1,0);
  locClus.set(2,0,0);
  if(HMdcTrackDSet::getFitAuthor()==0) {
    Warning("init",
        "Hejdar's tack fitter not suported more, Alexander's tack fitter will used!");
    HMdcTrackDSet::setFitAuthor(1);
  }
      
  fittersArr[0].init(HMdcTrackDSet::getFitAuthor(),&fitpar);
  fittersArr[1].init(HMdcTrackDSet::getFitAuthor(),&fitpar);
  f34ClFinder  = HMdc34ClFinder::getExObject();
  if(isGeant) pTrackInfSim = HMdcGeantEvent::getMdcTrackInfSim();
  
  findOffVertTrk = HMdcTrackDSet::getFindOffVertTrkFlag();
  nLayersCutOVT  = HMdcTrackDSet::getNLayersCutOVT();
  nWiresCutOVT   = HMdcTrackDSet::getNWiresCutOVT();
  
  return kTRUE;
}
Bool_t HMdc12Fit::reinit(void) {
  if(!fitpar.reinit()) return kFALSE;
  if(isCosmicData) {
    clusFitAlg = 4;
    fitpar.setTargetScanFlag(kFALSE);
  } else {
    clusFitAlg = 1;
    if(HMdcTrackDSet::isCoilOff()) {
      if(HMdcTrackDSet::getClFinderType()==1) clusFitAlg = 2;
      else clusFitAlg = 3;
    } else useFittedTrPar = HMdcTrackDSet::useFittedSeg1ParFlag();
  }
  if(!prntSt) printStatusM();
  if(f34ClFinder != NULL) {
    printf("--------------------------------------------------------------------------------------------\n");
    printf("Outer cluster finder (HMdc34ClFinder):\n");
    printf("  Use track parameter of inner %s.\n",useFittedTrPar ? "segment (HMdcTrackParam)" :
                                                                   "cluster (HMdcClus)");
    if(useFitted) printf("  Skip not fitted inner segments.\n");
    f34ClFinder->printClFinderParam();
    printf("--------------------------------------------------------------------------------------------\n");
  }
  return kTRUE;
}
Int_t HMdc12Fit::execute(void) {
  if(HMdcTrackDSet::fPrint()) {
    fitpar.setPrintFlag(gHades->getEventCounter());
    if(fitpar.getPrintFlag()) printf(
      "============================== Event %i =============================\n",
      gHades->getEventCounter());
  }
  iterClus->Reset();
  for(Int_t s=0;s<6;s++) {
    indFirstSeg[s]  = -1;
    indLastSeg[s]   = -2;
    indFstTrCand[s] = -1;
    indLstTrCand[s] = -2;
  }
  if     (clusFitAlg == 1) fitAlgorithm1();   
  else if(clusFitAlg == 2) fitAlgorithm2();   
  else if(clusFitAlg == 3) fitAlgorithm3b();  
  else if(clusFitAlg == 4) fitAlgorithm4();   
  return 0;
}
Bool_t HMdc12Fit::testRestOfWires(Int_t sec) {
  HMdcEvntListCells *pEvListCells = HMdcEvntListCells::getExObject();
  locClus[0]    = sec;
  locTrkCand[0] = sec;
  Int_t nMdcsSeg2 = fitpar.getMdcSizesCells()->nModInSeg(sec,1);
  pSecListCells = &((*pEvListCells)[sec]);
  Int_t nNFCellsM1,nNFCellsM2;
  Int_t nLay1 = (*pSecListCells)[0].genNumNotFittedLayers(nNFCellsM1);
  Int_t nLay2 = (*pSecListCells)[1].genNumNotFittedLayers(nNFCellsM2);
  if(nLay1 + nLay2 < nLayersCutOVT) return kFALSE;  
  
  if(nNFCellsM1*nNFCellsM2 > nWiresCutOVT*nWiresCutOVT) return kFALSE;
  fitter = fittersArr[0].getFitter(0);
  if(fitter == NULL) fitter = fittersArr[0].getNewFitter();
  HMdcLineParam lineParam;
  HMdcList12GroupCells listCells;
  Int_t nlays = fitter->getWiresArr().testRestForTrack(sec,lineParam,listCells, 
                                                       nLay1+nLay2,nNFCellsM1+nNFCellsM2);
                         
  if(nlays < nLayersCutOVT) return kFALSE;
  locClus[0] = sec;
  locClus[1] = 0;    
  Int_t index;
  HMdcClus *pClusSeg1 = (HMdcClus*)fClusCat->getNewSlot(locClus,&index);
  if(!pClusSeg1) {
    Warning("execute","Sec.%i Segment %i No slot HMdcClus available",sec+1,1);
    return kFALSE;
  }
  if(isGeant) pClusSeg1 = (HMdcClus*)(new(pClusSeg1) HMdcClusSim(listCells));
  else        pClusSeg1 =             new(pClusSeg1) HMdcClus(listCells);
  pClusSeg1->setTarget(lineParam.x1(),0.,lineParam.y1(),0.,lineParam.z1(),0.);
  HMdcPlane *pl = lineParam.getSecondPlane();
  pClusSeg1->setPrPlane(pl->A(),pl->B(),pl->D());
  pClusSeg1->setXY(lineParam.x2(),0.,lineParam.y2(),0.);
  pClusSeg1->setSecSegInd(sec,0,index);  
  pClusSeg1->setMod(-1);
  pClusSeg1->setSumWt(0.);
  pClusSeg1->setRealLevel(nlays);
  pClusSeg1->setNBins(0);
  pClusSeg1->setTypeClFinder(256 + 0);  
  pClusSeg1->setMinCl(nLayersCutOVT-nLayersCutOVT/2,nLayersCutOVT/2);
                                                                                                                                   
  if(pTrackInfSim != NULL) pTrackInfSim->fillClusTrackInf((HMdcClusSim*)pClusSeg1);
  fittersArr[0].reset();
  Bool_t flag = fitSeg(pClusSeg1);
  if(!flag) return kFALSE;
  
  if(fitter->getSegIndex()<0) return kFALSE;
  HMdcTrkCand* fTrkCand = fillTrkCandISeg();
  if(fTrkCand == NULL) return kFALSE;
  
  if( !isFitted ) return kFALSE;
  
  if(nMdcsSeg2 <= 0) return kTRUE;
  if(findSeg2Clusters(fitter) <= 0) return kTRUE;
  Int_t firstCh,lastCh;
  pClusSeg1->getIndexRegChilds(firstCh,lastCh);
  fittersArr[1].reset();
  for(Int_t ind=firstCh;ind<=lastCh;ind++) {
    HMdcClus* fClstSeg2 = (HMdcClus*)fClusCat->getObject(ind);
    if(fClstSeg2 == NULL) return kTRUE;
    flag = nMdcsSeg2==1 ? fitMod(fClstSeg2,1) : fitSeg(fClstSeg2,1);
    if(!fillHitSeg || !flag || fitter->getSegIndex()<0) return kTRUE;
    
    fTrkCand = fillTrkCandOSeg(fTrkCand);
    if(fTrkCand == NULL) break;
  }
  return kTRUE;
}
void HMdc12Fit::sortGeantInf(void) {
  
  iterClus->Reset();
  HMdcClusSim* pClusSim;
  while ((pClusSim=(HMdcClusSim*)iterClus->Next())!=0) pClusSim->sortTrListByContr();
  
  Int_t nsegs = fSegCat->getEntries();
  for(Int_t i=0; i<nsegs; i++) ((HMdcSegSim*)fSegCat->getObject(i))->sortTrListByContr();
  
  if(HMdcTrackDSet::fNTuple()) {
    if(fClusFitCat == NULL) fClusFitCat = HMdcGetContainers::getObject()->getCatMdcClusFit();
    if(fClusFitCat != NULL) {
      Int_t nent = fClusFitCat->getEntries();
      for(Int_t n=0;n<nent;n++) {
        HMdcClusFitSim *pClusFitSim = (HMdcClusFitSim*)(fClusFitCat->getObject(n));
        if(pClusFitSim == NULL) continue;
        Int_t clInd = pClusFitSim->getClustCatIndex();
        HMdcClusSim* pClusSim = (HMdcClusSim*)(fClusCat->getObject(clInd));
        if(pClusSim == NULL) continue;
        Int_t segInd = pClusSim->getSegIndex();
        if(segInd<0) continue;
        HMdcSegSim* pSegSim = (HMdcSegSim*)(fSegCat->getObject(segInd));
        if(pSegSim == NULL) continue;
        Int_t track = pClusFitSim->getGeantTrackNum();
        if(track <= 0) continue;
        Int_t ind = pSegSim->findTrack(track);
        if(pSegSim->isFakeContribution(ind) ) pClusFitSim->setFakeFlag();
      }
    } 
  }
}
void HMdc12Fit::fitAlgorithm1(void) {
  Int_t maxNumSectors = ((HMatrixCategory*)fClusCat)->getSize(0);
  locClus[1]          = 0;
  Int_t fitType       = HMdcTrackDSet::getFitType();
  for(Int_t sec=0; sec<maxNumSectors; sec++) {
     
    locClus[0]    = sec;
    locTrkCand[0] = sec;
    iterClus->gotoLocation(locClus);
    Int_t nMdcsSeg1 = fitpar.getMdcSizesCells()->nModInSeg(sec,0);
    Int_t nMdcsSeg2 = fitpar.getMdcSizesCells()->nModInSeg(sec,1);
    HMdcClus * fClstSeg1;
    while((fClstSeg1=(HMdcClus*)iterClus->Next())) {
      
      Bool_t flag = kFALSE;
      Int_t typeClFnSeg1=fClstSeg1->getTypeClFinder();
      fittersArr[0].reset();
      if(nMdcsSeg1==1)           flag = fitMod(fClstSeg1); 
      else if(typeClFnSeg1==0) {                           
        if(fitType==0)           flag = fitSeg(fClstSeg1);
        else if(fitType==1)      flag = fitCombClusIndFit(fClstSeg1);
      } else if(typeClFnSeg1==1) flag = fitChambClus(fClstSeg1);
      else if(typeClFnSeg1==2)   flag = fitMixedClus(fClstSeg1);
      if(!flag) continue;
      
      fitter = fittersArr[0].getFitter(0); 
      if(fitter->getSegIndex()<0) continue;
      HMdcTrkCand* fTrkCand = fillTrkCandISeg();
      if(fTrkCand == NULL) continue;
      
      if(useFitted && !isFitted) continue;
      if(nMdcsSeg2 <= 0) continue;
      if(findSeg2Clusters(fitter) <= 0) continue;
      Int_t firstCh,lastCh;
      fClstSeg1->getIndexRegChilds(firstCh,lastCh);
      fittersArr[1].reset();
      for(Int_t ind=firstCh;ind<=lastCh;ind++) {
        HMdcClus* fClstSeg2 = (HMdcClus*)fClusCat->getObject(ind);
        if(fClstSeg2==0) {
          Error("fitAlgorithm1","Absent cluster with ind=%i!",ind);
          continue;
        }
        Int_t typeClFnSeg2 = fClstSeg2->getTypeClFinder();
        if(nMdcsSeg2==1)           flag = fitMod(fClstSeg2,1); 
        else if(typeClFnSeg2==0) {                             
          if(fitType==0)           flag = fitSeg(fClstSeg2,1);
          else if(fitType==1)      flag = fitCombClusIndFit(fClstSeg2,1);
        } else if(typeClFnSeg2==1) flag = fitChambClus(fClstSeg2,1);
        else if(typeClFnSeg2==2)   flag = fitMixedClus(fClstSeg2,1);
        if(!fillHitSeg) continue;
        if(!flag || fitter->getSegIndex()<0) continue;
        
        fTrkCand = fillTrkCandOSeg(fTrkCand);
        if(!fTrkCand) break;
      }
    }
    
    if(isGeant) sortGeantInf(); 
    
    suppressFakes(sec,0);
    if(findOffVertTrk) while (testRestOfWires(sec));
    suppressFakes(sec,1); 
    
    
    indFirstTrCand = indFstTrCand[sec];
    indLastTrCand  = indLstTrCand[sec];
    if(indFirstTrCand < 0 || indFirstTrCand >= indLastTrCand) continue;
    for(Int_t itr1=indFirstTrCand; itr1<indLastTrCand; itr1++) {
      HMdcTrkCand* trkCand1 = (HMdcTrkCand*)fTrkCandCat->getObject(itr1);
      Int_t ind1 = trkCand1->getSeg1Ind();
      Int_t ind2 = trkCand1->getSeg2Ind();
      if(ind1 < 0) continue;
      for(Int_t itr2=itr1+1; itr2<=indLastTrCand; itr2++) {
        HMdcTrkCand* trkCand2 = (HMdcTrkCand*)fTrkCandCat->getObject(itr2);
        if(ind1 != trkCand2->getSeg1Ind() || ind2 != trkCand2->getSeg2Ind()) continue;
        if(ind2 >= 0) {
          trkCand1->setSeg2Ind(-1);
          trkCand1->setFakeFlagSeg2();
        } 
        trkCand1->setFakeFlagSeg1();
        break;
      }
    }
  }  
  if(isGeant && fClusFitCat != NULL) {  
    Int_t nent = fClusFitCat->getEntries();
    for(Int_t n=0;n<nent;n++) {
      HMdcClusFitSim *pClusFitSim = (HMdcClusFitSim*)(fClusFitCat->getObject(n));
      HMdcSegSim     *pSegSim     = (HMdcSegSim*)fSegCat->getObject(n);
      if(pSegSim == NULL) continue;
      Int_t track = pClusFitSim->getGeantTrackNum();
      if(track <= 0) continue;
      Int_t ind = pSegSim->findTrack(track);
      if( pSegSim->isFakeContribution(ind) ) pClusFitSim->setFakeFlag();
    }
  }
}
Int_t HMdc12Fit::findSeg2Clusters(HMdcTrackFitter* fitter) {
  
  
  if(f34ClFinder == NULL) return 0;
  HMdcWiresArr& wiresArr =  fitter->getWiresArr();
  HMdc34ClFinderSec& f34CFSc=(*f34ClFinder)[wiresArr.getSector()];
  if(!&f34CFSc || f34CFSc.notEnoughWires()) return 0;
  if(isFitted && useFittedTrPar) {
    HMdcSeg* fSeg = (HMdcSeg*)fSegCat->getObject(fitter->getSegIndex());
    if(fSeg==0) return 0;
    return      f34CFSc.findClustersSeg2(fitter->getFinalParam(),wiresArr.getClust1());
  } else return f34CFSc.findClustersSeg2(wiresArr.getClust1());
}
void HMdc12Fit::fitAlgorithm2(void) {
  
  Int_t maxNumSectors  = ((HMatrixCategory*)fClusCat)->getSize(0);
  Int_t maxNumSegments = ((HMatrixCategory*)fClusCat)->getSize(1);
  for(locClus[0]=0; locClus[0]<maxNumSectors; locClus[0]++){
    for(locClus[1]=0; locClus[1]<maxNumSegments; locClus[1]++) {
       
      iterClus->gotoLocation(locClus);
      Int_t nMdcs = fitpar.getMdcSizesCells()->nModInSeg(locClus[0],locClus[1]);
      HMdcClus * fClst;
      while((fClst=(HMdcClus*)iterClus->Next())) {
        fittersArr[0].reset();
        if(nMdcs==1) fitMod(fClst);             
        else         fitChambClus(fClst);       
      }
    }
  }
  if(isGeant) sortGeantInf();
}
void HMdc12Fit::fitAlgorithm3(void) {
  
  
  Int_t maxNumSectors = ((HMatrixCategory*)fClusCat)->getSize(0);
  locClus[1]          = 0;
  Int_t fitType       = HMdcTrackDSet::getFitType();
  for(Int_t sec=0; sec<maxNumSectors; sec++){
     
    locClus[0]=sec;
    locTrkCand[0]=sec;
    iterClus->gotoLocation(locClus);
    Int_t nMdcsSeg1=fitpar.getMdcSizesCells()->nModInSeg(sec,0);
    Int_t nMdcsSeg2=fitpar.getMdcSizesCells()->nModInSeg(sec,1);
    HMdcClus * fClstSeg1;
    while((fClstSeg1=(HMdcClus*)iterClus->Next())) {
      
      Bool_t flag = kFALSE;
      Int_t typeClFnSeg1=fClstSeg1->getTypeClFinder();
      fittersArr[0].reset();
      if(nMdcsSeg1==1)           flag = fitMod(fClstSeg1); 
      else if(typeClFnSeg1==0) {                           
        if(fitType==0)           flag = fitSeg(fClstSeg1);
        else if(fitType==1)      flag = fitCombClusIndFit(fClstSeg1);
      } else if(typeClFnSeg1==2) flag = fitMixedClus(fClstSeg1);
      
      
      if(!flag) continue;
      
      
      fitter = fittersArr[0].getFitter(0); 
      if(fitter->getSegIndex()<0) continue;
      HMdcTrkCand* fTrkCand = fillTrkCandISeg();
      if(fTrkCand==0) continue;
      
      Int_t firstCh,lastCh;
      fClstSeg1->getIndexRegChilds(firstCh,lastCh);
      fittersArr[1].reset();
      for(Int_t ind=firstCh;ind<=lastCh;ind++) {
        HMdcClus* fClstSeg2 = (HMdcClus*)fClusCat->getObject(ind);
        if(fClstSeg2==0) {
          Error("fitAlgorithm3","Absent cluster with ind=%i!",ind);
          continue;
        }
        flag=kFALSE;
        Int_t typeClFnSeg2 = fClstSeg2->getTypeClFinder();
        if(nMdcsSeg2==1)      flag = fitMod(fClstSeg2,1); 
        else if(typeClFnSeg2==0) {                        
          if(fitType==0)      flag = fitSeg(fClstSeg2,1);
          else if(fitType==1) flag = fitCombClusIndFit(fClstSeg2,1);
        }
        if(!fillHitSeg) continue;
        if(!flag || fitter->getSegIndex()<0) continue;
        
        fTrkCand = fillTrkCandOSeg(fTrkCand);
        if(!fTrkCand) break;
      }
    }
  }
  if(isGeant) sortGeantInf();
}
void HMdc12Fit::fitAlgorithm3b(void) {
  
  
  Int_t fitType = HMdcTrackDSet::getFitType();
  HMdcClus* fClst1;
  while((fClst1=(HMdcClus*)iterClus->Next())) {
    if(fClst1->getIndexParent() >= 0) continue;
    fittersArr[0].reset();
    Int_t first,last;
    fClst1->getIndexRegChilds(first,last);
    HMdcClus* fClst2 = (first<0) ? 0:(HMdcClus*)fClusCat->getObject(first);
    Int_t sec=fClst1->getSec();
    Int_t seg=fClst1->getIOSeg();
    Bool_t flag=kFALSE;
    if(fClst2==0) {
      Int_t typeClFn=fClst1->getTypeClFinder();
      Int_t nMdcsSeg=fitpar.getMdcSizesCells()->nModInSeg(sec,seg);
      if(nMdcsSeg==1)        flag = fitMod(fClst1);  
      else if(typeClFn==0) {                         
        if(fitType==0)       flag = fitSeg(fClst1);
        else if(fitType==1)  flag = fitCombClusIndFit(fClst1);
      } else if(typeClFn==2) flag = fitMixedClus(fClst1);
      if(!flag) continue;
      if(!fillHitSeg) continue;
      fitter = fittersArr[0].getFitter(0); 
      if(fitter->getSegIndex()<0) continue;
      fillTrkCandISeg();
    } else {
      flag = fitSec(fClst1,fClst2);  
    }
  }
  if(isGeant) sortGeantInf();
}
void HMdc12Fit::fitAlgorithm4(void) {
  
  HMdcClus* fClstSeg;
  Int_t  fitType = HMdcTrackDSet::getFitType();
  while((fClstSeg=(HMdcClus*)iterClus->Next())) {
    Int_t sec=fClstSeg->getSec();
    Int_t seg=fClstSeg->getIOSeg();
    Int_t typeClFnSeg=fClstSeg->getTypeClFinder();
    fittersArr[0].reset();
    Int_t nMdcsSeg=fitpar.getMdcSizesCells()->nModInSeg(sec,seg);
    if(nMdcsSeg==1)           fitMod(fClstSeg); 
    else if(typeClFnSeg==0) {                          
      if(fitType==0)          fitSeg(fClstSeg);
      else if(fitType==1)     fitCombClusIndFit(fClstSeg);
    } else if(typeClFnSeg==2) fitMixedClus(fClstSeg);
  }
  if(isGeant) sortGeantInf();
}
Bool_t HMdc12Fit::fitMod(HMdcClus* fClst, Int_t arrInd) {
  
  Int_t modClus = fClst->getMod();
  Int_t iMod;
  if(modClus<0) iMod = (fClst->getNDrTimesMod(0)) ? 0:1; 
  else          iMod = modClus&1;
    
  fitter = fittersArr[arrInd].getNewFitter();
  if(pTrackInfSim) pTrackInfSim->setWiresArr(&(fitter->getWiresArr()));
  if(!fitter->setClustAndFill(fClst)) return kFALSE;
  fitter->setRegionOfWires();
  if(fClst->getNLayersMod(iMod)<5) isFitted = kFALSE;
  else                             isFitted = fitter->fitCluster();
  if(!fillHitSeg) return kTRUE;
  if(!isFitted) {
    hitSegFiller.setClusParam(fClst,HMdcTrackDSet::isCoilOff());
    if(fillHitSegByClus(iMod)) fClst->setSegIndex(fitter->getSegIndex());
  } else  {
    hitSegFiller.setFitParam(*(fitter->getFinalParam())); 
    if(fillHitSegByFit(iMod)) fClst->setSegIndex(fitter->getSegIndex());
    
    
  }
  return kTRUE;
}
Bool_t HMdc12Fit::fitSeg(HMdcClus* fClst, Int_t arrInd) {
  
  fitter = fittersArr[arrInd].getNewFitter();
  if(pTrackInfSim) pTrackInfSim->setWiresArr(&(fitter->getWiresArr()));
  if(fClst==NULL || !fitter->setClustAndFill(fClst)) return kFALSE;
  fitter->setRegionOfWires();
  isFitted = fitter->fitCluster();
  if(!fillHitSeg) return kTRUE;
  if(!isFitted) {
    hitSegFiller.setClusParam(fClst,HMdcTrackDSet::isCoilOff());
    if(fillHitSegByClus()) fClst->setSegIndex(fitter->getSegIndex());
  } else  {
    hitSegFiller.setFitParam(*(fitter->getFinalParam())); 
    if(fillHitSegByFit()) fClst->setSegIndex(fitter->getSegIndex());
    
    
    
    if(fClst->getIOSeg() == 0 && findOffVertTrk) {
      HMdcSeg* pSeg = (HMdcSeg*)fSegCat->getObject(fitter->getSegIndex());
      if(fClst->getNBins() == 0) {                       
        Int_t nUnWires = pSecListCells->getNFittedUnWires2(0,pSeg);
        Int_t nWrTot   = pSeg->getSumWires();
        if(nWrTot-nUnWires >= nUnWires) {
          setFake(pSeg);
          return kFALSE;
        }
        
        pSeg->ResetBit(kRealKeep);
        pSecListCells->addToNFittedCounters(0,pSeg);
        pSeg->SetBit(kInFittedList);
      } else if(pSeg->getNLayers() < 7) setFake(pSeg);  
    }
    
    
  }
  return kTRUE;
}
Bool_t HMdc12Fit::fitSec(HMdcClus* fClst1, HMdcClus* fClst2) {
  
  fitter = fittersArr[0].getNewFitter();
  if(pTrackInfSim) pTrackInfSim->setWiresArr(&(fitter->getWiresArr()));
  if(!fitter->setClustAndFill(fClst1,fClst2)) return kFALSE;
  fitter->setRegionOfWires();
  HMdcTrkCand* fTrkCand = 0;
  isFitted = fitter->fitCluster();
  if(!fillHitSeg) return kTRUE;
  if(!isFitted) {
    hitSegFiller.setClusParam(fClst1,HMdcTrackDSet::isCoilOff());
    if(fillHitSegByClus(-1)) {
      fClst1->setSegIndex(fitter->getSegIndex());
      if(fTrkCandCat) {
        fTrkCand = fillTrkCandISeg();
        if(fTrkCand == 0) return kFALSE;
      }
    }
    if(fillHitSegByClus(-2)) {
      fClst2->setSegIndex(fitter->getSegIndex());
      if(fTrkCand) fTrkCand = fillTrkCandOSeg(fTrkCand);
    }
  } else  {
    hitSegFiller.setFitParam(*(fitter->getFinalParam())); 
    if(fillHitSegByFit(-1)) {
      fClst1->setSegIndex(fitter->getSegIndex());
      if(fTrkCandCat) {
        fTrkCand=fillTrkCandISeg();
        if(fTrkCand==0) return kFALSE;
      }
    }
    if(fillHitSegByFit(-2)) {
      fClst2->setSegIndex(fitter->getSegIndex());
      if(fTrkCand) fTrkCand = fillTrkCandOSeg(fTrkCand);
    }
    
    
  }
  return kTRUE;
}
Bool_t HMdc12Fit::fit2Sectors(HMdcClus* fClst1, HMdcClus* fClst2,
                              HMdcClus* fClst3, HMdcClus* fClst4) {
  
  
  fitter = fittersArr[0].getNewFitter();
  if(pTrackInfSim) pTrackInfSim->setWiresArr(&(fitter->getWiresArr()));
  if(!fitter->setClustAndFill(fClst1,fClst2,fClst3,fClst4)) return kFALSE;
  fitter->setRegionOfWires();
  isFitted = fitter->fitCluster();
  if(!fillHitSeg) return kTRUE;
  if(!isFitted) {
    
    hitSegFiller.setClusParam(fClst1,HMdcTrackDSet::isCoilOff());
    if(fillHitSegByClus(-1) && fClst1!=NULL) fClst1->setSegIndex(fitter->getSegIndex());
    if(fillHitSegByClus(-2) && fClst2!=NULL) fClst2->setSegIndex(fitter->getSegIndex());
    
    if(fClst3) hitSegFiller.setClusParam(fClst3,HMdcTrackDSet::isCoilOff());
    else       hitSegFiller.setClusParam(fClst4,HMdcTrackDSet::isCoilOff());
    if(fillHitSegByClus(-3) && fClst3!=NULL) fClst3->setSegIndex(fitter->getSegIndex());
    if(fillHitSegByClus(-4) && fClst4!=NULL) fClst4->setSegIndex(fitter->getSegIndex());
    
  } else  {
    hitSegFiller.setFitParam(*(fitter->getFinalParam())); 
    if(fillHitSegByFit(-1) && fClst1!=NULL) fClst1->setSegIndex(fitter->getSegIndex());
    if(fillHitSegByFit(-2) && fClst2!=NULL) fClst2->setSegIndex(fitter->getSegIndex());
    if(fitter->getWiresArr().getOutputListCells2().getNDrTimes() > 0) {
      HMdcTrackParam parInSec2(*(fitter->getFinalParam()));
      Int_t sec2 = fitter->getWiresArr().getSector2();
      fitpar.getMdcSizesCells()->transLineToAnotherSec(parInSec2,sec2);
      hitSegFiller.setFitParamForSecondSec(parInSec2);
      if(fillHitSegByFit(-3) && fClst3!=NULL) fClst3->setSegIndex(fitter->getSegIndex());
      if(fillHitSegByFit(-4) && fClst4!=NULL) fClst4->setSegIndex(fitter->getSegIndex());
    }
    
    
  }
  return kTRUE;
}
Bool_t HMdc12Fit::fitNSectors(HMdcClus* cl1, HMdcClus* cl2,HMdcClus* cl3, HMdcClus* cl4,
                              HMdcClus* cl5, HMdcClus* cl6,HMdcClus* cl7, HMdcClus* cl8) {
  
  
  fitter = fittersArr[0].getNewFitter();
  if(pTrackInfSim) pTrackInfSim->setWiresArr(&(fitter->getWiresArr()));
  if( !fitter->setClustAndFill(cl1,cl2,cl3,cl4,cl5,cl6,cl7,cl8) ) return kFALSE;
  fitter->setRegionOfWires();
  isFitted = fitter->fitCluster();
  if(!fillHitSeg) return kTRUE;
  if(!isFitted) {
    
    hitSegFiller.setClusParam(cl1,HMdcTrackDSet::isCoilOff());
    if(cl1!=NULL && fillHitSegByClus(-1)) cl1->setSegIndex(fitter->getSegIndex());
    if(cl2!=NULL && fillHitSegByClus(-2)) cl2->setSegIndex(fitter->getSegIndex());
    
    if(cl3!=NULL) hitSegFiller.setClusParam(cl3,HMdcTrackDSet::isCoilOff());
    else          hitSegFiller.setClusParam(cl4,HMdcTrackDSet::isCoilOff());
    if(cl3!=NULL && fillHitSegByClus(-3)) cl3->setSegIndex(fitter->getSegIndex());
    if(cl4!=NULL && fillHitSegByClus(-4)) cl4->setSegIndex(fitter->getSegIndex());
    if(cl5==NULL && cl6==NULL) return kTRUE;
    if(cl5!=NULL) hitSegFiller.setClusParam(cl5,HMdcTrackDSet::isCoilOff());
    else          hitSegFiller.setClusParam(cl6,HMdcTrackDSet::isCoilOff());
    if(cl5!=NULL && fillHitSegByClus(-5)) cl5->setSegIndex(fitter->getSegIndex());
    if(cl6!=NULL && fillHitSegByClus(-6)) cl6->setSegIndex(fitter->getSegIndex());
    if(cl7==NULL && cl8==NULL) return kTRUE;
    if(cl7!=NULL) hitSegFiller.setClusParam(cl7,HMdcTrackDSet::isCoilOff());
    else          hitSegFiller.setClusParam(cl8,HMdcTrackDSet::isCoilOff());
    if(cl7!=NULL && fillHitSegByClus(-7)) cl7->setSegIndex(fitter->getSegIndex());
    if(cl8!=NULL && fillHitSegByClus(-8)) cl8->setSegIndex(fitter->getSegIndex());
  } else {
    hitSegFiller.setFitParam(*(fitter->getFinalParam())); 
    if(cl1 && fillHitSegByFit(-1)) cl1->setSegIndex(fitter->getSegIndex());
    if(cl2 && fillHitSegByFit(-2)) cl2->setSegIndex(fitter->getSegIndex());
    if(fitter->getWiresArr().getOutputListCells2().getNDrTimes() > 0) {
      HMdcTrackParam parInSec2(*(fitter->getFinalParam()));
      Int_t sec2 = fitter->getWiresArr().getSector2();
      fitpar.getMdcSizesCells()->transLineToAnotherSec(parInSec2,sec2);
      hitSegFiller.setFitParamForSecondSec(parInSec2);
      if(cl3!=NULL && fillHitSegByFit(-3)) cl3->setSegIndex(fitter->getSegIndex());
      if(cl4!=NULL && fillHitSegByFit(-4)) cl4->setSegIndex(fitter->getSegIndex());
    }
    if(cl5==NULL && cl6==NULL) return kTRUE;
    if(fitter->getWiresArr().getOutputListCells3().getNDrTimes() > 0) {
      HMdcTrackParam parInSec3(*(fitter->getFinalParam()));
      Int_t sec3 = fitter->getWiresArr().getSector3();
      fitpar.getMdcSizesCells()->transLineToAnotherSec(parInSec3,sec3);
      hitSegFiller.setFitParamForSecondSec(parInSec3);
      if(cl5!=NULL && fillHitSegByFit(-5)) cl5->setSegIndex(fitter->getSegIndex());
      if(cl6!=NULL && fillHitSegByFit(-6)) cl6->setSegIndex(fitter->getSegIndex());
    }
    if(cl7==NULL && cl8==NULL) return kTRUE;
    if(fitter->getWiresArr().getOutputListCells4().getNDrTimes() > 0) {
      HMdcTrackParam parInSec4(*(fitter->getFinalParam()));
      Int_t sec4 = fitter->getWiresArr().getSector4();
      fitpar.getMdcSizesCells()->transLineToAnotherSec(parInSec4,sec4);
      hitSegFiller.setFitParamForSecondSec(parInSec4);
      if(cl7!=NULL && fillHitSegByFit(-7)) cl7->setSegIndex(fitter->getSegIndex());
      if(cl8!=NULL && fillHitSegByFit(-8)) cl8->setSegIndex(fitter->getSegIndex());
    }
  }
  return kTRUE;
}
Bool_t HMdc12Fit::fitCombClusIndFit(HMdcClus* fClst, Int_t arrInd) {
  
  fitter = fittersArr[arrInd].getNewFitter();
  if(pTrackInfSim) pTrackInfSim->setWiresArr(&(fitter->getWiresArr()));
  if(!fitter->setClustAndFill(fClst)) return kFALSE;
  Int_t hitIndex[2];
  Int_t seg = fClst->getIOSeg();
  Int_t nFittedHits = 0;
  for(Int_t iMod=0; iMod<2; iMod++) {
    Int_t mod=iMod+seg*2;
    fitter->setRegionOfWires(mod);
    if(fClst->getNLayersMod(iMod)<5) isFitted = kFALSE;
    else                             isFitted = fitter->fitCluster(mod);
    if(!fillHitSeg) continue;
    if(!isFitted) {
      hitSegFiller.setClusParam(fClst,HMdcTrackDSet::isCoilOff());
      hitIndex[iMod] = fillHitByClus(mod);
    } else {
      nFittedHits++;
      hitSegFiller.setFitParam(*(fitter->getFinalParam())); 
      hitIndex[iMod] = fillHitByFit(mod);
    }
  }
  isFitted = nFittedHits==2;
  if(fillHitSeg) fillSegBy2Hits(hitIndex[0],hitIndex[1]);
  return kTRUE;
}
Bool_t HMdc12Fit::fitChambClus(HMdcClus* fClst, Int_t arrInd) {
  
  Int_t modClus=fClst->getMod();
  if(modClus<0) return kFALSE;
  fitter = fittersArr[arrInd].getNewFitter();
  if(pTrackInfSim) pTrackInfSim->setWiresArr(&(fitter->getWiresArr()));
  if(!fitter->setClustAndFill(fClst)) return kFALSE;
  Int_t iMod=modClus&1;
  fitter->setRegionOfWires();
  isFitted = fitter->fitCluster();
  if(!fillHitSeg) return kTRUE;
  if(!isFitted) {
    hitSegFiller.setClusParam(fClst,HMdcTrackDSet::isCoilOff());
    if(modClus==modForSeg[fitter->getWiresArr().getSegment()]) {
      if(fillHitSegByClus(iMod)) fClst->setSegIndex(fitter->getSegIndex());
    } else fillHitByClus(modClus);
  } else  {
    hitSegFiller.setFitParam(*(fitter->getFinalParam())); 
    if(modClus==modForSeg[fitter->getWiresArr().getSegment()]) {
      if(fillHitSegByFit(iMod)) fClst->setSegIndex(fitter->getSegIndex());
    } else fillHitByFit(modClus);
    
    
  }
  return kTRUE;
}
Bool_t HMdc12Fit::fitMixedClus(HMdcClus* fClst, Int_t arrInd) {
  
  Int_t modClus=fClst->getMod();
  if(modClus<0) return kFALSE;
  Int_t iMod=modClus&1;
  Int_t addMod=fClst->getIOSeg()*2 + (iMod^1);
  if(fClst->getNLayersMod(iMod^1)<HMdcTrackDSet::getMixFitCut()) return kFALSE;
  fitter = fittersArr[arrInd].getNewFitter();
  if(pTrackInfSim) pTrackInfSim->setWiresArr(&(fitter->getWiresArr()));
  if(!fitter->setClustAndFill(fClst)) return kFALSE;
  fitter->setRegionOfWires();
  isFitted = fitter->fitCluster();
  if(!isFitted) {
    if(fillHitSeg && fClst->getNLayersMod(iMod^1) >= HMdcTrackDSet::getMixClusCut()) {
      hitSegFiller.setClusParam(fClst,HMdcTrackDSet::isCoilOff());
      if(fillHitSegByClus(iMod)) fClst->setSegIndex(fitter->getSegIndex());
    }
  } else  {
    if(fitter->getWiresArr().getOutputListCells().getNLayersMod(addMod) <
                                         HMdcTrackDSet::getMixFitCut()) isFitted = kFALSE;
    else if(fillHitSeg) {
      hitSegFiller.setFitParam(*(fitter->getFinalParam())); 
      fillHitSegByFit(iMod); 
    };
    
    
  }
  return kTRUE;
}
void HMdc12Fit::fillClusInf(HMdcHit* fHit, Int_t iMod, Char_t fitSt,Int_t indClusFit) {
  fHit->setTrackFinder(1);
  if(fClusInfCat==0) return; 
  Int_t index;
  HMdcClusInf* fClusInf=(HMdcClusInf*)fClusInfCat->getNewSlot(locClInf,&index);
  if(!fClusInf) {
    Warning("fillClusInf","No slot HMdcClusInf available");
    return;
  }
  fClusInf = (isGeant) ? (HMdcClusInf*)(new(fClusInf) HMdcClusInfSim) :
                                        new(fClusInf) HMdcClusInf;
  fHit->setClusInfIndex(index);
  fClusInf->setFitStat(fitSt);
  Int_t mod = fHit->getModule();
  HMdcWiresArr& wires = fitter->getWiresArr();
  HMdcClus* fClst = wires.getClust2() && mod>1 ? 
                    wires.getClust2() : wires.getClust1();
  
  Int_t nmods=fClst->getMod();
  fClusInf->setNModInCl((nmods<0) ? -nmods:1); 
  fClusInf->setNModInFit(wires.getNModulesInFit());
  fClusInf->setClusIndex(fClst->getOwnIndex());
  fClusInf->setClusFitIndex(fitter->getIndClusFit());
  
  fClusInf->setXYHit(fHit->getX(),fHit->getY());
  
  HMdcSizesCellsMod* fSCMod = fitpar.getSCellsModArr(wires.getSector())[mod];
  Double_t xm,ym,zm;
  fSCMod->calcIntersection(
      fClst->getXTarg(),fClst->getYTarg(),fClst->getZTarg(),
      fClst->getX(),    fClst->getY(),    fClst->getZ(),    xm,ym,zm);
  fSCMod->transTo(xm,ym,zm);
  fClusInf->setXYClus(xm,ym);
  
  if(iMod==0) {
    fClusInf->setLevelClFinding(fClst->getClFnLevelM1());
    fClusInf->setClusSize(fClst->getClusSizeM1());
    fClusInf->setNMergClust(fClst->getNMergClustM1());
    fClusInf->setNDrTimes(fClst->getNDrTimesM1());
    fClusInf->setSigma1(fClst->getSigma1M1());
    fClusInf->setSigma2(fClst->getSigma2M1());
    fClusInf->setAlpha(fClst->getAlphaM1());
    fClusInf->setNLayers(fClst->getNLayersMod(0));
    if(!fitSt) {
      fClusInf->setNLayersFitted(fClst->getNLayersMod(0));
      fClusInf->setNDrTimesFitted(fClst->getNDrTimesM1());
    }
  } else {
    fClusInf->setLevelClFinding(fClst->getClFnLevelM2());
    fClusInf->setClusSize(fClst->getClusSizeM2());
    fClusInf->setNMergClust(fClst->getNMergClustM2());
    fClusInf->setNDrTimes(fClst->getNDrTimesM2());
    fClusInf->setSigma1(fClst->getSigma1M2());
    fClusInf->setSigma2(fClst->getSigma2M2());
    fClusInf->setAlpha(fClst->getAlphaM2());
    fClusInf->setNLayers(fClst->getNLayersMod(1));
    if(!fitSt) {
      fClusInf->setNLayersFitted(fClst->getNLayersMod(1));
      fClusInf->setNDrTimesFitted(fClst->getNDrTimesM2());
    }
  }
  if(fitSt) {
    fClusInf->setNLayersFitted(fitter->getWiresArr().getOutputListCells().getNLayersMod(mod));
    fClusInf->setNDrTimesFitted(fitter->getWiresArr().getOutputListCells().getNDrTimesMod(mod));
  }
  if(isGeant) {
    HMdcClusSim* fClSim=(HMdcClusSim*)fClst;
    ((HMdcClusInfSim*)fClusInf)->setTracksList(fClSim->getNTracksMod(iMod),
        fClSim->getListTrM(iMod),fClSim->getNTimesM(iMod));
  }
}
void HMdc12Fit::fillClusInf(HMdcSeg* fSeg,Bool_t secondSec) {
  HMdcWiresArr& wires = fitter->getWiresArr();
  HMdcClus* fClst1 = wires.getClust1();
  HMdcClus* fClst2 = wires.getClust2();
  if(secondSec) {
    fClst1 = wires.getClust3();
    fClst2 = wires.getClust4();
  }
  Int_t nMrCl = fClst1->getNMergClust();
  if(nMrCl>99) nMrCl=99;
  HMdcClus* fClst=(fClst2 && fSeg->getIOSeg()==1) ? fClst2 : fClst1;
  fSeg->setClusInfo(fClst->getNBins(),fClst->getNDrTimes(),fClst1->getNMergClust());
  
  fSeg->setClusIndex(fClst->getOwnIndex());
}
Bool_t HMdc12Fit::fillSegBy2Hits(Int_t ind1, Int_t ind2) {
  HMdcWiresArr& wires = fitter->getWiresArr();
  Int_t segment = wires.getSegment();
  Int_t mod1    = segment*2;
  Int_t mod2    = mod1+1;
  Int_t sector  = wires.getSector();
  HMdcSizesCellsMod* fSCMod1=fitpar.getSCellsModArr(sector)[mod1];
  HMdcSizesCellsMod* fSCMod2=fitpar.getSCellsModArr(sector)[mod2];
  if(!fSCMod1 || !fSCMod2) return kFALSE;
  HMdcHit* h1=(HMdcHit*)fHitCat->getObject(ind1);
  HMdcHit* h2=(HMdcHit*)fHitCat->getObject(ind2);
  if(h1==0 || h2==0) return kFALSE;
  Float_t x1,y1,z1,ex1,ey1;
  Float_t x2,y2,z2,ex2,ey2;
  h1->getXY(x1,ex1,y1,ey1);
  h2->getXY(x2,ex2,y2,ey2);
  fSCMod1->transFromZ0(x1,y1,z1);
  fSCMod2->transFromZ0(x2,y2,z2);
  ey1 /= sqrt(1.+fSCMod1->B()*fSCMod1->B()); 
  ey2 /= sqrt(1.+fSCMod2->B()*fSCMod2->B()); 
  HMdcSeg* fSeg = getSegSlot(sector,segment);
  if(!fSeg) return kFALSE;
  for(Int_t l=0; l<6; l++) {
    copySignId(h1,0,l,fSeg);
    copySignId(h2,1,l,fSeg);
  }
  Double_t zm, r0, theta, phi;
  Double_t eZm, eR0, eTheta, ePhi;
  HMdcSizesCells::calcMdcSeg(x1,y1,z1,x2,y2,z2,ex1,ey1,0.,ex2,ey2,
      -fSCMod1->A(),-fSCMod1->B(),-fSCMod2->A(),-fSCMod2->B(),
      zm,eZm, r0,eR0,theta,eTheta, phi,ePhi);
  fSeg->setPar(zm, eZm, r0, eR0, theta, eTheta, phi, ePhi);
  
  HMdcSizesCellsSec& fSCSec=(*(fitpar.getMdcSizesCells()))[sector];
  Double_t zPrime=zm; 
  Double_t rPrime=r0;
  if(&fSCSec) fSCSec.calcRZToTargLine(x1,y1,z1,x2,y2,z2,zPrime,rPrime);
  fSeg->setZprime(zPrime);
  fSeg->setRprime(rPrime);
  
  fSeg->setHitInd(0,ind1);
  fSeg->setHitInd(1,ind2);
  fSeg->setChi2(-2.);
  if(isGeant) ((HMdcSegSim*)fSeg)->calcNTracks();
  
  if(h1->getChi2()>=0 || h2->getChi2()>=0) fitter->setFitStatus(kTRUE); 
  fillClusInf(fSeg);
  return kTRUE;
}
void HMdc12Fit::copySignId(HMdcHit* hit,Int_t mod,Int_t lay,HMdcSeg* seg) {
  
  Int_t nHits=hit->getNCells(lay);
  if(nHits<=0||nHits>4) return;
  Int_t id[4]={0,0,0,0};
  Int_t cell=hit->getCell(lay,0);
  for(Int_t i=0; i<nHits; i++) {
    Int_t n=hit->getCell(lay,i) - cell;
    if(n>=0&&n<4) id[n] = hit->getSignId(lay,i);
  }
  seg->setSignId(lay+mod*6,cell,id[0],id[1],id[2],id[3]);
}
Int_t HMdc12Fit::fillHitByFit(Int_t mod) {
  HMdcWiresArr& wires = fitter->getWiresArr();
  HMdcList24GroupCells* lCells = &(fitter->getWiresArr().getOutputListCells());
  Int_t sector = wires.getSector();
  if(mod>=4) {  
    lCells = &(fitter->getWiresArr().getOutputListCells2());
    sector = wires.getSector2();
    if(sector<0) return -1;
    mod -= 4; 
  }
  if(lCells->getNDrTimesMod(mod) == 0) return -1;
  HMdcSizesCellsMod* fSCMod=fitpar.getSCellsModArr(sector)[mod];
  if(!fSCMod) return -1;
  Int_t index=-1;
  HMdcHit* fHit = getHitSlot(sector,mod,index);
  if(!fHit) return -1;
  hitSegFiller.fillMdcHit(fSCMod,fHit);
  fHit->setChi2(fitter->getChi2()); 
  setGroup(lCells, fHit, mod);
  fillClusInf(fHit,mod&1,1,fitter->getIndClusFit()); 
  return index;
}
Bool_t HMdc12Fit::fillHitSegByFit(Int_t iMod) {
  
  
  
  
  
  
  
  HMdcWiresArr& wires = fitter->getWiresArr();
  Int_t segInd = wires.getSegment();
  if(iMod<=-1 && iMod>=-4) segInd = -iMod-1;  
  Int_t segment = segInd&1;
  HMdcList24GroupCells* lCells = &(wires.getOutputListCells());
  Int_t sector = wires.getSector();
  if(segInd>1) {
    lCells = &(wires.getOutputListCells2());
    sector = wires.getSector2();
    if(sector<0) return kFALSE;
  }
  if(lCells->getNDrTimes(segment*12,segment*12+11) == 0) return kFALSE;
  
  HMdcSeg* fSeg = getSegSlot(sector,segment);
  if(!fSeg) return kFALSE;
  Int_t indx1=-1;
  if(iMod!=1) indx1=fillHitByFit(segInd*2);
  Int_t indx2=-1;
  if(iMod!=0) indx2=fillHitByFit(segInd*2+1);
  if(indx1>=0) fSeg->setHitInd(0,indx1);
  if(indx2>=0) fSeg->setHitInd(1,indx2);
  fSeg->setChi2(fitter->getChi2()); 
  setGroup(lCells, fSeg, segment);
  HMdcSizesCellsSec& fSCSec=(*(fitpar.getMdcSizesCells()))[sector];
  const HGeomVector* targ=0;
  if(&fSCSec) targ=&(fSCSec.getTargetMiddlePoint());
  if( findOffVertTrk && segment==0 && wires.getClust1()->getNBins()==0) fSeg->setOffVertexClus();
 
  hitSegFiller.fillMdcSeg(fSeg,targ);
  
  fillClusInf(fSeg,segInd>1);
  return kTRUE;
}
Int_t HMdc12Fit::fillHitByClus(Int_t mod) {
  HMdcWiresArr& wires = fitter->getWiresArr();
  HMdcList24GroupCells* lCells = &(fitter->getWiresArr().getInputListCells());
  Int_t sector = wires.getSector();
  if(mod>=12) {  
    lCells = &(wires.getInputListCells4());
    sector = wires.getSector4();
  } else if(mod>=8) {  
    lCells = &(wires.getInputListCells3());
    sector = wires.getSector3();
  } else if(mod>=4) {  
    lCells = &(wires.getInputListCells2());
    sector = wires.getSector2();
  }
  mod &= 3;
  if(sector<0) return -1;
  
  if(lCells->getNDrTimesMod(mod) == 0) return -1;
  HMdcSizesCellsMod* fSCMod = fitpar.getSCellsModArr(sector)[mod];
  if(!fSCMod) return -1;
  Int_t index = -1;
  HMdcHit* fHit = getHitSlot(sector,mod,index);
  if(!fHit) return -1;
  hitSegFiller.fillMdcHitByClus(fSCMod,fHit);
  fHit->setChi2(-1.);
  setGroup(lCells, fHit,mod);
  fillClusInf(fHit,mod&1,0); 
  return index;
}
Bool_t HMdc12Fit::fillHitSegByClus(Int_t iMod) {
  
  
  
  
  
  
  
  
  HMdcWiresArr& wires = fitter->getWiresArr();
  Int_t segInd = wires.getSegment();
  if(iMod<=-1 && iMod>=-8) segInd = -iMod-1;  
  Int_t secInd = segInd/4;
  Int_t segment = segInd&1;
  HMdcList24GroupCells* lCells = &(wires.getInputListCells());
  Int_t sector = wires.getSector();
  if(secInd==1) {
    lCells = &(wires.getInputListCells2());
    sector = wires.getSector2();
  } else if(secInd==2) {
    lCells = &(wires.getInputListCells3());
    sector = wires.getSector3();
  } else if(secInd==3) {
    lCells = &(wires.getInputListCells4());
    sector = wires.getSector4();
  }
  if(sector<0) return kFALSE;
  if(lCells->getNDrTimes(segment*12,segment*12+11) == 0) return kFALSE;
  
  HMdcSeg* fSeg = getSegSlot(sector,segment);
  if(fSeg == NULL) return kFALSE;
  Int_t indx1 = -1;
  if(iMod != 1) indx1 = fillHitByClus(segInd*2);
  Int_t indx2 = -1;
  if(iMod != 0) indx2 = fillHitByClus(segInd*2+1);
  if(indx1 >= 0) fSeg->setHitInd(0,indx1);
  if(indx2 >= 0) fSeg->setHitInd(1,indx2);
  fSeg->setChi2(-1.);
  setGroup(lCells, fSeg, segment);
  HMdcSizesCellsSec& fSCSec = (*(fitpar.getMdcSizesCells()))[sector];
  const HGeomVector* targ   = (&fSCSec) ? &(fSCSec.getTargetMiddlePoint()) : 0;
  hitSegFiller.fillMdcSegByClus(fSeg,targ,fitter->getInitParam());
  
  fillClusInf(fSeg,segInd>1);
  return kTRUE;
}
HMdcHit* HMdc12Fit::getHitSlot(Int_t sec, Int_t mod, Int_t& index) {
  
  locHit[0] = sec;
  locHit[1] = mod;
  HMdcHit* fHit = (HMdcHit*)fHitCat->getNewSlot(locHit,&index);
  if(!fHit) {
    Warning("getHitSlot"," No slot in catMdcHit available");
    index=-1;
    return 0;
  }
  if(isGeant) fHit=(HMdcHit*) new(fHit) HMdcHitSim;
  else fHit= new(fHit) HMdcHit;
  fHit->setSecMod(sec,mod);
  return fHit;
}
HMdcSeg* HMdc12Fit::getSegSlot(Int_t sec,Int_t segment) {
  
  if(sec<0) return 0;
  locSeg[0] = sec;
  locSeg[1] = segment;
  Int_t index;
  HMdcSeg* fSeg = (HMdcSeg*)fSegCat->getNewSlot(locSeg,&index);
  if(!fSeg) {
    Warning("getSegSlot"," No slot in catMdcSeg available");
    fitter->setSegIndex(-1);
    return 0;
  }
  fitter->setSegIndex(index);      
  fSeg = (isGeant) ? (HMdcSeg*)(new(fSeg) HMdcSegSim) : new(fSeg) HMdcSeg;
  fSeg->setSec(sec);
  fSeg->setIOSeg(segment);
  if( !isCosmicData ) {
    if(indFirstSeg[sec] < 0) indFirstSeg[sec] = index;
    indLastSeg[sec] = index;
  }
  return fSeg;
}
HMdcTrkCand* HMdc12Fit::fillTrkCandISeg(void) {
  if(fTrkCandCat == NULL) return NULL;
  Int_t index;
  HMdcTrkCand* fTrkCandNew = (HMdcTrkCand*)fTrkCandCat->getNewSlot(locTrkCand,&index);
  if( fTrkCandNew == NULL ) {
    Warning("fillTrkCandISeg"," No slot available in catMdcTrkCand");
    fitter->setSegIndex(-1);
    return NULL;
  }
  Int_t sec = fitter->getWiresArr().getSector();
  if(indFirstSeg[sec] < 0) indFstTrCand[sec] = index;
  indLstTrCand[sec] = index;
  return new(fTrkCandNew) HMdcTrkCand(sec,fitter->getSegIndex(),index);
}
HMdcTrkCand* HMdc12Fit::fillTrkCandOSeg(HMdcTrkCand* fTrkCand) {
  if(fTrkCandCat==0 || fTrkCand==0) return 0;
  Int_t index;
  HMdcTrkCand* fTrkCandNew = (HMdcTrkCand*)fTrkCandCat->getNewSlot(locTrkCand,&index);
  if(!fTrkCandNew) {
    Warning("fillTrkCandOSeg"," No slot available in catMdcTrkCand");
    fitter->setSegIndex(-1);
    return NULL;
  }
  Int_t sec = fTrkCand->getSec();
  if(indFstTrCand[sec] < 0) indFstTrCand[sec] = index;
  indLstTrCand[sec] = index;
  return new(fTrkCandNew) HMdcTrkCand(fTrkCand,fitter->getSegIndex(),index);
}
Double_t HMdc12Fit::calcVertexDist( Double_t x0, Double_t y0, Double_t z0,
			      Double_t x1, Double_t y1, Double_t z1,
			      Double_t x2, Double_t y2, Double_t z2) {
  
  return sqrt( ((y2-y1)*(z1-z0) - (z2-z1)*(y1-y0))*((y2-y1)*(z1-z0) - (z2-z1)*(y1-y0)) +
	       ((z2-z1)*(x1-x0) - (x2-x1)*(z1-z0))*((z2-z1)*(x1-x0) - (x2-x1)*(z1-z0)) +
               ((x2-x1)*(y1-y0) - (y2-y1)*(x1-x0))*((x2-x1)*(y1-y0) - (y2-y1)*(x1-x0)) )/
    sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1) + (z2-z1)*(z2-z1));
}
void HMdc12Fit::setGroup(HMdcList24GroupCells* cells, HMdcSeg* fSeg, Int_t seg) {
  
  Int_t lc = seg*12;
  for(Int_t l=0; l<12; l++,lc++) fSeg->setLayerGroup(l,cells->getOneLayerGroup(lc));
  if(pTrackInfSim) {
    HMdcClus *pClus = fitter->getWiresArr().getClust1();
    Int_t indPar  = pClus->getIndexParent();
    HMdcSegSim *pSegPar = NULL;
    if(indPar>=0) {
      HMdcClus *pClus = (HMdcClus*)fClusCat->getObject(indPar);
      Int_t segIndex = pClus == NULL ? -1 : pClus->getSegIndex();
      if(segIndex >= 0) pSegPar = (HMdcSegSim*)fSegCat->getObject(segIndex);
    }
    pTrackInfSim->fillSegTrackInf((HMdcSegSim*)fSeg,cells,pSegPar);
  }
}
void HMdc12Fit::setGroup(HMdcList24GroupCells* cells, HMdcHit* fHit, Int_t mod) {
  
  Int_t lc = mod*6;
  for(Int_t l=0; l<6; l++,lc++) fHit->setLayerGroup(l,cells->getOneLayerGroup(lc));
  if(pTrackInfSim) pTrackInfSim->fillHitTrackInf((HMdcHitSim*)fHit,cells);
}
void HMdc12Fit::printStatusM(void) {
  
  const Char_t* hAuth  = "1 = Alexander, 2 = tuned ver. 1";
  const Char_t* hTmVer = "0 = polynomial,  1 = HMdcCal2ParSim::calcTime";
  const Char_t* hFType = "0 = segment fit,  1 = independent mdc fit";
  const Char_t* hDCat  = "1 = create and fill catMdcClusFit&catMdcWireFit 0 = don't cr.";
  const Char_t* hDPr   = "1 = print debug information, 0 = don't print";
  const Char_t* hUWOff = "1 = remove signal time on wire from drift time, 0 = don't remove";
  const Char_t* hCITrp = "1 = for all clusters, 2 = for not fitted+, 0 = don't calc. init tr.param.";
  printf("--------------------------------------------------------------------------------------------\n");
  printf("HMdc12FitSetup:\n");
  printf("CalcInitTrParam =  %i :  %s\n",HMdcTrackDSet::getCalcInitValueFlag(),hCITrp);
  if(HMdcTrackDSet::getCalcInitValueFlag() > 0) printf("  dDistCut Seg1 = %.2f  Seg2 = %.2f[mm]\n",
      HMdcTrackDSet::getCalcInitValueCut(0),HMdcTrackDSet::getCalcInitValueCut(1));
  printf("FitVersion      =  %i :  %s\n",HMdcTrackDSet::getFitAuthor(),hAuth);
  printf("DrTimeCalcVers  =  %i :  %s\n",HMdcTrackDSet::getFitVersion(),hTmVer);
  printf("FitType         =  %i :  %s\n",HMdcTrackDSet::getFitType(),hFType);
  printf("useWireOffset   =  %i :  %s\n",HMdcTrackDSet::getUseWireOffset(),hUWOff);
  printf("DebugCategorie  =  %i :  %s\n",HMdcTrackDSet::fNTuple(),hDCat);
  printf("DebugPrint      =  %i :  %s\n",HMdcTrackDSet::fPrint(),hDPr);
  printf("--------------------------------------------------------------------------------------------\n");
  prntSt = kTRUE;
}
Bool_t HMdc12Fit::finalize(void) {
  return kTRUE;
}
void HMdc12Fit::suppressFakes(Int_t sec,Int_t segIO) {
  if(indLastSeg[sec] <= indFirstSeg[sec]) return;
  currSeg = segIO;
  Int_t nShLayCut = nSharedLayersCut[currSeg];
  Int_t nLayOrCut = nLayerOrientCut[currSeg];
  Int_t nDCMinCut = nDCellsMinCut[currSeg];
  Int_t nDCCut    = nDCellsCut[currSeg];
  HMdcEvntListCells *pEvListCells = HMdcEvntListCells::getExObject();
  pSecListCells  = &((*pEvListCells)[sec]);
  indFirst       = indFirstSeg[sec];
  indLast        = indLastSeg[sec];
  indFirstTrCand = indFstTrCand[sec];
  indLastTrCand  = indLstTrCand[sec];
  for(Int_t is1=indFirst+1; is1<=indLast; is1++) {
    HMdcSeg* seg1 = (HMdcSeg*)fSegCat->getObject(is1);
    if(seg1->getIOSeg() != currSeg) continue;
    if(seg1->isFake()) continue;
    Short_t x1       = seg1->getX1Sh();
    Short_t y1       = seg1->getY1Sh();
    Short_t x2       = seg1->getX2Sh();
    Short_t y2       = seg1->getY2Sh();
    Int_t   nWires1  = seg1->getSumWires();
    Int_t   nLayers1 = seg1->getNLayers();
    Float_t chi2S1   = seg1->getChi2();
    for(Int_t is2 = indFirst; is2<is1; is2++) {
      HMdcSeg* seg2 = (HMdcSeg*)fSegCat->getObject(is2);
      if(seg2->getIOSeg() != currSeg) continue;
      if(seg2->isFake()) continue;
       if(TMath::Abs(x1 - seg2->getX1Sh())>400 || TMath::Abs(x2 - seg2->getX2Sh())>400 ) continue;
       if(TMath::Abs(y1 - seg2->getY1Sh())>150 || TMath::Abs(y2 - seg2->getY2Sh())>150 ) continue;
      Int_t nLayOr, nSharedLayers;
      Int_t nSharedCells = seg1->getNSharedCells(seg2,nSharedLayers,nLayOr);
      if(nSharedLayers<nShLayCut || nLayOr<nLayOrCut) continue;
      Int_t dCells1   = nWires1             - nSharedCells;
      Int_t dCells2   = seg2->getSumWires() - nSharedCells;
      Int_t dCellsMin = TMath::Min(dCells1,dCells2);
      if((dCellsMin<nSharedCells && dCellsMin<nDCMinCut) || dCells1+dCells2 < nDCCut) { 
        Float_t chi2S2   = seg2->getChi2();
        Int_t   nLayers2 = seg2->getNLayers();
        Int_t   prefer   = 0;
        if(chi2S2 < 0.) prefer  = 1;
        if(chi2S1 < 0.) prefer += 2;
        if(prefer == 3 || prefer == 0) { 
          if(nLayers1 != nLayers2) prefer = nLayers1 > nLayers2 ? 1:2;
          else if(prefer == 0)     prefer = chi2S1   < chi2S2   ? 1:2; 
          else                     prefer = dCells1  > dCells2  ? 1:2; 
        }
        if(prefer == 1) {
          if(isGeant) testGeantInf((HMdcSegSim*)seg2,(HMdcSegSim*)seg1); 
          if(currSeg == 1) setFakeFlageAndIndexis(seg2,is2,seg1,is1);
          setFake(seg2);
        } else {
          if(isGeant) testGeantInf((HMdcSegSim*)seg1,(HMdcSegSim*)seg2); 
          if(currSeg == 1) setFakeFlageAndIndexis(seg1,is1,seg2,is2);
          setFake(seg1);
        }      
        if(prefer == 2) break;
      }
    }
  }
  
  addToNFittedCounter();
  Int_t n1,n2;
  do {
    n1 = markReals(1);  
    n2 = markFakes(1);  
  } while( n1+n2 > 0);
  
  for(Int_t is=indFirst; is<=indLast; is++) {
    HMdcSeg* seg = (HMdcSeg*)fSegCat->getObject(is);
    if(seg->getIOSeg() == currSeg && seg->isFake() ) setFakeInd(is);
  }
}
void HMdc12Fit::setFake(HMdcSeg* segFake) {
  segFake->setFakeFlag();
  segFake->SetBit(kKeep);   
}
void HMdc12Fit::setFakeInd(Int_t index) {
  
  if(indFirstTrCand >= 0) for(Int_t itr=indFirstTrCand; itr<=indLastTrCand; itr++) {
    HMdcTrkCand* trkCand = (HMdcTrkCand*)fTrkCandCat->getObject(itr);
    if(currSeg == 0) {
      if(index == trkCand->getSeg1Ind()) trkCand->setFakeFlagSeg1();
    } else {
      if(index == trkCand->getSeg2Ind()) trkCand->setFakeFlagSeg2();
    }
  }
  
  if(fClusFitCat == NULL) fClusFitCat = HMdcGetContainers::getObject()->getCatMdcClusFit();
  if(fClusFitCat != NULL && clusFitAlg == 1) {
    
    HMdcClusFit *clFit = (HMdcClusFit*)fClusFitCat->getObject(index);
    if(clFit == NULL) Error("setFake","Pointer to the HMdcClusFit object = NULL!");
    else  clFit->setFakeFlag();
  }
}
void HMdc12Fit::testGeantInf(HMdcSegSim* segFake,HMdcSegSim* segGood) {
  if(segGood->isFake()) return;
  if(segFake->isFakeContribution(0)) return;
  Int_t trf = segFake->getTrack(0);
  if(trf<=0 || trf != segGood->getTrack(0)) return;
  if(segGood->getChi2() < 0.) return;
  Int_t nTmG = segGood->getNTimes(0);
  if(nTmG<5) return;
  Int_t nTmF = segFake->getNTimes(0);
  if(nTmF <= nTmG || ((nTmF>=8 || nTmF == nTmG+1) && segGood->getSumWires()-nTmG < nTmG-2)) {
    if(segGood->resetFakeContributionFlag()) segFake->setFakeContributionFlag();
  }
}
  
HMdcSeg* HMdc12Fit::getInnerSegment(Int_t clIndPar) const {
  HMdcClus *clusPar = clIndPar >= 0 ? (HMdcClus*)fClusCat->getObject(clIndPar) : NULL;
  if(clusPar == NULL) return NULL;           
  Int_t segIndPar = clusPar->getSegIndex();  
  return segIndPar >= 0 ? (HMdcSeg*)fSegCat->getObject(segIndPar) : NULL;
}
Int_t HMdc12Fit::getInnerClusInd(HMdcSeg* outerSegment,HMdcClus* &outerClus) const {
  Int_t clInd = outerSegment->getClusIndex();
  outerClus = clInd >= 0 ? (HMdcClus*)fClusCat->getObject(clInd) : NULL;
  if(outerClus == NULL) return -1;           
  return outerClus->getIndexParent();
}
void HMdc12Fit::setFakeFlageAndIndexis(HMdcSeg* segOFake,Int_t indFakeSeg,HMdcSeg* segOGood,Int_t indGoodSeg) {
  if( segOFake->isFake() ) return;
  HMdcClus *clusOFake = NULL;
  Int_t indClusIFake = getInnerClusInd(segOFake,clusOFake);
  HMdcClus *clusGood = NULL;
  Int_t indClusIGood = getInnerClusInd(segOGood,clusGood);
  if(indClusIFake == indClusIGood || indClusIFake<0 || indClusIGood<0) return;
  
  HMdcSeg  *segIFake  = getInnerSegment(indClusIFake);
  clusOFake->setSegIndex(indGoodSeg);  
  if(indFirstTrCand >= 0) for(Int_t itr=indFirstTrCand; itr<=indLastTrCand; itr++) {
    HMdcTrkCand* trkCand = (HMdcTrkCand*)fTrkCandCat->getObject(itr);
    if(indFakeSeg == trkCand->getSeg2Ind()) trkCand->setSeg2Ind(indGoodSeg);
  }
 
  if(segIFake->isFake() || segIFake->getChi2() < 0.) return;
  
  HMdcSeg  *segIGood = getInnerSegment(indClusIGood);
  
  
  if(segIGood->isFake() || segIGood->getChi2() < 0.) segOGood->setClusIndex(segOFake->getClusIndex());
  
}
void HMdc12Fit::addToNFittedCounter(void) { 
  for(Int_t ind=indFirst;ind<=indLast;ind++) {  
    HMdcSeg* pSeg = (HMdcSeg*)fSegCat->getObject(ind);
    if( pSeg->getIOSeg() != currSeg ) continue;
    if( pSeg->isFake() ) pSeg->SetBit(kKeep);  
    else if( pSeg->getChi2() >= 0. ) {
      if( pSeg->TestBit(kInFittedList) ) continue;
      pSeg->ResetBit(kRealKeep);
      pSecListCells->addToNFittedCounters(currSeg,pSeg);
      pSeg->SetBit(kInFittedList);
    }
  }
}
Float_t HMdc12Fit::calcWeight(HMdcSeg* pSeg, Float_t *cut) const {
  Int_t nWrTot   = 0;
  Int_t nWrForWt = 0;
  Int_t mod      = currSeg*2;
  Int_t cells[4];
  Int_t ns = pSeg->TestBit(kInFittedList) ? 1 : 0;
  for(Int_t layInd=0;layInd<12;layInd++) {
    if(layInd == 6) mod++;
    Int_t nCells = pSeg->getLayerListCells(layInd,cells);
    nWrTot += nCells;
    const HMdcLayListCells &layList = (*pSecListCells)[mod][layInd%6];
    for(Int_t i=0;i<nCells;i++) if(layList.getNFitted(cells[i]) > ns) {
      nWrForWt++;                                       
      if(layList.getNRFitted(cells[i]) > 0) nWrForWt++; 
    }
  }
  Int_t level = nWrTot-5;
  if     (level<0) level = 0;
  else if(level>7) level = 7; 
  return Float_t(nWrForWt)/Float_t(nWrTot)/cut[level];
}
Int_t HMdc12Fit::markFakes(Int_t cutNMarked) {
  
  Float_t *cut = cutForFake[currSeg];
  for(Int_t n=0;n<cutNMarked;n++) {
    Float_t  maxWt   = 0.;
    Int_t    nFkCand = 0;                      
    HMdcSeg* pSegMax = NULL;
    for(Int_t ind=indFirst;ind<=indLast;ind++) {  
      HMdcSeg* pSeg = (HMdcSeg*)fSegCat->getObject(ind);
      if( pSeg->getIOSeg() != currSeg ) continue;
      if( pSeg->TestBit(kAllTypes) )    continue;  
      Float_t wt = calcWeight(pSeg,cut);
      if( wt <= 1. ) continue;
      if( pSeg->getChi2() < 0.) pSeg->SetBit(kFake);
      else {
        nFkCand++;
        if(wt <= maxWt) continue;
        maxWt   = wt;
        pSegMax = pSeg;
      }
    }
    if(pSegMax != NULL) {
      if( pSegMax->TestBit(kReal) ) {
        pSecListCells->subFittedAndRealCounters(currSeg,pSegMax);
        pSegMax->ResetBit(kReal);
      } else pSecListCells->subFittedCounters(currSeg,pSegMax);
      pSegMax->ResetBit(kInFittedList);
      pSegMax->SetBit(kFake);
      if(nFkCand == 1) return n+1;             
    } else             return n;
  }
  return cutNMarked;
}
Int_t HMdc12Fit::markReals(Int_t cutNMarked) {
  
  Float_t *cut = cutForReal[currSeg];
  for(Int_t n=0;n<cutNMarked;n++) {
    Float_t  minWt   = 10.;
    Int_t    nRlCand = 0;                      
    HMdcSeg* pSegMin = NULL;
    for(Int_t ind=indFirst;ind<=indLast;ind++) {  
      HMdcSeg* pSeg = (HMdcSeg*)fSegCat->getObject(ind);
      if( pSeg->getIOSeg() != currSeg ) continue;
      if( pSeg->getChi2() < 0. )        continue;
      if( pSeg->TestBit(kRealKeep) )    continue;  
      Float_t wt = calcWeight(pSeg,cut);
      if(wt == 0.) {
        pSeg->SetBit(kKeep);
        continue;
      }
      if( wt >= 1. ) continue;
      nRlCand++;
      if(wt >= minWt) continue;
      minWt   = wt;
      pSegMin = pSeg;
    }
    if(pSegMin != NULL) {
      if( pSegMin->TestBit(kFake) ) {
        pSecListCells->addToFittedAndRealCounters(currSeg,pSegMin);
        pSegMin->SetBit(kInFittedList);
        pSegMin->ResetBit(kFake);
      } else pSecListCells->addToNRFittedCounters(currSeg,pSegMin);
      pSegMin->SetBit(kReal);
      if(nRlCand == 1) return n+1;             
    } else             return n;
  }
  return cutNMarked;
}