CMS 3D CMS Logo

List of all members | Classes | Public Member Functions | Private Member Functions | Private Attributes | Friends
HFClusterAlgo Class Reference

#include <HFClusterAlgo.h>

Classes

struct  HFCompleteHit
 

Public Member Functions

void clusterize (const HFRecHitCollection &hf, const CaloGeometry &geom, reco::HFEMClusterShapeCollection &clusters, reco::SuperClusterCollection &SuperClusters)
 
 HFClusterAlgo ()
 
void isMC (bool isMC)
 
void resetForRun ()
 
void setup (double minTowerEnergy, double seedThreshold, double maximumSL, double m_maximumRenergy, bool usePMTflag, bool usePulseflag, bool forcePulseFlagMC, int correctionSet)
 

Private Member Functions

bool isPMTHit (const HFRecHit &hfr)
 
bool makeCluster (const HcalDetId &seedid, const HFRecHitCollection &hf, const CaloGeometry *geom, reco::HFEMClusterShape &clusShp, reco::SuperCluster &SClus)
 

Private Attributes

std::vector< double > m_correctionByEta
 
int m_correctionSet
 
std::vector< double > m_cutByEta
 
bool m_forcePulseFlagMC
 
bool m_isMC
 
double m_maximumRenergy
 
double m_maximumSL
 
double m_minTowerEnergy
 
std::vector< double > m_seedmnEta
 
std::vector< double > m_seedmnPhi
 
std::vector< double > m_seedMXeta
 
std::vector< double > m_seedMXphi
 
double m_seedThreshold
 
bool m_usePMTFlag
 
bool m_usePulseFlag
 

Friends

class CompareHFCompleteHitET
 
class CompareHFCore
 

Detailed Description

Author
Kevin Klapoetke (Minnesota)

$Id:version 1.2

Author
K. Klapoetke – Minnesota

Definition at line 22 of file HFClusterAlgo.h.

Constructor & Destructor Documentation

HFClusterAlgo::HFClusterAlgo ( )

Definition at line 20 of file HFClusterAlgo.cc.

21 {
22  m_isMC=true; // safest
23 
24 }

Member Function Documentation

void HFClusterAlgo::clusterize ( const HFRecHitCollection hf,
const CaloGeometry geomO,
reco::HFEMClusterShapeCollection clusters,
reco::SuperClusterCollection SuperClusters 
)

Analyze the hits

Definition at line 91 of file HFClusterAlgo.cc.

References edm::SortedCollection< T, SORT >::begin(), edm::SortedCollection< T, SORT >::end(), HFClusterAlgo::HFCompleteHit::energy, HFClusterAlgo::HFCompleteHit::et, PVValHelper::eta, edm::SortedCollection< T, SORT >::find(), relativeConstraints::geom, CaloGeometry::getGeometry(), CaloGeometry::getPosition(), HcalForward, photonIsolationHIProducer_cfi::hf, mps_fire::i, HFClusterAlgo::HFCompleteHit::id, indexByEta(), gen::k, SimDataFormats::CaloAnalysis::sc, and EZArrayFL< T >::size().

Referenced by isMC(), and HFEMClusterProducer::produce().

