ROOT logo
using namespace std;
#include "hemcclusterf.h"
#include "hdebug.h"
#include "hades.h"
#include "hiterator.h"
#include "hruntimedb.h"
#include "hspectrometer.h"
#include "hemcdetector.h"
#include "hgeantemc.h"
#include "hevent.h"
#include "hcategory.h"
#include "hemccalsim.h"
#include "hemcclustersim.h"
#include "rpcdef.h"
#include "hrpcclustersim.h"
#include "hrpchitsim.h"
#include "hemcgeompar.h"
#include "hgeomtransform.h"
#include "hgeomcompositevolume.h"
#include "hgeomvolume.h"
#include "hgeomvector.h"
#include <iostream>

#include <iomanip>


//*-- Author   : V. Pechenov

//*-- Modified : R. Lalik (07.05.2018)


/////////////////////////////////////////////////////////////////////

//

//  HEmcClusterF combines neighboring time correlated cells to the cluster,

//  matches cells to RPC,

//  calculates cluster mean time (by corrected times)

//  In simulation the cluster is assigned to the track which has maximal energy deposit

//

//  Algorithm

//  "0": find cell which has maximal energy deposit (t0 is a time of this cell)

//  "1": test 8 neighboring cells and add time correlated cells to the cluster

//  "2": test cells neighboring to added ones in the previous step

//  "3": test cells neighboring to added ones in the previous step

//  ...

//

//  Time Correlation

//  Assumption: first cell fired by this particle has maximal energy deposit

//  dt0 = tc - V*dc    - t0

//  dt  = (tc - V*dc) - (tp - V*dp) ,

//  where

//   V = 0.30 ns/cell

//   cells "c" and "p" are neighboring cells

//   dc and dp  are distances to the cell which has maximal energy deposit (cell from step "0"), units are cells

//   tc and tp  are measured times in cells "c" and "p"

//  Cells accepted for the cluster must fulfill conditions

//    dtmin < dt0 < dtmax

//     &&

//    dtmin < dt < dtmax

//

//  Matching to RPC

//  Matching by theta, phi and time

//  Cluster is marked as matched with RPC if at least one cell in the steps "0" and "1" has a matching with RPC

//

/////////////////////////////////////////////////////////////////////


HEmcClusterF::HEmcClusterF(void) {
  initData();
}

HEmcClusterF::HEmcClusterF(const Text_t *name, const Text_t *title) : HReconstructor(name,title) {
  initData();
}

void HEmcClusterF::initData(void) {
  fLoc.set(2,0,0);
  fEmcCalCat      = NULL;
  fClusterCat     = NULL;
  // RPC matching parameters:

  dThetaSigOffset  = 0.1;   // (thetaEmc-thetaRpc)/sigmaDTheta+dThSigOffset

  dThetaScale      = 1.61;  // dTheta = dThetaSigOffset/dThetaScale

  dTimeOffset      = 0.03;  // [ns] (time1 - timeRpcN + dTimeOffset)/sigmaDTof;

  dTimeCut         = 3.;    // Nsigma cut for matchin in time

  dThdPhCut        = 3.6;   // Nsigma cut for matching in angles

  dTimeCutNS       = 0.;    // [ns] cut for the matchin in time if dTimeCutNS > 0 dTimeCut will not used

  // Cluster finder parameters:

  cellToCellSpeed  = 0.3;   // [ns/cell]

  distOffset       = 0.9;
  timeCutMin       = -0.6;
  timeCutMax       = +0.6;
  addEnergy        = 0.;
  energyCut        = 0.;
  for(Int_t s=0;s<6;s++) {
    for(Int_t c=0;c<emcMaxComponents;c++) emcCellsLab[s][c] = NULL;
  }
}

HEmcClusterF::~HEmcClusterF(void) {
}

Bool_t HEmcClusterF::init(void) {

  gHades->getRuntimeDb()->getContainer("EmcGeomPar");

  HEmcDetector* emc = (HEmcDetector*)(gHades->getSetup()->getDetector("Emc"));
  if (emc == NULL) {
    Error("HEmcClusterF::init()","No Emc Detector");
    return kFALSE;
  }

  HCategory* fGeantKineCat = gHades->getCurrentEvent()->getCategory(catGeantKine);
  if (fGeantKineCat) { isSimulation = kTRUE;  }
  else               { isSimulation = kFALSE; }

  fEmcCalCat = gHades->getCurrentEvent()->getCategory(catEmcCal);
  if (!fEmcCalCat) {
    Error("HEmcClusterF::init()","Cal EMC input missing");
    return kFALSE;
  }

  fRpcCat = gHades->getCurrentEvent()->getCategory(catRpcCluster);
  if (!fRpcCat) {
    Warning("HEmcClusterF::init()","Cluster RPC input missing");
    return kFALSE;
  }

  //Build the Cluster category

  fClusterCat = gHades->getCurrentEvent()->getCategory(catEmcCluster);
  if (!fClusterCat) {
    if(isSimulation) { fClusterCat = emc->buildMatrixCategory("HEmcClusterSim",0.5); }
    else             { fClusterCat = emc->buildMatrixCategory("HEmcCluster",0.5); }
    gHades->getCurrentEvent()->addCategory(catEmcCluster,fClusterCat,"Emc");
    fClusterCat->setPersistency(kTRUE);
  }

  return kTRUE;
}

