StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
StFttClusterMaker.cxx
1 /***************************************************************************
2  *
3  * $Id: StFttClusterMaker.cxx,v 1.4 2019/03/08 18:45:40 fseck Exp $
4  *
5  * Author: Florian Seck, April 2018
6  ***************************************************************************
7  *
8  * Description: StFttClusterMaker - class to fill the StEvent from DAQ reader:
9  * unpack raw data & save StETofHeader & StETofDigis in StETofCollection
10  *
11  ***************************************************************************/
12 #include <vector>
13 #include <set>
14 #include <map>
15 #include <array>
16 #include <algorithm> // std::is_sorted
17 
18 
19 #include "StEvent.h"
20 #include "StEnumerations.h"
21 
22 #include "StFttClusterMaker.h"
23 
24 
25 #include "StEvent/StFttRawHit.h"
26 #include "StEvent/StFttCluster.h"
27 #include "StEvent/StEvent.h"
28 #include "StEvent/StFttCollection.h"
29 
30 #include "StFttDbMaker/StFttDb.h"
31 
32 
33 //_____________________________________________________________
34 StFttClusterMaker::StFttClusterMaker( const char* name )
35 : StMaker( name ),
36  mEvent( 0 ),
37  mRunYear( 0 ),
38  mDebug( false ),
39  mFttDb( nullptr )
40 {
41  LOG_DEBUG << "StFttClusterMaker::ctor" << endm;
42 }
43 
44 //_____________________________________________________________
45 StFttClusterMaker::~StFttClusterMaker()
46 { /* no op */
47 
48 }
49 
50 //_____________________________________________________________
51 Int_t
52 StFttClusterMaker::Init()
53 {
54  LOG_INFO << "StFttClusterMaker::Init" << endm;
55 
56  return kStOk;
57 }
58 
59 //_____________________________________________________________
60 Int_t
61 StFttClusterMaker::InitRun( Int_t runnumber )
62 {
63  mRunYear = ( runnumber + 727000 ) / 1000000 + 1999;
64 
65  LOG_INFO << "runnumber: " << runnumber << " --> year: " << mRunYear << endm;
66 
67  return kStOk;
68 }
69 
70 //_____________________________________________________________
71 Int_t
72 StFttClusterMaker::FinishRun( Int_t runnumber )
73 {
74  return kStOk;
75 }
76 
77 //_____________________________________________________________
78 Int_t
80 {
81  return kStOk;
82 }
83 
84 
85 //_____________________________________________________________
86 Int_t
88 {
89  mEvent = (StEvent*)GetInputDS("StEvent");
90  if(mEvent) {
91  } else {
92  LOG_WARN<<"No StEvent!"<<endm;
93  return kStWarn;
94  }
95  mFttCollection=mEvent->fttCollection();
96  if(!mFttCollection) {
97  LOG_WARN << "No StFttCollection" << endm;
98  return kStOk;
99  }
100 
101  mFttDb = static_cast<StFttDb*>(GetDataSet("fttDb"));
102  assert( mFttDb );
103 
104  LOG_DEBUG << "Found " << mFttCollection->rawHits().size() << " Ftt Hits" << endm;
105  ApplyHardwareMap();
106 
107 
108 
109  // InjectTestData();
110 
111  // next we need to sort the hits into 1D projections
112  // process 1 quadrant (ROB) at a time,
113  // process horizontal, vertical or diagonal strips one at a time
114 
115  // key == ROB
116  std::map< UChar_t, std::vector<StFttRawHit *> > hStripsPerRob; // Horizontal
117  std::map< UChar_t, std::vector<StFttRawHit *> > vStripsPerRob; // Vertical
118  std::map< UChar_t, std::vector<StFttRawHit *> > dhStripsPerRob; // Diagonal on Horizontal
119  std::map< UChar_t, std::vector<StFttRawHit *> > dvStripsPerRob; // Diagonal on Vertical
120 
121  size_t nStripsHit = 0;
122  for ( StFttRawHit* hit : mFttCollection->rawHits() ) {
123  UChar_t rob = mFttDb->rob( hit );
124  UChar_t so = mFttDb->orientation( hit );
125 
126  // Apply the time cut
127  if ( !PassTimeCut( hit ) ) continue;
128 
129  if ( kFttHorizontal == so ){
130  hStripsPerRob[ rob ].push_back(hit);
131  nStripsHit++;
132  }
133  if ( kFttVertical == so ){
134  vStripsPerRob[ rob ].push_back(hit);
135  nStripsHit++;
136  }
137  if ( kFttDiagonalH == so ){
138  dhStripsPerRob[ rob ].push_back(hit);
139  nStripsHit++;
140  }
141  if ( kFttDiagonalV == so ){
142  dvStripsPerRob[ rob ].push_back(hit);
143  nStripsHit++;
144  }
145  } // loop on hit
146 
147  size_t nClusters = 0;
148  LOG_DEBUG << "StFttClusterMaker::Make{ nStripsHit = " << nStripsHit << " }" << endm;
149  if ( nStripsHit > 0 ){ // could make more strict?
150  for ( UChar_t iRob = 1; iRob < StFttDb::nRob+1; iRob++ ){
151 
152  auto hClusters = FindClusters( hStripsPerRob[iRob] );
153  // Add them to StEvent
154  for ( StFttCluster * clu : hClusters ){
155  mFttCollection->addCluster( clu );
156  nClusters++;
157  }
158  auto vClusters = FindClusters( vStripsPerRob[iRob] );
159  // Add them to StEvent
160  for ( StFttCluster * clu : vClusters ){
161  mFttCollection->addCluster( clu );
162  nClusters++;
163  }
164  auto hdClusters = FindClusters( dhStripsPerRob[iRob] );
165  // Add them to StEvent
166  for ( StFttCluster * clu : hdClusters ){
167  mFttCollection->addCluster( clu );
168  nClusters++;
169  }
170  auto vdClusters = FindClusters( dvStripsPerRob[iRob] );
171  // Add them to StEvent
172  for ( StFttCluster * clu : vdClusters ){
173  mFttCollection->addCluster( clu );
174  nClusters++;
175  }
176  } // loop on iRob
177  } // nStripsHit
178  LOG_DEBUG << "Found " << nClusters << " clusters this event" << endm;
179 
180  return kStOk;
181 } // Make
182 
183 void StFttClusterMaker::InjectTestData(){
184  mFttCollection->rawHits().clear();
185 
186  StFttRawHit *hit = new StFttRawHit( 1, 1, 1, 1, 1, 55, 1, 1, 0 );
187  hit->setMapping( 1, 1, 1, 23, kFttHorizontal ); // LEFT 2
188  mFttCollection->addRawHit( hit );
189 
190  hit = new StFttRawHit( 1, 1, 1, 1, 1, 90, 1, 1, 0 );
191  hit->setMapping( 1, 1, 1, 24, kFttHorizontal ); // LEFT 1
192  mFttCollection->addRawHit( hit );
193 
194  hit = new StFttRawHit( 1, 1, 1, 1, 1, 60, 1, 1, 0 );
195  hit->setMapping( 1, 1, 1, 27, kFttHorizontal );
196  mFttCollection->addRawHit( hit );
197 
198  hit = new StFttRawHit( 1, 1, 1, 1, 1, 95, 1, 1, 0 );
199  hit->setMapping( 1, 1, 1, 25, kFttHorizontal ); // CENTER
200  mFttCollection->addRawHit( hit );
201 
202  hit = new StFttRawHit( 1, 1, 1, 1, 1, 93, 1, 1, 0 );
203  hit->setMapping( 1, 1, 1, 26, kFttHorizontal );
204  mFttCollection->addRawHit( hit );
205 
206  hit = new StFttRawHit( 1, 1, 1, 1, 1, 19, 1, 1, 0 );
207  hit->setMapping( 1, 1, 1, 28, kFttHorizontal );
208  mFttCollection->addRawHit( hit );
209 } // InjectTestData
210 
211 
212 bool StFttClusterMaker::PassTimeCut( StFttRawHit * hit ){
213  int time_cut0 = -999;
214  int time_cut1 = 999;
215  int time_cutm = 0;
216  // in principle it could vary VMM to VMM;
217  mFttDb->getTimeCut(hit, time_cutm, time_cut0, time_cut1);
218  if ( time_cutm == 0 ) // default, cut on bunch crossing
219  return (hit->time() <= time_cut1 && hit->time() >= time_cut0);
220 
221  // cut on timebin
222  return (hit->tb() <= time_cut1 && hit->tb() >= time_cut0);
223 }
224 
225 
226 StFttRawHit * StFttClusterMaker::FindMaxAdc( std::vector<StFttRawHit *> hits, size_t &pos ){
227  auto itMax = std::max_element(hits.begin(),
228  hits.end(),
229  [](const StFttRawHit* a,const StFttRawHit* b) { return a->adc() < b->adc(); });
230 
231  pos = (itMax - hits.begin());
232  if ( itMax == hits.end() ) return nullptr;
233  return *itMax;
234 }
235 
236 void StFttClusterMaker::SearchClusterEdges( std::vector< StFttRawHit * > hits,
237  size_t start, // start index at MaxADC
238  size_t &left, size_t &right ){
239  // set initial values
240  left = start;
241  right = start;
242 
243  auto lastHitLeft = hits[start];
244  auto lastHitRight = hits[start];
245 
246  bool searchRight = true;
247  bool searchLeft = true;
248 
249  StFttRawHit *hitLeft = nullptr, *hitRight = nullptr;
250 
251  while ( searchRight || searchLeft ){
252  LOG_DEBUG << "LEFT: " << left << ", RIGHT: " << right << ", start = " << start << ", size=" << hits.size() << endm;
253  if ( searchRight ){
254  if ( right == hits.size() || right == hits.size() - 1 ){
255  searchRight = false;
256  }
257  else {
258 
259  hitRight = hits[right+1];
260  if ( hitRight->adc() > lastHitRight->adc() || hitRight->adc() < GetThresholdFor( hitRight ) ){
261  searchRight = false;
262  }
263  if ( hitRight->row() != lastHitRight->row() || abs( hitRight->strip() - lastHitRight->strip() ) > 1 ){
264  searchRight = false;
265  }
266 
267  if ( searchRight ){
268  right ++;
269  lastHitRight = hitRight;
270  }
271  } // right < size - 1
272  } // searchRight
273 
274  if ( searchLeft ){
275  if ( left == 0 ){
276  searchLeft = false;
277  } else {
278  hitLeft = hits[left-1];
279  if ( hitLeft->adc() > lastHitLeft->adc() || hitLeft->adc() < GetThresholdFor( hitLeft ) ){
280  searchLeft = false;
281  }
282  if ( hitLeft->row() != lastHitLeft->row() || abs( hitLeft->strip() - lastHitLeft->strip() ) > 1 ){
283  searchLeft = false;
284  }
285 
286  if (searchLeft){
287  left--;
288  lastHitLeft = hitLeft;
289  }
290  } // left != 0
291  } // searchLeft
292  } // while searching
293 } // SearchClusterEdges
294 
295 
296 void StFttClusterMaker::CalculateClusterInfo( StFttCluster * clu ){
297 
298  clu->setNStrips( clu->rawHits().size() );
299 
300  // Compute the sumAdc, strip gravity center, and variance
301  float m0Sum = 0;
302  float m1Sum = 0;
303  float m2Sum = 0;
304 
305  std::for_each (clu->rawHits().begin(), clu->rawHits().end(), [&](const StFttRawHit *h) {
306  float x = ( h->strip() * 3.2 - 1.6 ); // replace with CONST
307 
308  m0Sum += h->adc();
309  m1Sum += (h->adc() * x);
310  m2Sum += ( h->adc() * x * x );
311  });
312 
313  if ( mDebug ) {
314  LOG_INFO << "m0Sum = " << m0Sum << endm;
315  LOG_INFO << "m1Sum = " << m1Sum << endm;
316  LOG_INFO << "m2Sum = " << m2Sum << endm;
317  }
318 
319  // m0Sum = sumAdc
320  // m1Sum / m0Sum = gravity center (1st moment)
321  // m2Sum = accumulated variance (2nd moment)
322 
323  clu->setSumAdc( m0Sum );
324  clu->setX( m1Sum / m0Sum );
325  float var = (m2Sum - m1Sum*m1Sum / m0Sum) / m0Sum;
326  clu->setSigma( sqrt( var ) );
327 }
328 
329 
330 
331 std::vector<StFttCluster*> StFttClusterMaker::FindClusters( std::vector< StFttRawHit * > hits ){
332  std::vector<StFttCluster*> clusters;
333 
334  /* early data (i.e. cosmic data pre dec 10 2021)
335  * had duplicates where the hits are identical except
336  * a different tb. Tonko fixed at some point
337  * So this could be wrapped in a run range block, but
338  * does no harm.
339  */
340  const bool dedup = false;
341  if ( dedup ){
342  auto cmp = [](StFttRawHit* a, StFttRawHit* b) {
343 
344  return a->plane() < b->plane() ||
345  a->quadrant() < b->quadrant() ||
346  a->row() < b->row() ||
347  a->strip() < b->strip() ||
348  a->orientation() < b->orientation();
349  };
350 
351  // NOTE according to SO this is faster than using ctor
352  set<StFttRawHit*, decltype(cmp)> s(cmp);
353  unsigned size = hits.size();
354  for( auto h : hits ) s.insert( h );
355  hits.assign( s.begin(), s.end() );
356  }
357 
358  // Sort the hits by row and strip
359  sort(hits.begin(), hits.end(), [](const StFttRawHit * a, const StFttRawHit * b) -> bool {
360  size_t indexA = a->orientation() + StFttDb::nStripOrientations * ( a->strip() + a->row() * StFttDb::maxStripPerRow);
361  size_t indexB = b->orientation() + StFttDb::nStripOrientations * ( b->strip() + b->row() * StFttDb::maxStripPerRow);
362  return indexA < indexB;
363  });
364 
365  if ( mDebug ) {
366  LOG_INFO << "We have " << hits.size() << " hits after removing duplicates" << endm;
367  }
368 
369 
370  // Get the max ADC hit in this projection
371  size_t anchor = hits.size()+1;
372  auto maxAdcHit = FindMaxAdc( hits, anchor );
373 
374  // Loop as long as there is at least 1 hit left
375  while ( maxAdcHit ){
376  StFttCluster * clu = new StFttCluster();
377 
378  if ( Debug() ){
379  LOG_DEBUG << "CLUSTER FIND START WITH HITS:" << endm;
380  size_t i = 0;
381  for ( auto *h : hits ){
382  LOG_DEBUG << "[" << i << "]" << *h;
383  i++;
384  }
385  }
386 
387  // Set cluster "location" from max ADC hit
388  clu->setPlane ( maxAdcHit->plane ( ) );
389  clu->setQuadrant ( maxAdcHit->quadrant ( ) );
390  clu->setRow ( maxAdcHit->row ( ) );
391  clu->setOrientation ( maxAdcHit->orientation ( ) );
392 
393  // Now find the cluster edges
394  size_t left = anchor, right = anchor;
395  SearchClusterEdges( hits, anchor, left, right);
396 
397  LOG_DEBUG << "Cluster points ( " << left << ", " << anchor << ", " << right << " )" << endm;
398 
399 
400  // OK now add these hits to the cluster
401  for ( size_t i = left; i < right + 1; i++ ){
402  clu->addRawHit( hits[i] );
403  }
404 
405  // Compute cluster information from the added hits
406  CalculateClusterInfo( clu );
407 
408  if (mDebug){
409  LOG_INFO << *clu << endm;;
410  }
411  clusters.push_back( clu );
412 
413  // Now erase all hits from this cluster so that we can move on to find the next one
414  hits.erase( hits.begin() + left, hits.begin() + right + 1 );
415  maxAdcHit = FindMaxAdc( hits, anchor );
416  } // while maxAdcHit
417  return clusters;
418 }
419 
420 
421 
422 void StFttClusterMaker::ApplyHardwareMap(){
423  for ( StFttRawHit* rawHit : mFttCollection->rawHits() ) {
424  mFttDb->hardwareMap( rawHit );
425  }
426 
427 }
428 
Definition: Stypes.h:42
Definition: Stypes.h:41