94  {
95 
96  const CaloGeometry* geom(&geomO);
97  std::vector<HFCompleteHit> protoseeds, seeds;
99  std::vector<HFCompleteHit>::iterator i;
100  std::vector<HFCompleteHit>::iterator k;
101  int dP, dE, PWrap;
102  bool isok=true;
103  HFEMClusterShape clusShp;
104 
105  SuperCluster Sclus;
106  bool doCluster=false;
107 
108  for (j=hf.begin(); j!= hf.end(); j++) {
109  const int aieta=j->id().ietaAbs();
110  int iz=(aieta-29);
111  // only long fibers and not 29,40,41 allowed to be considered as seeds
112  if (j->id().depth()!=1) continue;
113  if (aieta==40 || aieta==41 || aieta==29) continue;
114 
115 
116  if (iz<0 || iz>12) {
117  edm::LogWarning("HFClusterAlgo") << "Strange invalid HF hit: " << j->id();
118  continue;
119  }
120 
121  if (m_cutByEta[iz]<0) {
122  double eta=geom->getPosition(j->id()).eta();
123  m_cutByEta[iz]=m_seedThreshold*cosh(eta); // convert ET to E for this ring
124  auto ccg=geom->getGeometry(j->id());
125  const CaloCellGeometry::CornersVec& CellCorners=ccg->getCorners();
126  for(size_t sc=0;sc<CellCorners.size();sc++){
127  if(fabs(CellCorners[sc].z())<1200){
128  if(fabs(CellCorners[sc].eta())<m_seedmnEta[iz])m_seedmnEta[iz]=fabs(CellCorners[sc].eta());
129  if(fabs(CellCorners[sc].eta())>m_seedMXeta[iz])m_seedMXeta[iz]=fabs(CellCorners[sc].eta());
130  }
131  }
132  }
133  double elong=j->energy()*m_correctionByEta[indexByEta(j->id())];
134  if (elong>m_cutByEta[iz]) {
135  j2=hf.find(HcalDetId(HcalForward,j->id().ieta(),j->id().iphi(),2));
136  double eshort=(j2==hf.end())?(0):(j2->energy());
137  if (j2!=hf.end())
138  eshort*=m_correctionByEta[indexByEta(j2->id())];
139  if (((elong-eshort)/(elong+eshort))>m_maximumSL) continue;
140  //if ((m_usePMTFlag)&&(j->flagField(4,1))) continue;
141  //if ((m_usePulseFlag)&&(j->flagField(1,1))) continue;
142  if(isPMTHit(*j)) continue;
143 
144  HFCompleteHit ahit;
145  double eta=geom->getPosition(j->id()).eta();
146  ahit.id=j->id();
147  ahit.energy=elong;
148  ahit.et=ahit.energy/cosh(eta);
149  protoseeds.push_back(ahit);
150  }
151  }
152 
153  if(!protoseeds.empty()){
154  std::sort(protoseeds.begin(), protoseeds.end(), CompareHFCompleteHitET());
155  for (i=protoseeds.begin(); i!= protoseeds.end(); i++) {
156  isok=true;
157  doCluster=false;
158 
159  if ( (i==protoseeds.begin()) && (isok) ) {
160  doCluster=true;
161  }else {
162  // check for overlap with existing clusters
163  for (k=seeds.begin(); isok && k!=seeds.end(); k++) { //i->hits, k->seeds
164 
165  for (dE=-2; dE<=2; dE++)
166  for (dP=-4;dP<=4; dP+=2) {
167  PWrap=k->id.iphi()+dP;
168  if (PWrap<0)
169  PWrap+=72;
170  if (PWrap>72)
171  PWrap-=72;
172 
173  if ( (i->id.iphi()==PWrap) && (i->id.ieta()==k->id.ieta()+dE))
174  isok = false;
175  }
176  }
177  if (isok) {
178  doCluster=true;
179  }
180  }
181  if (doCluster) {
182  seeds.push_back(*i);
183 
184  bool clusterOk=makeCluster( i->id(),hf, geom,clusShp,Sclus);
185  if (clusterOk) { // cluster is _not_ ok if seed is rejected due to other cuts
186  clusterShapes.push_back(clusShp);
187  SuperClusters.push_back(Sclus);
188  }
189 
190  }
191  }//end protoseed loop
192  }//end if seeCount
193 }
std::vector< double > m_cutByEta
Definition: HFClusterAlgo.h:48
double m_maximumSL
Definition: HFClusterAlgo.h:43
std::vector< double > m_correctionByEta
Definition: HFClusterAlgo.h:49
std::vector< T >::const_iterator const_iterator
std::vector< double > m_seedmnEta
Definition: HFClusterAlgo.h:50
friend class CompareHFCompleteHitET
Definition: HFClusterAlgo.h:40
l1t::ClusterShapes clusterShapes
Definition: classes.h:66
std::vector< double > m_seedMXeta
Definition: HFClusterAlgo.h:51
int k[5][pyjets_maxn]
const_iterator end() const
static int indexByEta(HcalDetId id)
size_type size() const
Definition: EZArrayFL.h:81
iterator find(key_type k)
double m_seedThreshold
Definition: HFClusterAlgo.h:43
bool makeCluster(const HcalDetId &seedid, const HFRecHitCollection &hf, const CaloGeometry *geom, reco::HFEMClusterShape &clusShp, reco::SuperCluster &SClus)
bool isPMTHit(const HFRecHit &hfr)
const_iterator begin() const
void HFClusterAlgo::isMC ( bool  isMC)
inline
bool HFClusterAlgo::isPMTHit ( const HFRecHit hfr)
private