Bool_t HEmcClusterF::reinit(void) {
  sigmaXYmod  = 92./TMath::Sqrt(12.);             // 92.mm - size of cell (module)

  HEmcGeomPar *emcGeomPar  = (HEmcGeomPar*)(gHades->getRuntimeDb()->getContainer("EmcGeomPar"));
  HGeomTransform labTrans[6];
  for(Int_t s=0;s<6;s++) {
    HModGeomPar* fmodgeom = emcGeomPar->getModule(s);
    labTrans[s] = fmodgeom->getLabTransform();
    HGeomCompositeVolume* fMod    = fmodgeom->getRefVolume();
    for(Int_t c=0;c<emcMaxComponents;c++) {
      HGeomVolume* fVol=fMod->getComponent(c);
      if(fVol == NULL || fVol->getNumPoints() != 8) {
        thetaEmcLab[s][c] = 0.;
        phiEmcLab[s][c]   = 0.;
        sigmaTheta[s][c]  = 0.;
        sigmaPhi[s][c]    = 0.;
        if(emcCellsLab[s][c] != NULL) delete emcCellsLab[s][c];
        emcCellsLab[s][c] = NULL;
        continue;
      }
      if(emcCellsLab[s][c] == NULL) emcCellsLab[s][c] = new HGeomVector;
      HGeomVector* p    = emcCellsLab[s][c];
      *p = fVol->getTransform().getTransVector();
      cellXmod[c] = p->getX();
      cellYmod[c] = p->getY();
      *p = labTrans[s].transFrom(*p);

      // Calc. theta and phi of module(cell)

      Double_t xy2      =  p->getX()*p->getX() + p->getY()*p->getY();
      Double_t xyz2     = xy2 + p->getZ()*p->getZ();
      thetaEmcLab[s][c] = TMath::ATan2(TMath::Sqrt(xy2),p->getZ())*TMath::RadToDeg();
      phiEmcLab[s][c]   = TMath::ATan2(p->getY(),p->getX())*TMath::RadToDeg();
      if(phiEmcLab[s][c] < 0.) phiEmcLab[s][c] += 360.;

      // Calc. errors of theta and phi

      sigmaTheta[s][c]    = p->getZ()/xyz2 * sigmaXYmod * TMath::RadToDeg();
      sigmaPhi[s][c]      = 1./TMath::Sqrt(xy2) * sigmaXYmod * TMath::RadToDeg();
    }
  }
  return kTRUE;
}

