Class Reference for E1039 Core & Analysis Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
EventReducer.cxx
Go to the documentation of this file.
1 #include <iostream>
2 #include <stdlib.h>
3 
4 #include "EventReducer.h"
5 
6 EventReducer::EventReducer(TString options) : afterhit(false), hodomask(false), outoftime(false), decluster(false), mergehodo(false), triggermask(false), sagitta(false), hough(false), externalpar(false), realization(false), difnim(false)
7 {
8  //parse the reducer setup
9  options.ToLower();
10  if(options.Contains("a")) afterhit = true;
11  if(options.Contains("h")) hodomask = true;
12  if(options.Contains("o")) outoftime = true;
13  if(options.Contains("c")) decluster = true;
14  if(options.Contains("m")) mergehodo = true;
15  if(options.Contains("t")) triggermask = true;
16  if(options.Contains("s")) sagitta = true;
17  if(options.Contains("g")) hough = true;
18  if(options.Contains("e")) externalpar = true;
19  if(options.Contains("r")) realization = true;
20  if(options.Contains("n")) difnim = true;
21 
22  rc = recoConsts::instance();
23  timeOffset = rc->get_DoubleFlag("TDCTimeOffset");
24  SAGITTA_TARGET_CENTER = rc->get_DoubleFlag("SAGITTA_TARGET_CENTER");
25  SAGITTA_TARGET_WIDTH = rc->get_DoubleFlag("SAGITTA_TARGET_WIDTH");
26  SAGITTA_DUMP_CENTER = rc->get_DoubleFlag("SAGITTA_DUMP_CENTER");
27  SAGITTA_TARGET_WIDTH = rc->get_DoubleFlag("SAGITTA_DUMP_WIDTH");
28  Z_TARGET = rc->get_DoubleFlag("Z_TARGET");
29  Z_DUMP = rc->get_DoubleFlag("Z_DUMP");
30 
31  TX_MAX = rc->get_DoubleFlag("TX_MAX");
32  TY_MAX = rc->get_DoubleFlag("TY_MAX");
33  USE_V1495_HIT = rc->get_BoolFlag("USE_V1495_HIT");
34  USE_TWTDC_HIT = rc->get_BoolFlag("USE_TWTDC_HIT");
35 
36  chamEff = 0.94;
37  chamResol = 0.04;
38 
39  //Screen output for all the methods enabled
40  if(afterhit) std::cout << "EventReducer: after-pulse removal enabled. " << std::endl;
41  if(hodomask) std::cout << "EventReducer: hodoscope masking enabled. " << std::endl;
42  if(outoftime) std::cout << "EventReducer: out-of-time hits removal enabled. " << std::endl;
43  if(decluster) std::cout << "EventReducer: hit cluster removal enabled. " << std::endl;
44  if(mergehodo) std::cout << "EventReducer: v1495 hits will be merged with TW-TDC hits. " << std::endl;
45  if(triggermask) std::cout << "EventReducer: trigger road masking enabled. " << std::endl;
46  if(sagitta) std::cout << "EventReducer: sagitta reducer enabled. " << std::endl;
47  if(hough) std::cout << "EventReducer: hough transform reducer enabled. " << std::endl;
48  if(externalpar) std::cout << "EventReducer: will reset the alignment/calibration parameters. " << std::endl;
49  if(realization) std::cout << "EventReducer: realization enabled. " << std::endl;
50  if(difnim) std::cout << "EventReducer: trigger masking will be disabled in NIM events. " << std::endl;
51  if(fabs(timeOffset) > 0.01) std::cout << "EventReducer: " << timeOffset << " ns will be added to tdcTime. " << std::endl;
52 
53  //initialize services
54  p_geomSvc = GeomSvc::instance();
55  if(triggermask)
56  {
57  p_triggerAna = new TriggerAnalyzer();
58  p_triggerAna->init();
59  p_triggerAna->buildTriggerTree();
60  }
61 
62  if(hodomask) initHodoMaskLUT();
63 
64  //set random seed
65  rndm.SetSeed(0);
66 }
67 
69 {
70  if(triggermask)
71  {
72  delete p_triggerAna;
73  }
74 }
75 
77 {
78  int nHits_before = rawEvent->getNChamberHitsAll();
79 
80  //temporarily disable trigger road masking if this event is not fired by any MATRIX triggers
81  bool triggermask_local = triggermask;
82  if(!(rc->get_BoolFlag("MC_MODE") || rawEvent->isFPGATriggered()))
83  {
84  triggermask_local = false;
85  }
86 
87  //dump the vector of hits from SRawEvent to a list first
88  hitlist.clear();
89  hodohitlist.clear();
90  for(std::vector<Hit>::iterator iter = rawEvent->fAllHits.begin(); iter != rawEvent->fAllHits.end(); ++iter)
91  {
92  if(outoftime && (!iter->isInTime())) continue;
93 
94  if(iter->detectorID <= nChamberPlanes) //chamber hits
95  {
96  if(realization && rndm.Rndm() > chamEff) continue;
97  //if(hodomask && (!iter->isHodoMask())) continue;
98  //if(triggermask && (!iter->isTriggerMask())) continue;
99  }
100  else if(iter->detectorID > nChamberPlanes && iter->detectorID <= nChamberPlanes+nHodoPlanes)
101  {
102  // if trigger masking is enabled, all the X hodos are discarded
103  if(triggermask_local && p_geomSvc->getPlaneType(iter->detectorID) == 1) continue;
104  }
105 
106  if(externalpar)
107  {
108  iter->pos = p_geomSvc->getMeasurement(iter->detectorID, iter->elementID);
109  iter->driftDistance = p_geomSvc->getDriftDistance(iter->detectorID, iter->tdcTime + timeOffset); // this is OK because hodoscopes don't have R-T curve anyways
110  //iter->setInTime(p_geomSvc->isInTime(iter->detectorID, iter->tdcTime));
111  }
112 
113  if(realization && iter->detectorID <= nChamberPlanes) iter->driftDistance += rndm.Gaus(0., chamResol);
114 
115  if(iter->detectorID >= nChamberPlanes+1 && iter->detectorID <= nChamberPlanes+nHodoPlanes)
116  {
117  hodohitlist.push_back(*iter);
118  }
119  else
120  {
121  hitlist.push_back(*iter);
122  }
123  }
124 
125  if(mergehodo)
126  {
127  for(std::vector<Hit>::iterator iter = rawEvent->fTriggerHits.begin(); iter != rawEvent->fTriggerHits.end(); ++iter)
128  {
129  if(triggermask_local && p_geomSvc->getPlaneType(iter->detectorID) == 1) continue;
130  hodohitlist.push_back(*iter);
131  }
132  }
133 
134  // manully create the X-hodo hits by the trigger roads
135  if(triggermask_local) p_triggerAna->trimEvent(rawEvent, hodohitlist, mergehodo || USE_V1495_HIT, mergehodo || USE_TWTDC_HIT);
136 
137  //apply hodoscope mask
138  hodohitlist.sort();
139  if(hodomask) hodoscopeMask(hitlist, hodohitlist);
140 
141  //Remove after hits
142  hitlist.sort();
143  hitlist.merge(hodohitlist);
144  if(afterhit) hitlist.unique();
145 
146  //Remove hit clusters
147  if(decluster) deClusterize();
148 
149  //Remove the hits by sagitta ratio
150  if(sagitta) sagittaReducer();
151 
152  //Push everything back to SRawEvent
153  rawEvent->fAllHits.clear();
154  rawEvent->fAllHits.assign(hitlist.begin(), hitlist.end());
155 
156  rawEvent->reIndex();
157  return nHits_before - rawEvent->getNChamberHitsAll();
158 }
159 
161 {
162  //find index for D1, D2, and D3
163  int nHits_D1 = 0;
164  int nHits_D2 = 0;
165  int nHits_D3 = 0;
166  int detectorID_st1_max = 12;
167  int detectorID_st2_max = 18;
168 
169  //hitlist here is assumed to be sorted of course
170  for(std::list<Hit>::iterator iter = hitlist.begin(); iter != hitlist.end(); ++iter)
171  {
172  if(iter->detectorID > nChamberPlanes) break;
173  if(iter->detectorID <= detectorID_st1_max)
174  {
175  ++nHits_D1;
176  }
177  else if(iter->detectorID <= detectorID_st2_max)
178  {
179  ++nHits_D2;
180  }
181  else
182  {
183  ++nHits_D3;
184  }
185  }
186  int idx_D1 = nHits_D1;
187  int idx_D2 = nHits_D1 + nHits_D2;
188  int idx_D3 = nHits_D1 + nHits_D2 + nHits_D3;
189 
190  //Loop over all hits
191  std::vector<Hit> hitTemp;
192  hitTemp.assign(hitlist.begin(), hitlist.end());
193 
194  std::vector<int> flag(hitTemp.size(), -1);
195  for(int i = idx_D2; i < idx_D3; ++i)
196  {
197  double z3 = p_geomSvc->getPlanePosition(hitTemp[i].detectorID);
198  double slope_target = hitTemp[i].pos/(z3 - Z_TARGET);
199  double slope_dump = hitTemp[i].pos/(z3 - Z_DUMP);
200  for(int j = idx_D1; j < idx_D2; ++j)
201  {
202  if(p_geomSvc->getPlaneType(hitTemp[i].detectorID) != p_geomSvc->getPlaneType(hitTemp[j].detectorID)) continue;
203 
204  double z2 = p_geomSvc->getPlanePosition(hitTemp[j].detectorID);
205  if(fabs((hitTemp[i].pos - hitTemp[j].pos)/(z2 - z3)) > TX_MAX) continue;
206  double s2_target = hitTemp[j].pos - slope_target*(z2 - Z_TARGET);
207  double s2_dump = hitTemp[j].pos - slope_dump*(z2 - Z_DUMP);
208 
209  for(int k = 0; k < idx_D1; ++k)
210  {
211  if(p_geomSvc->getPlaneType(hitTemp[i].detectorID) != p_geomSvc->getPlaneType(hitTemp[k].detectorID)) continue;
212  if(flag[i] > 0 && flag[j] > 0 && flag[k] > 0) continue;
213 
214  double z1 = p_geomSvc->getPlanePosition(hitTemp[k].detectorID);
215  double pos_exp_target = SAGITTA_TARGET_CENTER*s2_target + slope_target*(z1 - Z_TARGET);
216  double pos_exp_dump = SAGITTA_DUMP_CENTER*s2_dump + slope_dump*(z1 - Z_DUMP);
217  double win_target = fabs(s2_target*SAGITTA_TARGET_WIDTH);
218  double win_dump = fabs(s2_dump*SAGITTA_DUMP_WIDTH);
219 
220  double p_min = std::min(pos_exp_target - win_target, pos_exp_dump - win_dump);
221  double p_max = std::max(pos_exp_target + win_target, pos_exp_dump + win_dump);
222 
223  if(hitTemp[k].pos > p_min && hitTemp[k].pos < p_max)
224  {
225  flag[i] = 1;
226  flag[j] = 1;
227  flag[k] = 1;
228  }
229  }
230  }
231  }
232 
233  int idx = 0;
234  for(std::list<Hit>::iterator iter = hitlist.begin(); iter != hitlist.end(); )
235  {
236  if(flag[idx] < 0)
237  {
238  iter = hitlist.erase(iter);
239  }
240  else
241  {
242  ++iter;
243  }
244 
245  ++idx;
246  if(idx >= idx_D3) break;
247  }
248 }
249 
251 {
252  std::vector<std::list<Hit>::iterator> cluster;
253  cluster.clear();
254  for(std::list<Hit>::iterator hit = hitlist.begin(); hit != hitlist.end(); ++hit)
255  {
256  //if we already reached the hodo part, stop
257  if(hit->detectorID > nChamberPlanes) break;
258 
259  if(cluster.size() == 0)
260  {
261  cluster.push_back(hit);
262  }
263  else
264  {
265  if(hit->detectorID != cluster.back()->detectorID)
266  {
267  processCluster(cluster);
268  cluster.push_back(hit);
269  }
270  else if(hit->elementID - cluster.back()->elementID > 1)
271  {
272  processCluster(cluster);
273  cluster.push_back(hit);
274  }
275  else
276  {
277  cluster.push_back(hit);
278  }
279  }
280  }
281 }
282 
283 void EventReducer::processCluster(std::vector<std::list<Hit>::iterator>& cluster)
284 {
285  unsigned int clusterSize = cluster.size();
286 
287  //size-2 clusters, retain the hit with smaller driftDistance
288  if(clusterSize == 2)
289  {
290  double w_max = 0.9*0.5*(cluster.back()->pos - cluster.front()->pos);
291  double w_min = w_max/9.*4.; //double w_min = 0.6*0.5*(cluster.back()->pos - cluster.front()->pos);
292 
293  if((cluster.front()->driftDistance > w_max && cluster.back()->driftDistance > w_min) || (cluster.front()->driftDistance > w_min && cluster.back()->driftDistance > w_max))
294  {
295  cluster.front()->driftDistance > cluster.back()->driftDistance ? hitlist.erase(cluster.front()) : hitlist.erase(cluster.back());
296  }
297  else if(fabs(cluster.front()->tdcTime - cluster.back()->tdcTime) < 8. && cluster.front()->detectorID >= 19 && cluster.front()->detectorID <= 24)
298  {
299  hitlist.erase(cluster.front());
300  hitlist.erase(cluster.back());
301  }
302  }
303 
304  //size-larger-than-3, discard entirely
305  if(clusterSize >= 3)
306  {
307  double dt_mean = 0.;
308  for(unsigned int i = 1; i < clusterSize; ++i)
309  {
310  dt_mean += fabs(cluster[i]->tdcTime - cluster[i-1]->tdcTime);
311  }
312  dt_mean = dt_mean/(clusterSize - 1);
313 
314  if(dt_mean < 10.)
315  {
316  //electric noise, discard them all
317  for(unsigned int i = 0; i < clusterSize; ++i)
318  {
319  hitlist.erase(cluster[i]);
320  }
321  }
322  else
323  {
324  /*
325  double dt_rms = 0.;
326  for(unsigned int i = 1; i < clusterSize; ++i)
327  {
328  double dt = fabs(cluster[i]->tdcTime - cluster[i-1]->tdcTime);
329  dt_rms += ((dt - dt_mean)*(dt - dt_mean));
330  }
331  dt_rms = sqrt(dt_rms/(clusterSize - 1));
332 
333  //delta ray, keep the first and last
334  if(dt_rms < 5.)*/
335  {
336  for(unsigned int i = 1; i < clusterSize - 1; ++i)
337  {
338  hitlist.erase(cluster[i]);
339  }
340  }
341  }
342  }
343 
344  cluster.clear();
345 }
346 
348 {
349  h2celementID_lo.clear();
350  h2celementID_hi.clear();
351 
352  TString hodoNames[8] = {"H1B", "H1T", "H2B", "H2T", "H3B", "H3T", "H4B", "H4T"};
353  int hodoIDs[8];
354  for(int i = 0; i < 8; ++i) hodoIDs[i] = p_geomSvc->getDetectorID(hodoNames[i].Data());
355 
356  int chamIDs[8][12] = { {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12},
357  {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12},
358  {13, 14, 15, 16, 17, 18, 0, 0, 0, 0, 0, 0},
359  {13, 14, 15, 16, 17, 18, 0, 0, 0, 0, 0, 0},
360  {0, 0, 0, 0, 0, 0, 25, 26, 27, 28, 29, 30},
361  {19, 20, 21, 22, 23, 24, 0, 0, 0, 0, 0, 0},
362  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
363  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
364 
365  for(int i = 0; i < 8; ++i)
366  {
367  int nPaddles = p_geomSvc->getPlaneNElements(hodoIDs[i]);
368  for(int j = 1; j <= nPaddles; ++j)
369  {
370  //for each paddle, there is a group of 6/12 chamber planes to work with
371  int uniqueID = hodoIDs[i]*1000 + j;
372 
373  //get the four corners of the paddle
374  double z0, x0_min, x0_max, y0_min, y0_max;
375  z0 = p_geomSvc->getPlanePosition(hodoIDs[i]);
376  p_geomSvc->get2DBoxSize(hodoIDs[i], j, x0_min, x0_max, y0_min, y0_max);
377 
378  for(int k = 0; k < 12; ++k)
379  {
380  if(chamIDs[i][k] < 1) continue;
381 
382  //project the box to the chamber plane with maximum xz/yz slope
383  double z = p_geomSvc->getPlanePosition(chamIDs[i][k]);
384  double x_min = x0_min - fabs(TX_MAX*(z - z0));
385  double x_max = x0_max + fabs(TX_MAX*(z - z0));
386  double y_min = y0_min - fabs(TY_MAX*(z - z0));
387  double y_max = y0_max + fabs(TY_MAX*(z - z0));
388 
389  int elementID_lo = p_geomSvc->getPlaneNElements(chamIDs[i][k]);;
390  int elementID_hi = 0;
391  if(p_geomSvc->getPlaneType(chamIDs[i][k]) == 1)
392  {
393  elementID_lo = p_geomSvc->getExpElementID(chamIDs[i][k], x_min);
394  elementID_hi = p_geomSvc->getExpElementID(chamIDs[i][k], x_max);
395  }
396  else
397  {
398  for(int m = 1; m <= p_geomSvc->getPlaneNElements(chamIDs[i][k]); ++m)
399  {
400  double x1, y1, x2, y2;
401  p_geomSvc->getWireEndPoints(chamIDs[i][k], m, x1, x2, y1, y2);
402 
403  if(!lineCrossing(x_min, y_min, x_min, y_max, x1, y1, x2, y2) &&
404  !lineCrossing(x_max, y_min, x_max, y_max, x1, y1, x2, y2)) continue;
405 
406  if(m < elementID_lo) elementID_lo = m;
407  if(m > elementID_hi) elementID_hi = m;
408  }
409  }
410 
411  elementID_lo -= 2;
412  if(elementID_lo < 1) elementID_lo = 1;
413  elementID_hi += 2;
414  if(elementID_hi > p_geomSvc->getPlaneNElements(chamIDs[i][k])) elementID_hi = p_geomSvc->getPlaneNElements(chamIDs[i][k]);
415 
416  h2celementID_lo[uniqueID].push_back(chamIDs[i][k]*1000 + elementID_lo);
417  h2celementID_hi[uniqueID].push_back(chamIDs[i][k]*1000 + elementID_hi);
418  }
419  }
420  }
421 
422  //reverse the LUT
423  c2helementIDs.clear();
424  for(LUT::iterator iter = h2celementID_lo.begin(); iter != h2celementID_lo.end(); ++iter)
425  {
426  int hodoUID = iter->first;
427  for(unsigned int i = 0; i < h2celementID_lo[hodoUID].size(); ++i)
428  {
429  int chamUID_lo = iter->second[i];
430  int chamUID_hi = h2celementID_hi[hodoUID][i];
431  for(int j = chamUID_lo; j <= chamUID_hi; ++j)
432  {
433  c2helementIDs[j].push_back(hodoUID);
434  }
435  }
436  }
437 }
438 
439 void EventReducer::hodoscopeMask(std::list<Hit>& chamberhits, std::list<Hit>& hodohits)
440 {
441  for(std::list<Hit>::iterator iter = chamberhits.begin(); iter != chamberhits.end(); )
442  {
443  if(iter->detectorID > nChamberPlanes)
444  {
445  ++iter;
446  continue;
447  }
448 
449  int uniqueID = iter->uniqueID();
450 
451  bool masked = false;
452  for(std::vector<int>::iterator jter = c2helementIDs[uniqueID].begin(); jter != c2helementIDs[uniqueID].end(); ++jter)
453  {
454  if(std::find(hodohits.begin(), hodohits.end(), Hit(*jter)) != hodohits.end())
455  {
456  masked = true;
457  break;
458  }
459  }
460 
461  if(masked)
462  {
463  ++iter;
464  }
465  else
466  {
467  iter = chamberhits.erase(iter);
468  }
469  }
470 }
471 
472 bool EventReducer::lineCrossing(double x1, double y1, double x2, double y2,
473  double x3, double y3, double x4, double y4)
474 {
475  double tc = (x1 - x2)*(y3 - y1) + (y1 - y2)*(x1 - x3);
476  double td = (x1 - x2)*(y4 - y1) + (y1 - y2)*(x1 - x4);
477 
478  return tc*td < 0;
479 }
virtual bool get_BoolFlag(const std::string &name) const
Definition: PHFlag.cc:151
void trimEvent(SRawEvent *rawEvent, std::list< Hit > &hitlist, bool USE_TRIGGER_HIT, bool USE_HIT)
virtual double get_DoubleFlag(const std::string &name) const
Definition: PHFlag.cc:49
void get2DBoxSize(int detectorID, int elementID, double &x_min, double &x_max, double &y_min, double &y_max)
Definition: GeomSvc.cxx:830
static recoConsts * instance()
Definition: recoConsts.cc:7
#define nHodoPlanes
Definition: GlobalConsts.h:7
void sagittaReducer()
bool init(std::string fileName, double cut_td=0., double cut_gun=1E8)
bool lineCrossing(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4)
Definition of hit structure.
Definition: SRawEvent.h:34
void processCluster(std::vector< std::list< Hit >::iterator > &cluster)
EventReducer(TString options)
Definition: EventReducer.cxx:6
void initHodoMaskLUT()
Int_t getNChamberHitsAll()
Definition: SRawEvent.cxx:381
int getPlaneType(int detectorID) const
Definition: GeomSvc.h:223
int reduceEvent(SRawEvent *rawEvent)
void deClusterize()
#define nChamberPlanes
Definition: GlobalConsts.h:6
static GeomSvc * instance()
singlton instance
Definition: GeomSvc.cxx:211
void hodoscopeMask(std::list< Hit > &chamberhits, std::list< Hit > &hodohits)
void reIndex(bool doSort=false)
Reset the number hits on each plane.
Definition: SRawEvent.cxx:559
int getExpElementID(int detectorID, double pos_exp)
Definition: GeomSvc.cxx:807
int getDetectorID(const std::string &detectorName) const
Get the plane position.
Definition: GeomSvc.h:184
int getPlaneNElements(int detectorID)
Definition: GeomSvc.h:208
void getMeasurement(int detectorID, int elementID, double &measurement, double &dmeasurement)
Convert the detectorID and elementID to the actual hit position.
Definition: GeomSvc.cxx:781
void getWireEndPoints(int detectorID, int elementID, double &x_min, double &x_max, double &y_min, double &y_max)
Definition: GeomSvc.cxx:855
double getDriftDistance(int detectorID, double tdcTime)
Definition: GeomSvc.cxx:909
bool isFPGATriggered()
Definition: SRawEvent.cxx:639
double getPlanePosition(int detectorID) const
Definition: GeomSvc.h:197