Definition at line 399 of file HFClusterAlgo.cc.

References CaloRecHit::flagField(), HcalCaloFlagLabels::HFDigiTime, and HcalCaloFlagLabels::HFLongShort.

399  {
400 
401  bool pmthit=false;
402 
403  if((hfr.flagField(HcalCaloFlagLabels::HFLongShort))&&(m_usePMTFlag)) pmthit=true;
404  if (!(m_isMC && !m_forcePulseFlagMC))
405  if((hfr.flagField(HcalCaloFlagLabels::HFDigiTime))&&(m_usePulseFlag)) pmthit=true;
406 
407  return pmthit;
408 }
bool m_forcePulseFlagMC
Definition: HFClusterAlgo.h:45
constexpr uint32_t flagField(int base, int width=1) const
Definition: CaloRecHit.h:48
bool HFClusterAlgo::makeCluster ( const HcalDetId seedid,
const HFRecHitCollection hf,
const CaloGeometry geom,
reco::HFEMClusterShape clusShp,
reco::SuperCluster SClus 
)
private

Definition at line 196 of file HFClusterAlgo.cc.

References funct::abs(), edm::SortedCollection< T, SORT >::end(), PVValHelper::eta, PV3DBase< T, PVType, FrameType >::eta(), edm::SortedCollection< T, SORT >::find(), CaloGeometry::getPosition(), HcalForward, training_settings::idx, HcalDetId::ieta(), HcalDetId::ietaAbs(), indexByEta(), HcalDetId::iphi(), cmsBatch::log, M_PI, SiStripPI::max, AlCaHLTBitMon_ParallelJobs::p, PV3DBase< T, PVType, FrameType >::phi(), w, PV3DBase< T, PVType, FrameType >::x(), PV3DBase< T, PVType, FrameType >::y(), PV3DBase< T, PVType, FrameType >::z(), and HcalDetId::zside().