Int_t HEmcClusterF::execute(void) {
  Int_t nEmcCal = fEmcCalCat->getEntries();
  for(Int_t sec=0;sec<6;sec++) {
    HEmcCalSim * calsim = 0;
    memset(flagUsed,-1,emcMaxComponents);

    // Collect HEmcCal in one sector

    for(Int_t e=0; e<nEmcCal; e++) {
      HEmcCal* cal = (HEmcCal*)fEmcCalCat->getObject(e);
      if(sec != cal->getSector()) continue;
      // Test status:

      if(cal->getStatus() < 0) continue;              // Energy < energyCut for sim.data

      Float_t ener = cal->getEnergy() + addEnergy;
      if(ener <= energyCut) continue;

      Int_t cell       = cal->getCell();
      energy[cell]     = ener;
      pSecECells[cell] = cal;
      flagUsed[cell]   = 0;
    }

    //========  Cluster finder: ========================

    while(kTRUE) {
      Int_t   cell  = maxEnergyCell();
      if(cell < 0) break;  // all fired cells was used already

      
      //========  New cluster:  ========================

      HEmcCal     *cal  = pSecECells[cell];
      calsim = dynamic_cast<HEmcCalSim*>(cal);
      
      HGeomVector *pemc = emcCellsLab[sec][cell];
      HGeomVector pos(pemc->getX(),pemc->getY(),pemc->getZ());
      pos                *= energy[cell];
      Float_t posNorm     = energy[cell];
      Float_t xPos        = cellXmod[cell]*energy[cell];
      Float_t yPos        = cellYmod[cell]*energy[cell];
      Float_t errXYPos    = energy[cell]*energy[cell];
      Float_t time0       = cal->getTime();
      Float_t clustEnergy = energy[cell];
      Float_t clustEnErr  = calsim==NULL ? 0. : TMath::Power(calsim->getSigmaEnergy(),2);
      Float_t timeSum     = time0*energy[cell];
      Float_t timeError   = calsim==NULL ? 0. : TMath::Power(calsim->getSigmaTime()*energy[cell],2);
      
      Float_t qualityDThDPh,qualityDTime;
      HRpcCluster* pRpcClusF = rpcMatch(cal,qualityDThDPh,qualityDTime);
      Int_t nMatchedCells = pRpcClusF==NULL ? 0 : 1;

      listClustCell[0]    = cell;
      pClustCells[0]      = cal;
      flagUsed[cell]      = 1;
      Int_t   size        = 1;
      Int_t   ind         = 0;

      while(ind<size) {
        Int_t   cind   = listClustCell[ind];
        Float_t distN  = ind==0 ? 0. : calcDist(cal,pClustCells[ind]);  // dist. max.ener.cell->curr.cell

        Float_t tCorrN = pClustCells[ind]->getTime();
        if(ind > 0) tCorrN -= cellToCellSpeed*(distN - distOffset);
        
        // Test nearby cells: -------------------------------------

        for(Int_t i=0;i<8;i++) {
          Int_t celli = getNearbyCell(cind,i);
          if(celli < 0) continue;
          if( flagUsed[celli] != 0 ) continue;  // skip cells wich were used already

          HEmcCal *cali =  pSecECells[celli];
          if(cali == NULL) continue;

          Float_t dist0   = calcDist(cal,cali);             // dist. max.ener.cell->curr.cell

          Float_t tCorrI  = cali->getTime() - cellToCellSpeed*(dist0 - distOffset);
          Float_t dT0corr = tCorrI - time0;
          if(dT0corr < timeCutMin || dT0corr > timeCutMax) continue;  // 0.6

          if(ind > 0) {
            Float_t dTcorr = tCorrI - tCorrN;
            if(dTcorr  < timeCutMin || dTcorr  > timeCutMax) continue;
          }
          //======== Add to cluster ========================

          
          if(isSimulation) {
            HEmcCalSim *calsim = dynamic_cast<HEmcCalSim*>(cali);
            clustEnErr += calsim->getSigmaEnergy()*calsim->getSigmaEnergy();
            timeError  += TMath::Power(calsim->getSigmaTime()*energy[celli],2);
          }
          if(dist0<1.9) {   // Use cells nearby to max.ener.cell only

            HGeomVector *pemc = emcCellsLab[sec][celli];
            HGeomVector vc(pemc->getX(),pemc->getY(),pemc->getZ());
            vc       *= energy[celli];
            pos      += vc;
            posNorm  += energy[celli];
            xPos     += cellXmod[celli]*energy[celli];
            yPos     += cellYmod[celli]*energy[celli];
            errXYPos += energy[celli]*energy[celli];
          }
          timeSum            += tCorrI*energy[celli];
          clustEnergy        += energy[celli];
          flagUsed[celli]     = 1;
          listClustCell[size] = celli;
          pClustCells[size]   = cali;
          
          // Test RPC matching ---------------------------- 

          Float_t qualityDThDPhI,qualityDTimeI;
          HRpcCluster* pRpcClus = rpcMatch(cali,qualityDThDPhI,qualityDTimeI);
          if(pRpcClus != NULL) {
            if(pRpcClus == pRpcClusF) nMatchedCells++;
            else if(dist0 < 1.9) {
              nMatchedCells++;
              if(pRpcClusF == NULL) {
                pRpcClusF     = pRpcClus;
                qualityDThDPh = qualityDThDPhI;
                qualityDTime  = qualityDTimeI;
              }
            }
          }
          //-----------------------------------------------

          size++;
        }
        ind++;
      } //cluter end



      timeSum  /= clustEnergy;
      timeError = TMath::Sqrt(timeError)/clustEnergy;
      xPos     /= posNorm;
      yPos     /= posNorm;
      pos      /= posNorm;
      errXYPos = sigmaXYmod*TMath::Sqrt(errXYPos)/posNorm;

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

      // end of cluster

      fLoc[0] = sec;
      fLoc[1] = cell;
      Int_t clustIndex;
      HEmcCluster* pCluster = (HEmcCluster*)fClusterCat->getSlot(fLoc,&clustIndex);
      if(pCluster == NULL) {
        Warning("execute","S.%i No HEmcCluster slot available",sec+1);
        return 1;
      }

      for(Int_t s=0;s<size;s++) pClustCells[s]->setClusterIndex(clustIndex);
      pCluster = isSimulation ? (HEmcCluster*)(new(pCluster) HEmcClusterSim) : new(pCluster) HEmcCluster;
      pCluster->setSector(sec);
      pCluster->setCellList(size,listClustCell);
      pCluster->setIndex(clustIndex);
      pCluster->setMaxEnergy(energy[cell]);
      pCluster->setTime(timeSum);
      pCluster->setEnergy(clustEnergy);
      HEmcClusterSim * clsim = dynamic_cast<HEmcClusterSim*>(pCluster);
      if (clsim)
      {
        clsim->setSigmaEnergy(TMath::Sqrt(clustEnErr));
        clsim->setSigmaTime(timeError);
      }
      pCluster->setXYMod(xPos,yPos);
      pCluster->setSigmaXYMod(errXYPos);
      pCluster->setXYZLab(pos.getX(),pos.getY(),pos.getZ());
      Double_t xy    =  TMath::Sqrt(pos.getX()*pos.getX() + pos.getY()*pos.getY());
      Double_t theta = TMath::ATan2(xy,pos.getZ())*TMath::RadToDeg();
      Double_t phi   = TMath::ATan2(pos.getY(),pos.getX())*TMath::RadToDeg();
      if(phi < 0.) phi += 360.;
      pCluster->setTheta(theta);
      pCluster->setPhi(phi);
      pCluster->setCellList(size,listClustCell);
      if(pRpcClusF != NULL) {
        pCluster->setRpcIndex(pRpcClusF->getIndex());
        pCluster->setQualDThDPh(qualityDThDPh);
        pCluster->setQualDTime(qualityDTime);
        pCluster->setNMatchedCells(nMatchedCells);
      }

      if(isSimulation) { // For sim output:

        HEmcClusterSim* pClusterSim = (HEmcClusterSim*)pCluster;
        map<Int_t,Float_t>clTrackEnergy;  // For simulation only

        for(Int_t ind=0;ind<size;ind++) {
          HEmcCalSim* cal = (HEmcCalSim*)pClustCells[ind];
          Int_t ntr = cal->getNTracks();
          if(ntr < 1) continue; // Real track iEmbedded track

          for(Int_t i=0;i<ntr;i++) {
            Int_t track           = cal->getTrack(i);
            clTrackEnergy[track] += cal->getTrackEnergy(i); //ener;

          }
        }

        // Sort tracks by enegy deposit

        vector<pair<Int_t,Float_t> > vEn(clTrackEnergy.begin(),clTrackEnergy.end());
        if(vEn.size() > 1) sort(vEn.begin(),vEn.end(),cmpEnergy);
        for(UInt_t i = 0; i < vEn.size(); i++) pClusterSim->setTrack(vEn[i].first,vEn[i].second);
        if(pRpcClusF != NULL) pClusterSim->setRpcTrack(((HRpcClusterSim*)pRpcClusF)->getTrack());
      }
    }
  }
  return 0;
}

