/////////////////////////////////////////////////////////////////////////////
//
// EEezCluster
// 
// Author: Jason C. Webb <jwebb@iucf.indiana.edu>
//
// Storage class for clusters.  Inherits from EEezTower.  Will have a 
// method to build clusters from a specified seed tower.  Is meant to
// be a persistent object... i.e. an array of 720 m_Clusters sitting
// within the cluster maker.  Neighboring clusters can be easily associated
// with this cluster by storing pointers (much like was done for the towers).
//
/////////////////////////////////////////////////////////////////////////////

#include "EEezCluster.h"

#include "StEEmcUtil/EEmcGeom/EEmcGeomSimple.h"
#include "StEEmcUtil/StEEmcSmd/EEmcSmdGeom.h"

#define DEBUG 0

/////////////////////////////////////////////////////////////////////////////
ClassImp(EEezCluster);

 EEezCluster::EEezCluster() 
{
  // Class initialization.
  
  m_EETowGeom = new EEmcGeomSimple();
  m_EESmdGeom = EEmcSmdGeom::instance();
  m_EnergyCut = 0.;

  for ( Int_t i = 0; i < 2; i++ ) {
    m_UFirst[i] = 0;
    m_VFirst[i] = 0;
    m_ULast[i]  = 0;
    m_VLast[i]  = 0;
  }

}

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

 Int_t EEezCluster::hasTower ( EEezTower *tower ) 
{
  // Returns true if the tower has been associated with this cluster
  // NOTE: should add a pointer to EEezTower to hold all clusters 
  // which it has been associated with.
  

  Int_t dEta = tower -> getEtabin() - m_SeedTower -> getEtabin();
  Int_t dPhi = tower -> getPhibin() - m_SeedTower -> getPhibin();

  Int_t ret =
    ( (dEta*dEta)<=1 ) &&
    ( (dPhi*dPhi)<=1 ) &&
    tower -> getEnergy() > m_EnergyCut;

  return ret;

}

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

 void EEezCluster::buildCluster( EEezTower *seed ) 
{ 
  // Performs clustering of the specified seed tower.  The energies
  // and momentum (energy times direction from vertex) of the seed's 
  // neighbors are summed, if the neighboring energy exceeds a
  // specified threshold.
  

  // First, set the seed tower for this cluster
  m_SeedTower = seed;
  m_NumTowers = 1;
  m_NumSeeds  = 1;
  m_Index     = seed -> getIndex();

  //-- Add this seed tower to the list of seed towers 
  //-- for this cluster (generalized cluster may have
  //-- more than one seed tower).
  m_SeedTowers.push_back(seed);


  // Get the list of neighboring towers, and the list of
  // neighboring seed towers
  EEezTowerPtrVec_t fNeighbors     = seed -> getNeighbors();
  EEezTowerPtrVec_t fNeighborSeeds = seed -> getNeighborSeeds();
  m_NumSeeds += fNeighborSeeds.size();


  // Extract seed-tower parameters to local varaibles  
//   Int_t   fIndex  = seed -> getIndex();  // Tower index (0-719)
//   Int_t   fEta    = fIndex % 12;         // Etabin 
//   Int_t   fPhi    = fIndex / 12;         // Phibin
//   Int_t   fSec    = fPhi / 5;            // Sector
//   Int_t   fSub    = fPhi % 5;            // Subsector

  Int_t fIndex = seed -> getIndex();  // Tower index (0-719)
  Int_t fEta   = seed -> getEtabin(); // Etabin  (0-11)
  Int_t fPhi   = seed -> getPhibin(); // Phibin  (0-59)
  Int_t fSec   = seed -> getSector(); // Sector  (0-11)
  Int_t fSub   = seed -> getSubSector(); // SubSector (0-4)
  Float_t fEnergy = seed -> getEnergy(); // Energy of seed tower
  
  // Intial momentum vector
  TVector3 fMomentum = fEnergy * ( m_EETowGeom -> getTowerCenter(fSec,fSub,fEta).Unit() );


  //
  // Initialize pointers to first and last U and V strips
  //
  m_UFirst[0] = seed -> getUStrip(0);
  m_VFirst[0] = seed -> getVStrip(0);
  Int_t nu = seed -> getNUStrips();
  Int_t nv = seed -> getNVStrips();
  m_ULast[0] = seed -> getUStrip(nu-1);
  m_VLast[0] = seed -> getVStrip(nv-1);


  //
  // Our initial cluster model will be the seed tower plus the 
  // 8 surrounding towers.  Futher analysis may bring the SMD
  // in to refine the cluster.  For overlapping clusters, the
  // energy is split between the two, proportional to the 
  // energies of each seed.
  //


  // Iterate over neighboring towers and calculate energy,
  // eta and phi.
  EEezTowerPtrVecIter_t iter = fNeighbors.begin();

  // Running sum for energy.  Eta and phi will be computed from
  // the resulting summed momentum vector.
  Float_t fSumEnergy = fEnergy;
  

  // Loop over all neighboring towers
  while ( iter != fNeighbors.end() ) { 
    
    // Get the index of this tower, etc...
    Float_t fEnergy1 = (*iter)->getEnergy(); // Energy of this tower
    if ( fEnergy1 < m_EnergyCut ) continue;
    Int_t fIndex1  = (*iter)->getIndex();  // Tower index
//     Int_t fEta1    = fIndex1 % 12;         // Etabin
//     Int_t fPhi1    = fIndex1 / 12;         // Phibin
//     Int_t fSec1    = fPhi1 / 5;            // Sector
//     Int_t fSub1    = fPhi1 % 5;            // Subsector 
    Int_t fEta1 = (*iter)->getEtabin();
    Int_t fPhi1 = (*iter)->getPhibin();
    Int_t fSec1 = (*iter)->getSector();
    Int_t fSub1 = (*iter)->getSubSector(); 

    // Increment our tower count
    m_NumTowers++;

    // Get the momentum vector pointing at this tower
    TVector3 fMomentum1 = fEnergy1 * ( m_EETowGeom -> getTowerCenter(fSec1,fSub1,fEta1).Unit() );

    // Get the energy summed over all adjacent seed towers
    // for the current neighboring tower.  The weight for 
    // this tower is equal to the energy of the seed tower
    // divided by this number.

    EEezTowerPtrVec_t     fAdjSeeds = (*iter) -> getNeighborSeeds();
    EEezTowerPtrVecIter_t iterAdjSeeds = fAdjSeeds.begin();
    Float_t               fEnergyAdjSeeds = 0.;
    while ( iterAdjSeeds != fAdjSeeds.end() ) { 
      fEnergyAdjSeeds += (*iterAdjSeeds)->getEnergy(0);
      iterAdjSeeds++;
    }
    Float_t fWeight = seed -> getEnergy();
    if ( fEnergyAdjSeeds > 0. ) {
      fWeight /= fEnergyAdjSeeds;
    }
    else {
      fWeight = 1.0;
    }

    // Do the math
    fSumEnergy += ( fEnergy1   * fWeight );
    fMomentum  += ( fMomentum1 * fWeight );


    //--
    //-- Get pointers to the first and last U and V Strips
    //-- contained w/in the fiducial volume of this tower
    //--
    nu = (*iter) -> getNUStrips();
    nv = (*iter) -> getNVStrips();
    EEezStrip *uf = (*iter) -> getUStrip(0);
    EEezStrip *vf = (*iter) -> getVStrip(0);
    EEezStrip *ul = (*iter) -> getUStrip(nu-1);
    EEezStrip *vl = (*iter) -> getVStrip(nv-1);

    //-- Towers in the same sector with seed
    if ( fSec == fSec1 ) {
      if ( m_UFirst[0] -> getIndex() > uf -> getIndex() )
	m_UFirst[0] = uf;
      if ( m_VFirst[0] -> getIndex() > vf -> getIndex() )
	m_VFirst[0] = vf;
      if ( m_ULast[0] -> getIndex() < ul -> getIndex() )
	m_ULast[0] = ul;
      if ( m_VLast[0] -> getIndex() < vl -> getIndex() )
	m_VLast[0] = vl;      
    }
    //-- Towers in sector other than seed
    else {
      if ( !m_UFirst[1] ) {
	m_UFirst[1] = uf;
	m_VFirst[1] = vf;
	m_ULast[1]  = ul;
	m_VLast[1]  = vl;
      }
      if ( m_UFirst[1] -> getIndex() > uf -> getIndex() )
	m_UFirst[1] = uf;
      if ( m_VFirst[1] -> getIndex() > vf -> getIndex() )
	m_VFirst[1] = vf;
      if ( m_ULast[1] -> getIndex() < ul -> getIndex() )
	m_ULast[1] = ul;
      if ( m_VLast[1] -> getIndex() < vl -> getIndex() )
	m_VLast[1] = vl;    
    }



    //-- Next neighboring tower
    iter++;

  }



  // NOTE TO SELF-- we are NOT doing a weighted average here!  
  m_ClusterEnergy = fSumEnergy;



#if DEBUG
  std::cout << " Final: " 
	    << fMomentum[0] << " "
 	    << fMomentum[1] << " "
 	    << fMomentum[2] << " "
 	    << std::endl;

  std::cout << " Energy: " 
 	    << m_ClusterEnergy << " "
 	    << fMomentum.Mag() << std::endl;

  std::cout << std::endl;
#endif

  

  // There is a ~0.1% difference between the weighted energy sum,
  // and the magnitude of the resulting momentum vector.  Rescale
  // the momentum vector by our calculated energy.
  
  m_ClusterMomentum = m_ClusterEnergy * ( fMomentum.Unit() );


}


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

 void EEezCluster::setSeedTower( EEezTower *tower ) 
{
  // Sets the seed tower of this cluster... I don't see the need for
  // this method any longer... will probably delete it.
  
  
  m_SeedTower = tower;
  
}

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

 void EEezCluster::Consume ( EEezCluster *cluster ) 
{ 
  // The idea behind this method was to provide a way to merge clusters
  // when doing mixed-event backgrounds.  At the momentum, this method
  // does very little and should not be used.
  

  // Simple for now...
 
  m_ClusterMomentum += cluster -> getMomentum();
  m_ClusterEnergy   += cluster -> getEnergy();


}

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

 void EEezCluster::setType( EEezClusterType type )
{
  // Sets the type of the cluster.
  //
  // EEezCluster::kEEezClusterSingle
  //
  // "Single Seed" cluster.  The cluster is comprised of 8 towers
  // surrounding a single seed tower, such that E_seed / E_cluster
  // is larger than the value specified by setShapeLimit().
  //
  // EEezCluster::kEEezClusterDouble (not implemented)
  //
  // "Double Seed" cluster.  Single-seed clusters which fail the
  // shape limit may be classified as a double-seed cluster.  The
  // cluster will be comprised of the 10 neighbors of two non-
  // diagonally adjacent seed towers.  It is required that the sum
  // E_seed1 + E_seed2 / E_cluster is larger than the value 
  // specified by setShapeLimit().
  //
  // EEezCluster::kEEezClusterDiagonal (not implemented)
  //
  // "Double Seed Diagonal" cluster.  The cluster is comprised of
  // the 12 towers surrounding two diagonally-adjacent seed towers.
  // The sum of the two seeds is required to exceed the value
  // specified by setShapeLimit().
  //
  // EEezCluster::kEEezClusterOther (not implemented)
  //
  // This is a catch-all category which will be used to accumulate
  // multiple-adjacent seed towers, such as may be frequently encountered
  // in AuAu running.   These will be stored in a seperate vector
  // from "normal" clusters.... This type will be better defined
  // once implemented.
  //
  mType = type;

}
 Int_t EEezCluster::getType() 
{
  // Returns the type of cluster.  See setType() for definitions.
  return mType;
}


ROOT page - Class index - Top of the page

This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.