StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
StEEmcStripClusterFinderIU.cxx
1 
8 #include <algorithm>
9 
10 #include <Rtypes.h>
11 #include <TMath.h>
12 #include <TArrayS.h>
13 #include <TArrayF.h>
14 
15 #include "StRoot/St_base/StMessMgr.h"
16 #include "StRoot/St_base/Stypes.h"
17 
18 #include "StRoot/StEEmcPool/./EEmcTreeContainers/EEmcEnergy.h"
19 
20 #include "StEEmcStripClusterFinderIU.h"
21 #include "StSimpleCluster.h"
22 #include "StFinderAlg.h"
23 
26  mIgnoreCorners( true ),
27  mUseNaiveFloorShape( true ),
28  mApplyClusterSplitting( 1 ),
29  mMaxExtent( 3 ),
30  mMinStripsPerCluster( 3 ),
31  mMinSeedDistance( 3 ),
32  mSeedFloor( 2.0 ),
33  mNeedsToBeCleared( 1 )
34 {
35  mSeedEnergyThres[ U_LAYER ] = 0.003;
36  mSeedEnergyThres[ V_LAYER ] = 0.003;
37  mLayer = U_LAYER;
38  mSector = 0;
39  mIsReady = 1;
40 };
41 
42 void StEEmcStripClusterFinderIU_t::setMaxExtent( Int_t maxExtent ){
43  mMaxExtent = maxExtent;
44 
45  if( mMaxExtent < 3 ){
46  LOG_WARN << "StEEmcStripClusterFinderIU_t::setMaxExtent" << endm;
47  LOG_WARN << "\t maxExtent must be >= 2, not " << maxExtent << endm;
48  LOG_WARN << "\t defaulting to minimum: maxExtent = 2" << endm;
49  maxExtent = 2;
50  };
51 };
52 
53 void StEEmcStripClusterFinderIU_t::setMinStripsPerCluster( Int_t min ){
54  mMinStripsPerCluster = min;
55 
56  if( mMinStripsPerCluster < 2 ){
57  LOG_WARN << "StEEmcStripClusterFinderIU_t::setMinStripsPerCluster" << endm;
58  LOG_WARN << "\t MinStripsPerCluster must be >= 1, not " << mMinStripsPerCluster << endm;
59  LOG_WARN << "\t setting to default value of 3" << endm;
60  mMinStripsPerCluster = 3;
61  };
62 };
63 
65  // don't waste time if clear isn't needed
66  if( mNeedsToBeCleared ){
67  // reset array for keeping track of strips not in clusters
68  // negative flags that ID is invalid---but make sure IDs are still unique
69  for( Int_t i = 0; i < kEEmcNumStrips; ++i ){
70  mClosestClusterIDForEachStrip[i] = -i-1;
71  mFirstClusterIDForEachStrip[i] = -i-1;
72  };
73 
74  // clear seed floor array
75  for( Float_t *f_ptr = mSeedFloorArray; f_ptr != mSeedFloorArray + kEEmcNumStrips; ++f_ptr )
76  (*f_ptr) = 0;
77 
78  mNeedsToBeCleared = 0;
79  };
80 };
81 
83 Int_t StEEmcStripClusterFinderIU_t::find( const ESmdLayer_t& stripArray, StSimpleClusterVec_t& clusterVec ){
84 
85  if( mNeedsToBeCleared ){
86  // forgot to clear it, so do it now
87  clear();
88  };
89 
90  //LOG_INFO << "********** StEEmcStripClusterFinderIU_t::find(...) **********" << endm;
91 
92  // just return if no hit strips, or if not enough strips to form a cluster
93  if( stripArray.nStrips < mMinStripsPerCluster )
94  return kStOK;
95 
96  // ensure cleared
97  clear();
98 
99  double floorParam1 = 0;
100  double floorParam2 = 0;
101 
102  if( mSector == 0 || mSector == 3 || mSector == 6 || mSector == 9 ){
103  if( mLayer == U_LAYER ){
104  floorParam1=0.4;
105  floorParam2=0.2;
106  } else {
107  floorParam1=0.2;
108  floorParam2=0.1;
109  };
110  } else {
111  if( mLayer == U_LAYER ){
112  floorParam1=0.2;
113  floorParam2=0.1;
114  } else {
115  floorParam1=0.4;
116  floorParam2=0.2;
117  };
118  };
119 
120  // Note: for MC data, Weihong used fixed values for all layers and sectors
121  // floorParam1=0.2;
122  // floorParam2=0.1;
123 
124  // flag that will need to clear again after this function call
125  mNeedsToBeCleared = 1;
126 
127  // container for seeds
128  // important that this contains pointers, not copies
129  vector< const EEmcElement_t* > seedStrips;
130 
131  // set all hit strip points
132 
133  // iterate over strips to find seeds
134 
135  // Note: only iterates between 3 and 283, as per Weihong's code. He stated this was removing the "corners" but it only removes 2 of the 4 corners.
136  // It should also depend on the sector and u/v layer.
137  Int_t index = 3;
138  for( const EEmcElement_t *strip = &stripArray.strip[index]; strip != &stripArray.strip[283]; ++strip, ++index ){
139 
140  // determine energy threshold as the sum of the floor plus the
141  // overall threshold
142  Float_t threshold = mSeedEnergyThres[ mLayer ];
143  if( mSeedFloor )
144  threshold += mSeedFloor*mSeedFloorArray[ index ];
145  //LOG_INFO << "------> threshold = " << threshold << endm;
146 
147  // check cuts
148  if( !strip->fail && strip->energy > threshold ){
149  // strip passes as a seed, so add to the list
150  seedStrips.push_back( strip );
151 
152  //LOG_INFO << "-----> seed strip index = " << hitStripIter->index() << ", energy = " << hitStripIter->energy() << " <-----" << endm;
153 
154  // also increase floor for other strips
155  if( mUseNaiveFloorShape ){
156  // the not "LOOSE_CUTS" version
157 
158  for ( Int_t i = 0; i < 288; ++i ){
159  Int_t delta = (i > index ? i-index : index-i);
160 
162  if( delta < 3 )
163  mSeedFloorArray[i] += strip->energy;
164 
166  if( delta >= 3 && delta < 5 )
167  mSeedFloorArray[i] += floorParam1*strip->energy;
168 
170  if( delta >= 5 && delta < 11 )
171  mSeedFloorArray[i] += floorParam2*strip->energy;
172 
174  if( delta >= 11 && delta < 21 )
175  mSeedFloorArray[i] += 0.05*strip->energy;
176  };
177 
178  } else {
179  // the "LOOSE_CUTS" version
180 
181  Int_t imin = ( index -6 < 0 ? 0 : index - 6 );
182  Int_t imax = ( index + 6 > kEEmcNumStrips ? kEEmcNumStrips : index + 6 );
183 
184  for( Int_t i = imin; i <= imax; ++i ){
185  // "Within +/- 6 strips, Floor is (at least) 5% of seed"
186  // Note: if threshold already above, then don't add to it
187  if ( TMath::Abs(index-i) < 7 )
188  if ( 0.05*strip->energy > mSeedFloorArray[i] )
189  mSeedFloorArray[i] += 0.05*strip->energy;
190  };
191 
192  };
193  // end if statement for whether to keep
194  };
195  // end of iteration over strips
196  };
197 
198  // note: since mMaxExtent is fixed, then any one given strip can be
199  // in at most two clusters. Also, a cluster cannot overlap with
200  // more than one other cluster on each side.
201 
202  //LOG_INFO << "-----> Iterating over seeds (" << seedStrips.size() << ") to find clusters <-----" << endm;
203 
204  // sort seeds in decending order by energy
205  std::sort( seedStrips.begin(), seedStrips.end(), energyGreaterThan );
206 
207  // iterate over seeds to define clusters.
208  vector< const EEmcElement_t* >::iterator seedStripIter = seedStrips.begin();
209  for( ; seedStripIter != seedStrips.end(); ++seedStripIter ){
210  Int_t index = static_cast< Int_t >( (*seedStripIter) - stripArray.strip );
211 
212  Bool_t ok_seed = 1;
213 
214  //LOG_INFO << "VVV index " << index << " already in a cluster. Closest is " << mClosestClusterIDForEachStrip[ index ] << endm;
215 
216  // if seed already in a different strip, make sure it is at least
217  // so many strips apart.
218  if( mClosestClusterIDForEachStrip[ index ] > -1 ){
219 
220  // find the cluster to get its seed
221  Bool_t found = 0;
222  ok_seed = 0;
223  Int_t i = -1;
224 
225  while( i < (Int_t)clusterVec.size() - 1 && !found ){
226  found = (clusterVec[++i].getID() == mClosestClusterIDForEachStrip[ index ] );
227  //LOG_INFO << "vvv a) " << clusterVec[i].getID() << ' ' << clusterVec[i].getSeedMember() << endm;
228  };
229 
230  // sanity check
231  if( !found ){
232  LOG_WARN << "a) Error finding cluster with ID " << mClosestClusterIDForEachStrip[ index ] << endm;
233  } else {
234  Int_t delta = TMath::Abs( index - clusterVec[i].getSeedMember() );
235  ok_seed = ( delta > mMinSeedDistance );
236  //LOG_INFO << "Seed " << index << " already in cluster " << i << ", delta = |" << index << " - " << clusterVec[i].getSeedMember() << "| = " << delta << endm;
237  //LOG_INFO << clusterVec[i] << endm;
238 
239  if( clusterVec[i].getSeedIdx() > 10 ){
240  LOG_FATAL << "Something wierd is going on" << endm;
241  return kStFatal;
242  };
243  };
244  };
245 
246  // passes critereon
247  if( ok_seed ){
248 
249  //LOG_INFO << "-----> clus w/ seed index = " << (*seedStripIter)->index() << ", energy = " << (*seedStripIter)->energy() << " <-----" << endm;
250 
251  // range of strips to include
252  Int_t max = index + mMaxExtent;
253  Int_t min = index - mMaxExtent;
254 
255  // check range
256  if( min < 0 )
257  min = 0;
258  if( max > kEEmcNumStrips )
259  max = kEEmcNumStrips;
260 
261  // number of strips in the cluster
262  Int_t nStripsInClus = 0;
263 
264  // count how many strips actually in the cluster
265  for( Int_t i = min; i <= max; ++i )
266  if( stripArray.strip[i].energy && !stripArray.strip[i].fail )
267  ++nStripsInClus;
268 
269  // check if enough
270  if( nStripsInClus >= mMinStripsPerCluster ){
271 
272  // make a new cluster
273  clusterVec.push_back( StSimpleCluster_t( ++mLastClusterID ) );
274 
275  //LOG_INFO << "vvv new " << clusterVec.back().getID() << ' ' << clusterVec.back().getSeedMember() << endm;
276 
277  // get reference to the cluster. Note: important to use
278  // reference not copy constuctor in all the following places
279  // references occur
280  StSimpleCluster_t &cluster = clusterVec.back();
281 
282  // nominal value for the moment
283  cluster.setEnergy( -999 );
284 
285  // get reference to the arrays and set the size
286  TArrayS &member = cluster.getMemberArray();
287  TArrayF &weight = cluster.getWeightArray();
288  member.Set( nStripsInClus );
289  weight.Set( nStripsInClus );
290 
291  // keep track of position in member
292  Int_t member_idx = -1;
293 
294  // add the seed as the first strip (needed for splitting)
295  member[ ++member_idx ] = index;
296  weight[ member_idx ] = 1;
297  cluster.setSeedIdx( 0 ); // member_idx == 0 at this point
298 
299  //LOG_INFO << "-----> new cluster: " << cluster << endm;
300 
301  // iterate over strips in the cluster.
302  // save the index, but don't include the seed twice.
303  // also add to mClosestClusterIDForEachStrip
304  for( Int_t i = min; i <= max; ++i ){
305  // check that index doesn't equal that for the seed.
306  // Also check that the strip was really hit
307  if( i != index && stripArray.strip[i].energy > 0 && !stripArray.strip[i].fail ){
308 
309  //LOG_INFO << "www " << member_idx + 1 << ' ' << nStripsInClus << ' ' << member.GetSize() << endm;
310 
311  member[ ++member_idx ] = i;
312  weight[ member_idx ] = 1;
313 
314  //LOG_INFO << "www" << endm;
315 
316  //LOG_INFO << "first cluster for index " << i << " is " << mFirstClusterIDForEachStrip[ i ] << endm;
317 
318  if( mFirstClusterIDForEachStrip[ i ] < 0 ){
319  // this is the first one, so set is also the closest
320  mFirstClusterIDForEachStrip[ i ] = cluster.getID();
321  mClosestClusterIDForEachStrip[ i ] = cluster.getID();
322  } else {
323  // Not the first one--check to see if this clusters is "closer" than the previous closest cluster.
324  // Note: any strip can be in at most two clusters if min seed distance == max extent
325 
326  // find other cluster
327  Bool_t found = 0;
328  Int_t j = -1;
329  while( j < (Int_t)clusterVec.size() - 1 && !found )
330  found = (clusterVec[++j].getID() == mClosestClusterIDForEachStrip[ i ] );
331 
332  // sanity check
333  if( !found ){
334  LOG_WARN << "b) Error finding cluster with ID " << mClosestClusterIDForEachStrip[ i ] << endm;
335 
336  // default to using the new one, since the previous cluster not found
337  mClosestClusterIDForEachStrip[ i ] = cluster.getID();
338  } else {
339  Int_t delta_other = TMath::Abs( i - clusterVec[j].getSeedMember() );
340  Int_t delta_this = TMath::Abs( i - cluster.getSeedMember() );
341 
342  if( delta_this < delta_other ){
343  // switch to this one
344  mClosestClusterIDForEachStrip[ i ] = cluster.getID();
345  };
346  };
347  };
348 
349  //LOG_INFO << "vvv closest cluster for strip " << i << " ID = " << mClosestClusterIDForEachStrip[ i ] << endm;
350  };
351  };
352  //LOG_INFO << "VVV a)" << endm;
353  };
354  // end check that seed is far enough away from other seeds
355  //LOG_INFO << "VVV b)" << endm;
356  };
357  // end loop over all possible seeds
358  //LOG_INFO << "VVV c)" << endm;
359  };
360 
361  //LOG_INFO << "VVV d)" << endm;
362 
363  if( mApplyClusterSplitting ){
364 
365  //LOG_INFO << "-----> Applying cluster splitting <-----" << endm;
366 
367  // iterate over clusters
368  StSimpleClusterVec_t::iterator clusIter1 = clusterVec.begin();
369  StSimpleClusterVec_t::iterator clusIter2;
370 
371  for( clusIter1 = clusterVec.begin(); clusIter1 != clusterVec.end(); ++clusIter1 ){
372  for( clusIter2 = clusterVec.begin(); clusIter2 < clusIter1; ++clusIter2 ){
373 
374  // make some pointers for the two clusters to make the
375  // code simpler.
376  StSimpleCluster_t *rightClusPtr = &(*clusIter1);
377  StSimpleCluster_t *leftClusPtr = &(*clusIter2);
378 
379  // set it so that the index of left is less than the index of right
380  if( leftClusPtr->getSeedMember() > rightClusPtr->getSeedMember() ){
381  // switch
382  rightClusPtr = &(*clusIter2);
383  leftClusPtr = &(*clusIter1);
384  };
385 
386  // check to see how close they are
387  if( rightClusPtr->getSeedMember() - leftClusPtr->getSeedMember() <= 2*mMaxExtent ){
388  // are overlapping, do energy sharing
389 
390  // make copies of the indices for the seeds
391  Int_t leftSeedIdx = leftClusPtr->getSeedMember();
392  Int_t rightSeedIdx = rightClusPtr->getSeedMember();
393 
394  // Energy on the outside halves of both strips. Note:
395  // Weihong calls leftEnergy and rightEnergy,
396  // respectively, EI and EII. Both are intialized to
397  // the seed energy
398  Float_t leftEnergy = stripArray.strip[ leftSeedIdx ].energy;
399  Float_t rightEnergy = stripArray.strip[ rightSeedIdx ].energy;
400 
401  //LOG_INFO << "VVV e)" << endm;
402 
403  // Compute energy on the left hand side of the left cluster.
404  // Note: start at 1 so don't count seed twice.
405  // todo: could do a sanity check on temp_index
406  {
407  TArrayS leftMember = leftClusPtr->getMemberArray();
408  Int_t i = 1;
409  for( Int_t tempIdx = leftMember[ i ]; tempIdx < leftSeedIdx && i < leftMember.GetSize()-1; tempIdx = leftMember[++i] )
410  leftEnergy += stripArray.strip[ tempIdx ].energy;
411  };
412 
413  //LOG_INFO << "VVV f)" << endm;
414 
415  // Compute energy on the right hand side of the right cluster.
416  {
417  TArrayS rightMember = rightClusPtr->getMemberArray();
418  Int_t i = rightMember.GetSize()-1;
419  for( Int_t tempIdx = rightMember[ i ]; tempIdx > rightSeedIdx && i >-1; tempIdx = rightMember[--i] )
420  rightEnergy += stripArray.strip[ tempIdx ].energy;
421  };
422 
423  //LOG_INFO << "VVV g)" << endm;
424 
425 
426  //LOG_INFO << "fff " << leftEnergy << ' ' << rightEnergy << endm;
427 
428  // now that we know the energies, need to adjust
429  // weights for each of the strips that are in both
430  // clusters
431 
432  // for simplicity, now want pointers to the cluster
433  // according to which energy of the seeds is higher or lower
434  StSimpleCluster_t *lowerClusPtr = &(*clusIter1);
435  StSimpleCluster_t *higherClusPtr = &(*clusIter2);
436 
437  // this probably just a sanity check, as the seeds were
438  // ordered according to energy
439  if( stripArray.strip[ lowerClusPtr->getSeedMember() ].energy >
440  stripArray.strip[ higherClusPtr->getSeedMember() ].energy ){
441 
442  // switch
443  higherClusPtr = &(*clusIter2);
444  lowerClusPtr = &(*clusIter1);
445  };
446 
447  // get references to (not copies of) arrays.
448  TArrayS &lowerMemberArray = lowerClusPtr->getMemberArray();
449  TArrayF &lowerWeightArray = lowerClusPtr->getWeightArray();
450  TArrayS &higherMemberArray = higherClusPtr->getMemberArray();
451  TArrayF &higherWeightArray = higherClusPtr->getWeightArray();
452 
453  // precompute weights
454  Float_t sumOfEnergy = leftEnergy + rightEnergy;
455  Float_t lowerWeight = ( lowerClusPtr == leftClusPtr ? leftEnergy : rightEnergy ) / sumOfEnergy;
456  Float_t higherWeight = ( lowerClusPtr == leftClusPtr ? rightEnergy : leftEnergy ) / sumOfEnergy;
457 
458  //LOG_INFO << "VVV f)" << endm;
459 
460  // iterate over strips in the cluster with lower seed energy.
461  for( Int_t i=0; i<lowerMemberArray.GetSize(); ++i ){
462  //LOG_INFO << "Lower member " << i << ", index " << lowerMemberArray[i] << endm;
463 
464  // check if shares with the other cluster
465  if( mFirstClusterIDForEachStrip[ lowerMemberArray[i] ] == higherClusPtr->getID() ){
466  // adjust weight
467  lowerWeightArray[i] = lowerWeight;
468 
469  // reset the "first" cluster for the strip to be this cluster
470  // as a flag for the other cluster
471  mFirstClusterIDForEachStrip[ lowerMemberArray[i] ] = lowerClusPtr->getID();
472  };
473 
474  //LOG_INFO << "fff --> L index " << lowerMemberArray[i] << " setting weight to " << lowerWeightArray[i] << endm;
475  };
476 
477  //LOG_INFO << "VVV g)" << endm;
478 
479  // iterate over strips in the cluster with the higher seed energy
480  for( Int_t i=0; i<higherMemberArray.GetSize(); ++i ){
481  //LOG_INFO << "Higher member " << i << ", index " << lowerMemberArray[i] << endm;
482 
483  // check if shares with the other cluster
484  if( mFirstClusterIDForEachStrip[ higherMemberArray[i] ] == lowerClusPtr->getID() ){
485  // adjust weight
486  higherWeightArray[i] = higherWeight;
487 
488  // reset the "first" cluster for the strip back to the real "first"
489  mFirstClusterIDForEachStrip[ higherMemberArray[i] ] = higherClusPtr->getID();
490  };
491 
492  //LOG_INFO << "fff --> H index " << higherMemberArray[i] << " setting weight to " << higherWeightArray[i] << endm;
493 
494  };
495  // end check whether seed strips are close enough to cause clusters to overlap
496 
497  //LOG_INFO << "VVV f)" << endm;
498 
499  };
500  // end inner loop over clusters
501  };
502  // end outer loop over clusters
503  };
504  // end check whether to apply energy splitting
505  };
506 
507  //LOG_INFO << "VVV g)" << endm;
508 
509 
510  //LOG_INFO << "-----> Computing SMD energy per cluster <-----" << endm;
511 
512  // compute energy and mean per cluster
513  StSimpleClusterVec_t::iterator clusIter = clusterVec.begin();
514 
515  Int_t ierr = kStOK;
516  for( clusIter = clusterVec.begin(); clusIter != clusterVec.end() && !ierr; ++clusIter ){
517 
518  Float_t E = 0;
519  Float_t mean = 0;
520 
521  TArrayS &memberArray = clusIter->getMemberArray();
522  TArrayF &weightArray = clusIter->getWeightArray();
523 
524  if( memberArray.GetSize() != weightArray.GetSize() ){
525  LOG_FATAL << "SANITY CHECK FAILURE IN StEEmcStripClusterFinderIU.cxx, line " << __LINE__ << endm;
526  ierr = kStFatal;
527  };
528 
529  //LOG_INFO << "ggg Cluster with seed " << clusIter->getSeedMember() << endm;
530 
531  if( !ierr )
532  for( Int_t i = 0; i < memberArray.GetSize(); ++i ){
533  Float_t stripE = stripArray.strip[ memberArray[ i ] ].energy;
534  if( stripE > 0 && !stripArray.strip[ memberArray[ i ] ].fail ){
535 
536  Float_t thisE = weightArray[i]*stripE;
537  E += thisE;
538  mean += memberArray[i] * thisE;
539 
540  //LOG_INFO << "ggg " << mStripPtrArray[ memberArray[i ] ]->index()
541  // << " E += " << weightArray[i] << " * " << mStripPtrArray[ memberArray[ i ] ]->energy()
542  // << " = " << weightArray[i]*mStripPtrArray[ memberArray[ i ] ]->energy() << endm;
543  };
544  };
545  clusIter->setEnergy( E );
546  clusIter->setMeanX( E > 0 ? mean/E : memberArray[ 0 ] + 0.5 );
547 
548  //LOG_INFO << "-----> layer = " << mLayer << ", SMD cluster: " << *clusIter << endm;
549  };
550 
551  return kStOK;
552 };
553 
554 Bool_t StEEmcStripClusterFinderIU_t::energyGreaterThan( const EEmcElement_t *s1, const EEmcElement_t *s2 ){
555  return s1->energy > s2->energy;
556 };
557 
558 ClassImp( StEEmcStripClusterFinderIU_t );
559 
560 /*
561  * $Id: StEEmcStripClusterFinderIU.cxx,v 1.1 2012/11/26 19:05:55 sgliske Exp $
562  * $Log: StEEmcStripClusterFinderIU.cxx,v $
563  * Revision 1.1 2012/11/26 19:05:55 sgliske
564  * moved from offline/users/sgliske/StRoot/StEEmcPool/StEEmcHitMaker to StRoot/StEEmcPool/StEEmcHitMaker
565  *
566  *
567  */
virtual void clear()
clear between events
virtual Int_t find(const ESmdLayer_t &smdLayer, StSimpleClusterVec_t &cluster)
find some clusters
Definition: Stypes.h:40