HRpcCluster* HEmcClusterF::rpcMatch(HEmcCal* cal,Float_t &qualityDThDPh,Float_t &qualityDTime) {

  Int_t        sec     = cal->getSector();
  Int_t        cell    = cal->getCell();
  Float_t      time    = cal->getTime();
  Float_t      thEmc   = thetaEmcLab[sec][cell];
  Float_t      phEmc   = phiEmcLab[sec][cell];
  Float_t      sigmaTh = sigmaTheta[sec][cell];
  Float_t      sigmaPh = sigmaPhi[sec][cell];
  HEmcCalSim  *calsim  = dynamic_cast<HEmcCalSim*>(cal);
  Float_t      sigmaTm = calsim==NULL ? 0.0 : calsim->getSigmaTime();  // For the real data is not implemented yet

  HGeomVector *pemc    = emcCellsLab[sec][cell];
  HRpcCluster *out     = NULL;
  qualityDThDPh        = 1000000.;
  qualityDTime         = 1000000.;

  Int_t   nRpc = fRpcCat->getEntries();
  for(Int_t n=0;n<nRpc;n++) {
    HRpcCluster* rpc = (HRpcCluster*)fRpcCat->getObject(n);
    if(rpc->getSector() != sec) continue;

    // Propagate track to the EMC and calculate TOF (timeRpc) to the EMC module

    Float_t xrl,yrl,zrl;
    rpc->getXYZLab(xrl,yrl,zrl);
    Float_t deltaX     = pemc->getX()-xrl;
    Float_t deltaY     = pemc->getY()-yrl;
    Float_t deltaZ     = pemc->getZ()-zrl;
    Float_t distRpcEmc = TMath::Sqrt(deltaX*deltaX+deltaY*deltaY+deltaZ*deltaZ);
    Float_t timeCorr   = distRpcEmc/TMath::Sqrt(xrl*xrl+yrl*yrl+zrl*zrl) * rpc->getTof();
    Float_t timeRpc    = rpc->getTof() + timeCorr;

    // Calculate quality of matching for angles (dThdPh)

    Float_t dThSig = ((thEmc -rpc->getTheta())/sigmaTh + dThetaSigOffset)/dThetaScale;
    Float_t dPhSig = (phEmc - rpc->getPhi())/sigmaPh;
    Float_t dThdPh = TMath::Sqrt(dThSig*dThSig + dPhSig*dPhSig);  // O-shaped cut

    
    if(dThdPh > dThdPhCut) continue;

    Float_t dTOFc  = time - timeRpc + dTimeOffset;
    if(dTimeCutNS > 0.) {                                        // Cut in time by time difference

      if(TMath::Abs(dTOFc) > dTimeCutNS) continue;               // Test matching

    } else {
      // Calculate quality of matching for time (dTOFc)

      Float_t sigTof = rpc->getTOFRMS();
      dTOFc /= TMath::Sqrt(sigmaTm*sigmaTm + sigTof*sigTof);
      if(TMath::Abs(dTOFc) > dTimeCut) continue;                // Test matching

    }

    // Select best matching by smallest value of dTOFc

    if(TMath::Abs(dTOFc) < TMath::Abs(qualityDTime)) {
      qualityDThDPh = dThdPh;
      qualityDTime  = dTOFc;
      out           = rpc;
    }

  }
  if(out != NULL) cal->setMatchedRpc();
  return out;
}