200  {
201 
202 
203  double w=0;//sum over all log E's
204  double wgt=0;
205  double w_e=0;//sum over ieat*energy
206  double w_x=0;
207  double w_y=0;
208  double w_z=0;
209  double wp_e=0;//sum over iphi*energy
210  double e_e=0;//nonwieghted eta sum
211  double e_ep=0; //nonweighted phi sum
212 
213  double l_3=0;//sum for enenergy in 3x3 long fibers etc.
214  double s_3=0;
215  double l_5=0;
216  double s_5=0;
217  double l_1=0;
218  double s_1=0;
219  int de, dp, phiWrap;
220  double l_1e=0;
221  const GlobalPoint& sp=geom->getPosition(seedid);
222  std::vector<double> coreCanid;
223  std::vector<double>::const_iterator ci;
225  std::vector<DetId> usedHits;
226 
228  HcalDetId sid(HcalForward,seedid.ieta(),seedid.iphi(),1);
229  si=hf.find(sid);
230 
231  bool clusterOk=true; // assume the best to start...
232 
233  // lots happens here
234  // edge type 1 has 40/41 in 3x3 and 5x5
235  bool edge_type1=seedid.ietaAbs()==39 && (seedid.iphi()%4)==3;
236 
237  double e_seed=si->energy()*m_correctionByEta[indexByEta(si->id())];
238 
239  for (de=-2; de<=2; de++)
240  for (dp=-4;dp<=4; dp+=2) {
241  phiWrap=seedid.iphi()+dp;
242  if (phiWrap<0)
243  phiWrap+=72;
244  if (phiWrap>72)
245  phiWrap-=72;
246 
247 
248  /* Handling of phi-width change problems */
249  if (edge_type1 && de==seedid.zside()) {
250  if (dp==-2) { // we want it in the 3x3
251  phiWrap-=2;
252  if (phiWrap<0)
253  phiWrap+=72;
254  }
255  else if (dp==-4) {
256  continue; // but not double counted in 5x5
257  }
258  }
259 
260  HcalDetId idl(HcalForward,seedid.ieta()+de,phiWrap,1);
261  HcalDetId ids(HcalForward,seedid.ieta()+de,phiWrap,2);
262 
263 
264  il=hf.find(idl);
265  is=hf.find(ids);
266 
267 
268 
269 
270  double e_long=1.0;
271  double e_short=0.0;
272  if (il!=hf.end()) e_long=il->energy()*m_correctionByEta[indexByEta(il->id())];
273  if (e_long <= m_minTowerEnergy) e_long=0.0;
274  if (is!=hf.end()) e_short=is->energy()*m_correctionByEta[indexByEta(is->id())];
275  if (e_short <= m_minTowerEnergy) e_short=0.0;
276  double eRatio=(e_long-e_short)/std::max(1.0,(e_long+e_short));
277 
278  // require S/L > a minimum amount for inclusion
279  if ((abs(eRatio) > m_maximumSL)&&(std::max(e_long,e_short) > m_maximumRenergy)) {
280  if (dp==0 && de==0) clusterOk=false; // somehow, the seed is hosed
281  continue;
282  }
283 
284  if((il!=hf.end())&&(isPMTHit(*il))){
285  if (dp==0 && de==0) clusterOk=false; // somehow, the seed is hosed
286  continue;//continue to next hit, do not include this one in cluster
287  }
288 
289 
290 
291 
292 
293  if (e_long > m_minTowerEnergy && il!=hf.end()) {
294 
295  // record usage
296  usedHits.push_back(idl.rawId());
297  // always in the 5x5
298  l_5+=e_long;
299  // maybe in the 3x3
300  if ((de>-2)&&(de<2)&&(dp>-4)&&(dp<4)) {
301  l_3+=e_long;
302 
303  // sometimes in the 1x1
304  if ((dp==0)&&(de==0)) {
305  l_1=e_long;
306  }
307 
308  // maybe in the core?
309  if ((de>-2)&&(de<2)&&(dp>-4)&&(dp<4)&&(e_long>(.5*e_seed))) {
310  coreCanid.push_back(e_long);
311  }
312 
313  // position calculation
314  const GlobalPoint& p=geom->getPosition(idl);
315 
316  double d_p = p.phi()-sp.phi();
317  while (d_p < -M_PI)
318  d_p+=2*M_PI;
319  while (d_p > M_PI)
320  d_p-=2*M_PI;
321  double d_e = p.eta()-sp.eta();
322 
323  wgt=log((e_long));
324  if (wgt>0){
325  w+=wgt;
326  w_e+=(d_e)*wgt;
327  wp_e+=(d_p)*wgt;
328  e_e+=d_e;
329  e_ep+=d_p;
330 
331  w_x+=(p.x())*wgt;//(p.x()-sp.x())*wgt;
332  w_y+=(p.y())*wgt;
333  w_z+=(p.z())*wgt;
334  }
335  }
336  } else {
337  if (dp==0 && de==0) clusterOk=false; // somehow, the seed is hosed
338  }
339 
340  if (e_short > m_minTowerEnergy && is!=hf.end()) {
341  // record usage
342  usedHits.push_back(ids.rawId());
343  // always in the 5x5
344  s_5+=e_short;
345  // maybe in the 3x3
346  if ((de>-2)&&(de<2)&&(dp>-4)&&(dp<4)) {
347  s_3+=e_short;
348  }
349  // sometimes in the 1x1
350  if ((dp==0)&&(de==0)) {
351  s_1=e_short;
352  }
353  }
354  }
355 
356 
357  if (!clusterOk) return false;
358 
359  //Core sorting done here
360  std::sort(coreCanid.begin(), coreCanid.end(), CompareHFCore());
361  for (ci=coreCanid.begin();ci!=coreCanid.end();ci++){
362  if(ci==coreCanid.begin()){
363  l_1e=*ci;
364  }else if (*ci>.5*l_1e){
365  l_1e+=*ci;
366  }
367  }//core sorting end
368 
369  double z_=w_z/w;
370  double x_=w_x/w;
371  double y_=w_y/w;
372  math::XYZPoint xyzclus(x_,y_,z_);
373  //calcualte position, final
374  double eta=xyzclus.eta();//w_e/w+sp.eta();
375 
376  double phi=xyzclus.phi();//(wp_e/w)+sp.phi();
377 
378  while (phi < -M_PI)
379  phi+=2*M_PI;
380  while (phi > M_PI)
381  phi-=2*M_PI;
382 
383  //calculate cell phi and cell eta
384  int idx= fabs(seedid.ieta())-29;
385  int ipx=seedid.iphi();
386  double Cphi =(phi-m_seedmnPhi[ipx])/(m_seedMXphi[ipx]-m_seedmnPhi[ipx]);
387  double Ceta=(fabs(eta)- m_seedmnEta[idx])/(m_seedMXeta[idx]-m_seedmnEta[idx]);
388 
389  //return HFEMClusterShape, SuperCluster
390  HFEMClusterShape myClusShp(l_1, s_1, l_3, s_3, l_5,s_5, l_1e,Ceta, Cphi,seedid);
391  clusShp = myClusShp;
392 
393  SuperCluster MySclus(l_3,xyzclus);
394  Sclus=MySclus;
395 
396  return clusterOk;
397 
398 }
double m_minTowerEnergy
Definition: HFClusterAlgo.h:43
double m_maximumRenergy
Definition: HFClusterAlgo.h:43
const double w
Definition: UKUtility.cc:23
int zside() const
get the z-side of the cell (1/-1)
Definition: HcalDetId.h:149
double m_maximumSL
Definition: HFClusterAlgo.h:43
std::vector< double > m_correctionByEta
Definition: HFClusterAlgo.h:49
Geom::Phi< T > phi() const
Definition: PV3DBase.h:69
std::vector< T >::const_iterator const_iterator
T y() const
Definition: PV3DBase.h:63
std::vector< double > m_seedmnEta
Definition: HFClusterAlgo.h:50
friend class CompareHFCore
Definition: HFClusterAlgo.h:41
std::vector< double > m_seedMXeta
Definition: HFClusterAlgo.h:51
T z() const
Definition: PV3DBase.h:64
int ieta() const
get the cell ieta
Definition: HcalDetId.h:159
GlobalPoint getPosition(const DetId &id) const
Get the position of a given detector id.
Definition: CaloGeometry.cc:74
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
std::vector< double > m_seedmnPhi
Definition: HFClusterAlgo.h:52
#define M_PI
int ietaAbs() const
get the absolute value of the cell ieta
Definition: HcalDetId.h:154
const_iterator end() const
static int indexByEta(HcalDetId id)
int iphi() const
get the cell iphi
Definition: HcalDetId.h:161
XYZPointD XYZPoint
point in space with cartesian internal representation
Definition: Point3D.h:12
std::vector< double > m_seedMXphi
Definition: HFClusterAlgo.h:53
T eta() const
Definition: PV3DBase.h:76
iterator find(key_type k)
T x() const
Definition: PV3DBase.h:62
bool isPMTHit(const HFRecHit &hfr)
void HFClusterAlgo::resetForRun ( )