Int_t HEmcClusterF::maxEnergyCell(void) const {
  // Find cell with max.energy deposit

  Int_t   cellMax   = -1;
  for(Int_t cell=0; cell<emcMaxComponents; cell++) {
    if(flagUsed[cell] == 0) {
      if(cellMax<0 || energy[cell] > energy[cellMax]) cellMax = cell;
    }
  }
  return cellMax;
}

Float_t HEmcClusterF::calcDist(HEmcCal *cal1,HEmcCal *cal2) const {
  Float_t dCol = cal1->getColumn() - cal2->getColumn();
  Float_t dRow = cal1->getRow()    - cal2->getRow();
  return TMath::Sqrt(dCol*dCol+dRow*dRow);
}

Int_t HEmcClusterF::getNearbyCell(Int_t cell,Int_t i) const {
  Char_t dColumn[8] = {-1,+1,  0, 0, -1,-1, +1,+1};
  Char_t dRow[8]    = { 0, 0, -1,+1, -1,+1, -1,+1};
  Int_t row    = cell/emcMaxColumns + dRow[i];
  if(row<0    || row>=emcMaxRows)       return -1;
  Int_t column = cell%emcMaxColumns + dColumn[i];
  if(column<0 || column>=emcMaxColumns) return -1;
  return row*emcMaxColumns + column;
}