Definition at line 409 of file HFClusterAlgo.cc.

References cuy::ii.

Referenced by HFEMClusterProducer::beginRun(), and isMC().

409  {
410  edm::LogInfo("HFClusterAlgo")<<"Resetting for Run!";
411  for(int ii=0;ii<13;ii++){
412  m_cutByEta.push_back(-1);
413  m_seedmnEta.push_back(99);
414  m_seedMXeta.push_back(-1);
415  }
416 }
std::vector< double > m_cutByEta
Definition: HFClusterAlgo.h:48
std::vector< double > m_seedmnEta
Definition: HFClusterAlgo.h:50
std::vector< double > m_seedMXeta
Definition: HFClusterAlgo.h:51
ii
Definition: cuy.py:590
void HFClusterAlgo::setup ( double  minTowerEnergy,
double  seedThreshold,
double  maximumSL,
double  m_maximumRenergy,
bool  usePMTflag,
bool  usePulseflag,
bool  forcePulseFlagMC,
int  correctionSet 
)

Definition at line 48 of file HFClusterAlgo.cc.

References hfClusterShapes_cfi::forcePulseFlagMC, cuy::ii, M_PI, hfClusterShapes_cfi::maximumRenergy, hfClusterShapes_cfi::maximumSL, MCMaterialCorrections_3XX, hfClusterShapes_cfi::minTowerEnergy, and UEAnalysisJets_cfi::seedThreshold.

Referenced by HFEMClusterProducer::HFEMClusterProducer().

49  {
53  m_usePMTFlag=usePMTflag;
54  m_usePulseFlag=usePulseflag;
57  m_correctionSet = correctionSet;
58 
59  for(int ii=0;ii<13;ii++){
60  m_cutByEta.push_back(-1);
61  m_seedmnEta.push_back(99);
62  m_seedMXeta.push_back(-1);
63  }
64  for(int ii=0;ii<73;ii++){
65  double minphi=0.0872664*(ii-1);
66  double maxphi=0.0872664*(ii+1);
67  while (minphi < -M_PI)
68  minphi+=2*M_PI;
69  while (minphi > M_PI)
70  minphi-=2*M_PI;
71  while (maxphi < -M_PI)
72  maxphi+=2*M_PI;
73  while (maxphi > M_PI)
74  maxphi-=2*M_PI;
75  if(ii==37)
76  minphi=-3.1415904;
77  m_seedmnPhi.push_back(minphi);
78  m_seedMXphi.push_back(maxphi);
79  }
80 
81  // always set all the corrections to one...
82  for (int ii=0; ii<13*2; ii++)
83  m_correctionByEta.push_back(1.0);
84  if (m_correctionSet==1) { // corrections for material from MC
85  for (int ii=0; ii<13*2; ii++)
87  }
88 }
double m_minTowerEnergy
Definition: HFClusterAlgo.h:43
double m_maximumRenergy
Definition: HFClusterAlgo.h:43
bool m_forcePulseFlagMC
Definition: HFClusterAlgo.h:45
std::vector< double > m_cutByEta
Definition: HFClusterAlgo.h:48
double m_maximumSL
Definition: HFClusterAlgo.h:43
std::vector< double > m_correctionByEta
Definition: HFClusterAlgo.h:49
std::vector< double > m_seedmnEta
Definition: HFClusterAlgo.h:50
static const double MCMaterialCorrections_3XX[]
std::vector< double > m_seedMXeta
Definition: HFClusterAlgo.h:51
std::vector< double > m_seedmnPhi
Definition: HFClusterAlgo.h:52
ii
Definition: cuy.py:590
#define M_PI
std::vector< double > m_seedMXphi
Definition: HFClusterAlgo.h:53
double m_seedThreshold
Definition: HFClusterAlgo.h:43

Friends And Related Function Documentation

friend class CompareHFCompleteHitET
friend

Definition at line 40 of file HFClusterAlgo.h.

friend class CompareHFCore
friend

Definition at line 41 of file HFClusterAlgo.h.

Member Data Documentation

std::vector<double> HFClusterAlgo::m_correctionByEta
private

Definition at line 49 of file HFClusterAlgo.h.

int HFClusterAlgo::m_correctionSet
private

Definition at line 47 of file HFClusterAlgo.h.

std::vector<double> HFClusterAlgo::m_cutByEta
private

Definition at line 48 of file HFClusterAlgo.h.

bool HFClusterAlgo::m_forcePulseFlagMC
private

Definition at line 45 of file HFClusterAlgo.h.

bool HFClusterAlgo::m_isMC
private

Definition at line 46 of file HFClusterAlgo.h.

Referenced by isMC().

double HFClusterAlgo::m_maximumRenergy
private

Definition at line 43 of file HFClusterAlgo.h.

double HFClusterAlgo::m_maximumSL
private

Definition at line 43 of file HFClusterAlgo.h.

double HFClusterAlgo::m_minTowerEnergy
private

Definition at line 43 of file HFClusterAlgo.h.

std::vector<double> HFClusterAlgo::m_seedmnEta
private

Definition at line 50 of file HFClusterAlgo.h.

std::vector<double> HFClusterAlgo::m_seedmnPhi
private

Definition at line 52 of file HFClusterAlgo.h.

std::vector<double> HFClusterAlgo::m_seedMXeta
private

Definition at line 51 of file HFClusterAlgo.h.

std::vector<double> HFClusterAlgo::m_seedMXphi
private

Definition at line 53 of file HFClusterAlgo.h.

double HFClusterAlgo::m_seedThreshold
private

Definition at line 43 of file HFClusterAlgo.h.

bool HFClusterAlgo::m_usePMTFlag
private

Definition at line 44 of file HFClusterAlgo.h.

bool HFClusterAlgo::m_usePulseFlag
private

Definition at line 45 of file HFClusterAlgo.h.