ClassImp(HEmcClusterF)
 hemcclusterf.cc:1
 hemcclusterf.cc:2
 hemcclusterf.cc:3
 hemcclusterf.cc:4
 hemcclusterf.cc:5
 hemcclusterf.cc:6
 hemcclusterf.cc:7
 hemcclusterf.cc:8
 hemcclusterf.cc:9
 hemcclusterf.cc:10
 hemcclusterf.cc:11
 hemcclusterf.cc:12
 hemcclusterf.cc:13
 hemcclusterf.cc:14
 hemcclusterf.cc:15
 hemcclusterf.cc:16
 hemcclusterf.cc:17
 hemcclusterf.cc:18
 hemcclusterf.cc:19
 hemcclusterf.cc:20
 hemcclusterf.cc:21
 hemcclusterf.cc:22
 hemcclusterf.cc:23
 hemcclusterf.cc:24
 hemcclusterf.cc:25
 hemcclusterf.cc:26
 hemcclusterf.cc:27
 hemcclusterf.cc:28
 hemcclusterf.cc:29
 hemcclusterf.cc:30
 hemcclusterf.cc:31
 hemcclusterf.cc:32
 hemcclusterf.cc:33
 hemcclusterf.cc:34
 hemcclusterf.cc:35
 hemcclusterf.cc:36
 hemcclusterf.cc:37
 hemcclusterf.cc:38
 hemcclusterf.cc:39
 hemcclusterf.cc:40
 hemcclusterf.cc:41
 hemcclusterf.cc:42
 hemcclusterf.cc:43
 hemcclusterf.cc:44
 hemcclusterf.cc:45
 hemcclusterf.cc:46
 hemcclusterf.cc:47
 hemcclusterf.cc:48
 hemcclusterf.cc:49
 hemcclusterf.cc:50
 hemcclusterf.cc:51
 hemcclusterf.cc:52
 hemcclusterf.cc:53
 hemcclusterf.cc:54
 hemcclusterf.cc:55
 hemcclusterf.cc:56
 hemcclusterf.cc:57
 hemcclusterf.cc:58
 hemcclusterf.cc:59
 hemcclusterf.cc:60
 hemcclusterf.cc:61
 hemcclusterf.cc:62
 hemcclusterf.cc:63
 hemcclusterf.cc:64
 hemcclusterf.cc:65
 hemcclusterf.cc:66
 hemcclusterf.cc:67
 hemcclusterf.cc:68
 hemcclusterf.cc:69
 hemcclusterf.cc:70
 hemcclusterf.cc:71
 hemcclusterf.cc:72
 hemcclusterf.cc:73
 hemcclusterf.cc:74
 hemcclusterf.cc:75
 hemcclusterf.cc:76
 hemcclusterf.cc:77
 hemcclusterf.cc:78
 hemcclusterf.cc:79
 hemcclusterf.cc:80
 hemcclusterf.cc:81
 hemcclusterf.cc:82
 hemcclusterf.cc:83
 hemcclusterf.cc:84
 hemcclusterf.cc:85
 hemcclusterf.cc:86
 hemcclusterf.cc:87
 hemcclusterf.cc:88
 hemcclusterf.cc:89
 hemcclusterf.cc:90
 hemcclusterf.cc:91
 hemcclusterf.cc:92
 hemcclusterf.cc:93
 hemcclusterf.cc:94
 hemcclusterf.cc:95
 hemcclusterf.cc:96
 hemcclusterf.cc:97
 hemcclusterf.cc:98
 hemcclusterf.cc:99
 hemcclusterf.cc:100
 hemcclusterf.cc:101
 hemcclusterf.cc:102
 hemcclusterf.cc:103
 hemcclusterf.cc:104
 hemcclusterf.cc:105
 hemcclusterf.cc:106
 hemcclusterf.cc:107
 hemcclusterf.cc:108
 hemcclusterf.cc:109
 hemcclusterf.cc:110
 hemcclusterf.cc:111
 hemcclusterf.cc:112
 hemcclusterf.cc:113
 hemcclusterf.cc:114
 hemcclusterf.cc:115
 hemcclusterf.cc:116
 hemcclusterf.cc:117
 hemcclusterf.cc:118
 hemcclusterf.cc:119
 hemcclusterf.cc:120
 hemcclusterf.cc:121
 hemcclusterf.cc:122
 hemcclusterf.cc:123
 hemcclusterf.cc:124
 hemcclusterf.cc:125
 hemcclusterf.cc:126
 hemcclusterf.cc:127
 hemcclusterf.cc:128
 hemcclusterf.cc:129
 hemcclusterf.cc:130
 hemcclusterf.cc:131
 hemcclusterf.cc:132
 hemcclusterf.cc:133
 hemcclusterf.cc:134
 hemcclusterf.cc:135
 hemcclusterf.cc:136
 hemcclusterf.cc:137
 hemcclusterf.cc:138
 hemcclusterf.cc:139
 hemcclusterf.cc:140
 hemcclusterf.cc:141
 hemcclusterf.cc:142
 hemcclusterf.cc:143
 hemcclusterf.cc:144
 hemcclusterf.cc:145
 hemcclusterf.cc:146
 hemcclusterf.cc:147
 hemcclusterf.cc:148
 hemcclusterf.cc:149
 hemcclusterf.cc:150
 hemcclusterf.cc:151
 hemcclusterf.cc:152
 hemcclusterf.cc:153
 hemcclusterf.cc:154
 hemcclusterf.cc:155
 hemcclusterf.cc:156
 hemcclusterf.cc:157
 hemcclusterf.cc:158
 hemcclusterf.cc:159
 hemcclusterf.cc:160
 hemcclusterf.cc:161
 hemcclusterf.cc:162
 hemcclusterf.cc:163
 hemcclusterf.cc:164
 hemcclusterf.cc:165
 hemcclusterf.cc:166
 hemcclusterf.cc:167
 hemcclusterf.cc:168
 hemcclusterf.cc:169
 hemcclusterf.cc:170
 hemcclusterf.cc:171
 hemcclusterf.cc:172
 hemcclusterf.cc:173
 hemcclusterf.cc:174
 hemcclusterf.cc:175
 hemcclusterf.cc:176
 hemcclusterf.cc:177
 hemcclusterf.cc:178
 hemcclusterf.cc:179
 hemcclusterf.cc:180
 hemcclusterf.cc:181
 hemcclusterf.cc:182
 hemcclusterf.cc:183
 hemcclusterf.cc:184
 hemcclusterf.cc:185
 hemcclusterf.cc:186
 hemcclusterf.cc:187
 hemcclusterf.cc:188
 hemcclusterf.cc:189
 hemcclusterf.cc:190
 hemcclusterf.cc:191
 hemcclusterf.cc:192
 hemcclusterf.cc:193
 hemcclusterf.cc:194
 hemcclusterf.cc:195
 hemcclusterf.cc:196
 hemcclusterf.cc:197
 hemcclusterf.cc:198
 hemcclusterf.cc:199
 hemcclusterf.cc:200
 hemcclusterf.cc:201
 hemcclusterf.cc:202
 hemcclusterf.cc:203
 hemcclusterf.cc:204
 hemcclusterf.cc:205
 hemcclusterf.cc:206
 hemcclusterf.cc:207
 hemcclusterf.cc:208
 hemcclusterf.cc:209
 hemcclusterf.cc:210
 hemcclusterf.cc:211
 hemcclusterf.cc:212
 hemcclusterf.cc:213
 hemcclusterf.cc:214
 hemcclusterf.cc:215
 hemcclusterf.cc:216
 hemcclusterf.cc:217
 hemcclusterf.cc:218
 hemcclusterf.cc:219
 hemcclusterf.cc:220
 hemcclusterf.cc:221
 hemcclusterf.cc:222
 hemcclusterf.cc:223
 hemcclusterf.cc:224
 hemcclusterf.cc:225
 hemcclusterf.cc:226
 hemcclusterf.cc:227
 hemcclusterf.cc:228
 hemcclusterf.cc:229
 hemcclusterf.cc:230
 hemcclusterf.cc:231
 hemcclusterf.cc:232
 hemcclusterf.cc:233
 hemcclusterf.cc:234
 hemcclusterf.cc:235
 hemcclusterf.cc:236
 hemcclusterf.cc:237
 hemcclusterf.cc:238
 hemcclusterf.cc:239
 hemcclusterf.cc:240
 hemcclusterf.cc:241
 hemcclusterf.cc:242
 hemcclusterf.cc:243
 hemcclusterf.cc:244
 hemcclusterf.cc:245
 hemcclusterf.cc:246
 hemcclusterf.cc:247
 hemcclusterf.cc:248
 hemcclusterf.cc:249
 hemcclusterf.cc:250
 hemcclusterf.cc:251
 hemcclusterf.cc:252
 hemcclusterf.cc:253
 hemcclusterf.cc:254
 hemcclusterf.cc:255
 hemcclusterf.cc:256
 hemcclusterf.cc:257
 hemcclusterf.cc:258
 hemcclusterf.cc:259
 hemcclusterf.cc:260
 hemcclusterf.cc:261
 hemcclusterf.cc:262
 hemcclusterf.cc:263
 hemcclusterf.cc:264
 hemcclusterf.cc:265
 hemcclusterf.cc:266
 hemcclusterf.cc:267
 hemcclusterf.cc:268
 hemcclusterf.cc:269
 hemcclusterf.cc:270
 hemcclusterf.cc:271
 hemcclusterf.cc:272
 hemcclusterf.cc:273
 hemcclusterf.cc:274
 hemcclusterf.cc:275
 hemcclusterf.cc:276
 hemcclusterf.cc:277
 hemcclusterf.cc:278
 hemcclusterf.cc:279
 hemcclusterf.cc:280
 hemcclusterf.cc:281
 hemcclusterf.cc:282
 hemcclusterf.cc:283
 hemcclusterf.cc:284
 hemcclusterf.cc:285
 hemcclusterf.cc:286
 hemcclusterf.cc:287
 hemcclusterf.cc:288
 hemcclusterf.cc:289
 hemcclusterf.cc:290
 hemcclusterf.cc:291
 hemcclusterf.cc:292
 hemcclusterf.cc:293
 hemcclusterf.cc:294
 hemcclusterf.cc:295
 hemcclusterf.cc:296
 hemcclusterf.cc:297
 hemcclusterf.cc:298
 hemcclusterf.cc:299
 hemcclusterf.cc:300
 hemcclusterf.cc:301
 hemcclusterf.cc:302
 hemcclusterf.cc:303
 hemcclusterf.cc:304
 hemcclusterf.cc:305
 hemcclusterf.cc:306
 hemcclusterf.cc:307
 hemcclusterf.cc:308
 hemcclusterf.cc:309
 hemcclusterf.cc:310
 hemcclusterf.cc:311
 hemcclusterf.cc:312
 hemcclusterf.cc:313
 hemcclusterf.cc:314
 hemcclusterf.cc:315
 hemcclusterf.cc:316
 hemcclusterf.cc:317
 hemcclusterf.cc:318
 hemcclusterf.cc:319
 hemcclusterf.cc:320
 hemcclusterf.cc:321
 hemcclusterf.cc:322
 hemcclusterf.cc:323
 hemcclusterf.cc:324
 hemcclusterf.cc:325
 hemcclusterf.cc:326
 hemcclusterf.cc:327
 hemcclusterf.cc:328
 hemcclusterf.cc:329
 hemcclusterf.cc:330
 hemcclusterf.cc:331
 hemcclusterf.cc:332
 hemcclusterf.cc:333
 hemcclusterf.cc:334
 hemcclusterf.cc:335
 hemcclusterf.cc:336
 hemcclusterf.cc:337
 hemcclusterf.cc:338
 hemcclusterf.cc:339
 hemcclusterf.cc:340
 hemcclusterf.cc:341
 hemcclusterf.cc:342
 hemcclusterf.cc:343
 hemcclusterf.cc:344
 hemcclusterf.cc:345
 hemcclusterf.cc:346
 hemcclusterf.cc:347
 hemcclusterf.cc:348
 hemcclusterf.cc:349
 hemcclusterf.cc:350
 hemcclusterf.cc:351
 hemcclusterf.cc:352
 hemcclusterf.cc:353
 hemcclusterf.cc:354
 hemcclusterf.cc:355
 hemcclusterf.cc:356
 hemcclusterf.cc:357
 hemcclusterf.cc:358
 hemcclusterf.cc:359
 hemcclusterf.cc:360
 hemcclusterf.cc:361
 hemcclusterf.cc:362
 hemcclusterf.cc:363
 hemcclusterf.cc:364
 hemcclusterf.cc:365
 hemcclusterf.cc:366
 hemcclusterf.cc:367
 hemcclusterf.cc:368
 hemcclusterf.cc:369
 hemcclusterf.cc:370
 hemcclusterf.cc:371
 hemcclusterf.cc:372
 hemcclusterf.cc:373
 hemcclusterf.cc:374
 hemcclusterf.cc:375
 hemcclusterf.cc:376
 hemcclusterf.cc:377
 hemcclusterf.cc:378
 hemcclusterf.cc:379
 hemcclusterf.cc:380
 hemcclusterf.cc:381
 hemcclusterf.cc:382
 hemcclusterf.cc:383
 hemcclusterf.cc:384
 hemcclusterf.cc:385
 hemcclusterf.cc:386
 hemcclusterf.cc:387
 hemcclusterf.cc:388
 hemcclusterf.cc:389
 hemcclusterf.cc:390
 hemcclusterf.cc:391
 hemcclusterf.cc:392
 hemcclusterf.cc:393
 hemcclusterf.cc:394
 hemcclusterf.cc:395
 hemcclusterf.cc:396
 hemcclusterf.cc:397
 hemcclusterf.cc:398
 hemcclusterf.cc:399
 hemcclusterf.cc:400
 hemcclusterf.cc:401
 hemcclusterf.cc:402
 hemcclusterf.cc:403
 hemcclusterf.cc:404
 hemcclusterf.cc:405
 hemcclusterf.cc:406
 hemcclusterf.cc:407
 hemcclusterf.cc:408
 hemcclusterf.cc:409
 hemcclusterf.cc:410
 hemcclusterf.cc:411
 hemcclusterf.cc:412
 hemcclusterf.cc:413
 hemcclusterf.cc:414
 hemcclusterf.cc:415
 hemcclusterf.cc:416
 hemcclusterf.cc:417
 hemcclusterf.cc:418
 hemcclusterf.cc:419
 hemcclusterf.cc:420
 hemcclusterf.cc:421
 hemcclusterf.cc:422
 hemcclusterf.cc:423
 hemcclusterf.cc:424
 hemcclusterf.cc:425
 hemcclusterf.cc:426
 hemcclusterf.cc:427
 hemcclusterf.cc:428
 hemcclusterf.cc:429
 hemcclusterf.cc:430
 hemcclusterf.cc:431
 hemcclusterf.cc:432
 hemcclusterf.cc:433
 hemcclusterf.cc:434
 hemcclusterf.cc:435
 hemcclusterf.cc:436
 hemcclusterf.cc:437
 hemcclusterf.cc:438
 hemcclusterf.cc:439
 hemcclusterf.cc:440
 hemcclusterf.cc:441
 hemcclusterf.cc:442
 hemcclusterf.cc:443
 hemcclusterf.cc:444
 hemcclusterf.cc:445
 hemcclusterf.cc:446
 hemcclusterf.cc:447
 hemcclusterf.cc:448
 hemcclusterf.cc:449
 hemcclusterf.cc:450
 hemcclusterf.cc:451
 hemcclusterf.cc:452
 hemcclusterf.cc:453
 hemcclusterf.cc:454