StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
StFttFastSimMaker.cxx
1 
2 #include "StFttFastSimMaker.h"
3 
4 #include "StEvent/StEvent.h"
5 #include "St_base/StMessMgr.h"
6 
7 #include "StEvent/StRnDHit.h"
8 #include "StEvent/StRnDHitCollection.h"
9 #include "StThreeVectorF.hh"
10 
11 #include "TCanvas.h"
12 #include "TCernLib.h"
13 #include "TH2F.h"
14 #include "TLine.h"
15 #include "TString.h"
16 #include "TVector3.h"
17 #include "tables/St_g2t_fts_hit_Table.h"
18 #include "tables/St_g2t_track_Table.h"
19 #include <array>
20 
21 #include "StarGenerator/UTIL/StarRandom.h"
22 
23 namespace FttGlobal {
24  const bool verbose = false;
25 }
26 
27 StFttFastSimMaker::StFttFastSimMaker(const Char_t *name)
28  : StMaker{name},
29  hGlobalYX(0),
30  hOctantYX(0),
31  hOctantWireYX(0),
32  hOctantStripYX(0),
33  hWireDeltasX(0),
34  hWireDeltasY(0),
35  hStripDeltasX(0),
36  hStripDeltasY(0),
37  hWirePullsX(0),
38  hWirePullsY(0),
39  hStripPullsX(0),
40  hStripPullsY(0),
41  hPointsPullsX(0),
42  hPointsPullsY(0) {}
43 
44 int StFttFastSimMaker::Init() {
45  iEvent = 0;
46 
47  return StMaker::Init();
48 }
49 
51  LOG_DEBUG << "StFttFastSimMaker::Make" << endm;
52 
53  // Get the existing StEvent, or add one if it doesn't exist.
54  StEvent *event = static_cast<StEvent *>(GetDataSet("StEvent"));
55  if (!event) {
56  event = new StEvent;
57  AddData(event);
58  LOG_DEBUG << "Creating StEvent" << endm;
59  }
60 
61  if (0 == event->rndHitCollection()) {
62  event->setRnDHitCollection(new StRnDHitCollection());
63  LOG_DEBUG << "Creating StRnDHitCollection for FTS" << endm;
64  }
65 
66  FillThinGapChambers(event);
67  iEvent++;
68 
69  return kStOk;
70 }
71 
80 void StFttFastSimMaker::GlobalToLocal(float x, float y, int disk, int &quad, float &localX, float &localY) {
81  // quad RECT
82  float qr = -1;
83  float ql = -1;
84  float qb = -1;
85  float qt = -1;
86 
87  QuadBottomLeft(disk, 0, qb, ql);
88  qr = ql + STGC_QUAD_WIDTH;
89  qt = qb + STGC_QUAD_HEIGHT;
90  if (x >= ql && x < qr && y >= qb && y < qt) {
91  quad = 0;
92  localX = x - ql;
93  localY = y - qb;
94  }
95 
96  QuadBottomLeft(disk, 1, qb, ql);
97  qr = ql + STGC_QUAD_WIDTH;
98  qt = qb + STGC_QUAD_HEIGHT;
99  if (x >= ql && x < qr && y >= qb && y < qt) {
100  quad = 1;
101  localX = x - ql;
102  localY = y - qb;
103  }
104  QuadBottomLeft(disk, 2, qb, ql);
105  qr = ql + STGC_QUAD_WIDTH;
106  qt = qb + STGC_QUAD_HEIGHT;
107  if (x >= ql && x < qr && y >= qb && y < qt) {
108  quad = 2;
109  localX = x - ql;
110  localY = y - qb;
111  }
112  QuadBottomLeft(disk, 3, qb, ql);
113  qr = ql + STGC_QUAD_WIDTH;
114  qt = qb + STGC_QUAD_HEIGHT;
115  if (x >= ql && x < qr && y >= qb && y < qt) {
116  quad = 3;
117  localX = x - ql;
118  localY = y - qb;
119  }
120 
121  return;
122 }
123 
124 float StFttFastSimMaker::DiskOffset(int disk) {
125  assert(disk >= 9 && disk <= 12);
126  if (disk == 9)
127  return 10;
128  if (disk == 10)
129  return 11;
130  if (disk == 11)
131  return 12;
132  if (disk == 12)
133  return 13;
134  return 10;
135 }
136 
137 float StFttFastSimMaker::DiskRotation(int disk) {
138  assert(disk >= 9 && disk <= 12);
139  // these are
140  if (disk == 9)
141  return this->sTGC_disk9_theta;
142  if (disk == 10)
143  return this->sTGC_disk10_theta;
144  if (disk == 11)
145  return this->sTGC_disk11_theta;
146  if (disk == 12)
147  return this->sTGC_disk12_theta;
148  return 0;
149 }
150 
151 void StFttFastSimMaker::QuadBottomLeft(int disk, int quad, float &bottom, float &left) {
152  float hbp = DiskOffset(disk);
153  if ( FttGlobal::verbose ) {LOG_INFO << "disk: " << disk << ", offset = " << hbp << endm;}
154 
155  // quad 0 RECT
156  float q0l = hbp - STGC_QUAD_WIDTH;
157  float q0b = hbp;
158 
159  float q1l = hbp;
160  float q1b = -hbp;
161 
162  float q2l = -hbp;
163  float q2b = -hbp - STGC_QUAD_HEIGHT;
164 
165  float q3l = -hbp - STGC_QUAD_WIDTH;
166  float q3b = hbp - STGC_QUAD_HEIGHT;
167 
168  if (0 == quad) {
169  bottom = q0b;
170  left = q0l;
171  }
172  if (1 == quad) {
173  bottom = q1b;
174  left = q1l;
175  }
176  if (2 == quad) {
177  bottom = q2b;
178  left = q2l;
179  }
180  if (3 == quad) {
181  bottom = q3b;
182  left = q3l;
183  }
184  return;
185 }
186 
190 void StFttFastSimMaker::LocalToGlobal(float localX, float localY, int disk, int quad, float &globalX, float &globalY) {
191  // quad RECT
192  float qb = -1;
193  float ql = -1;
194  QuadBottomLeft(disk, quad, qb, ql);
195 
196  globalX = localX + ql;
197  globalY = localY + qb;
198  return;
199 }
200 
206 bool StFttFastSimMaker::Overlaps(StRnDHit *hitA, StRnDHit *hitB) {
207  // require that they are in the same disk!
208  if (hitA->layer() != hitB->layer())
209  return false;
210  int disk = hitA->layer();
211  // require that they are in the same quadrant of the detector
212  if (hitA->wafer() != hitB->wafer())
213  return false;
214  int quad = hitA->wafer();
215 
216  float x1 = hitA->double2();
217  float y1 = hitA->double3();
218  float x2 = hitB->double2();
219  float y2 = hitB->double3();
220 
221  float b = -1, l = -1;
222  QuadBottomLeft(disk, quad, b, l);
223 
224  float lx1 = x1 - l;
225  float ly1 = y1 - b;
226  float lx2 = x2 - l;
227  float ly2 = y2 - b;
228 
229  int chunkx1 = lx1 / STGC_WIRE_LENGTH;
230  int chunky1 = ly1 / STGC_WIRE_LENGTH;
231 
232  int chunkx2 = lx2 / STGC_WIRE_LENGTH;
233  int chunky2 = ly2 / STGC_WIRE_LENGTH;
234 
235  if (chunkx1 != chunkx2)
236  return false;
237  if (chunky1 != chunky2)
238  return false;
239  return true;
240 }
241 
242 void StFttFastSimMaker::FillThinGapChambers(StEvent *event) {
243  // Read the g2t table
244  St_g2t_fts_hit *hitTable = static_cast<St_g2t_fts_hit *>(GetDataSet("g2t_stg_hit"));
245  if (!hitTable) {
246  LOG_INFO << "g2t_stg_hit table is empty" << endm;
247  return;
248  } // if !hitTable
249 
250  StRnDHitCollection *ftscollection = event->rndHitCollection();
251 
252  std::vector<StRnDHit *> hits;
253 
254  // Prepare to loop over all hits
255  const int nhits = hitTable->GetNRows();
256  const g2t_fts_hit_st *hit = hitTable->GetTable();
257 
259 
260  float dx = STGC_SIGMA_X;
261  float dy = STGC_SIGMA_Y;
262  float dz = STGC_SIGMA_Z;
263 
264  int nSTGCHits = 0;
265  sTGCNRealPoints = 0;
266  sTGCNGhostPoints = 0;
267 
268  for (int i = 0; i < nhits; i++) {
269  hit = (g2t_fts_hit_st *)hitTable->At(i);
270  if (0 == hit)
271  continue;
272 
273  float xhit = hit->x[0];
274  float yhit = hit->x[1];
275  float zhit = hit->x[2];
276  int volume_id = hit->volume_id;
277  // volume_id = (1 front | 2 back) + 10 * (quadrant 0-3) + 100 * (station 0-4)
278  int disk = ((volume_id - 1) / 100) + 9 ;
279  LOG_DEBUG << "sTGC hit: volume_id = " << volume_id << " disk = " << disk << endm;
280 
281  // Now that geometry has a front and back, we skip points on the back module for fast sim
282  if (disk < 9 || volume_id % 2 == 0)
283  continue;
284 
285  float theta = DiskRotation(disk);
286 
287  float x_blurred = xhit + rand.gauss( STGC_SIGMA_X);
288  float y_blurred = yhit + rand.gauss( STGC_SIGMA_Y);
289 
290  float x_rot = -999, y_rot = -999;
291  this->rot(-theta, x_blurred, y_blurred, x_rot, y_rot);
292 
293  int quad = -1;
294  float localX = -999, localY = -999;
295  GlobalToLocal(x_rot, y_rot, disk, quad, localX, localY);
296 
297  // not in the active region
298  if (quad < 0 || quad > 3)
299  continue;
300  nSTGCHits++;
301 
302  StRnDHit *ahit = new StRnDHit();
303 
304  ahit->setPosition({x_blurred, y_blurred, zhit});
305  ahit->setPositionError({dx, dy, 0.1});
306 
307  ahit->setDouble0(xhit);
308  ahit->setDouble1(yhit);
309  ahit->setDouble2(x_rot);
310  ahit->setDouble3(y_rot);
311 
312  ahit->setLayer(disk); // disk mapped to layer
313  ahit->setLadder(2); // indicates a point
314  ahit->setWafer(quad); // quadrant number
315 
316  ahit->setIdTruth(hit->track_p, 0);
317  ahit->setDetectorId(kFtsId); // TODO: use dedicated ID for Ftt when StEvent is updated
318 
319  float Ematrix[] = {
320  dx * dx, 0.f, 0.f,
321  0.f, dy * dy, 0.f,
322  0.f, 0, 0.f, dz * dz};
323 
324  ahit->setErrorMatrix(Ematrix);
325  hits.push_back(ahit);
326 
327  if (!STGC_MAKE_GHOST_HITS) {
328  // Make this "REAL" hit.
329  if (FttGlobal::verbose){
330  ahit->Print();
331  }
332  ftscollection->addHit(ahit);
333  sTGCNRealPoints++;
334  }
335  }
336 
337  if (STGC_MAKE_GHOST_HITS) {
338  for (auto &hit0 : hits) { // first loop on hits
339  float hit0_x = hit0->double2();
340  float hit0_y = hit0->double3();
341  int disk0 = hit0->layer();
342  int quad0 = hit0->wafer();
343  float theta = DiskRotation(disk0);
344 
345  for (auto &hit1 : hits) { // second loop on hits
346  float hit1_x = hit1->double2();
347  float hit1_y = hit1->double3();
348  int disk1 = hit1->layer();
349  int quad1 = hit1->wafer();
350 
351  if (disk0 != disk1)
352  continue;
353  if (quad0 != quad1)
354  continue;
355 
356  // check on overlapping segments
357  if (false == Overlaps(hit0, hit1))
358  continue;
359 
360  float x = hit0_x;
361  float y = hit1_y;
362 
363  int qaTruth = 0;
364  int idTruth = 0;
365  if (hit1_x == hit0_x && hit1_y == hit0_y) {
366  sTGCNRealPoints++;
367  qaTruth = 1;
368  idTruth = hit0->idTruth();
369  } else {
370  sTGCNGhostPoints++;
371  qaTruth = 0;
372  }
373 
374  float rx = -999, ry = -999;
375  this->rot(theta, x, y, rx, ry);
376  // the trick here is that rotations (in 2D) will commute
377  // so the earlier -theta rotation and this +theta
378  // rotation cancel for real hits
379  // but not so for ghost hits
380 
381  StRnDHit *ahit = new StRnDHit();
382 
383  ahit->setPosition({rx, ry, hit0->position().z()});
384  ahit->setPositionError({dx, dy, 0.1});
385 
386  ahit->setDouble0(hit0_x);
387  ahit->setDouble1(hit0_y);
388  ahit->setDouble2(hit1_x);
389  ahit->setDouble3(hit1_y);
390 
391  ahit->setLayer(disk0); // disk mapped to layer
392  ahit->setLadder(2); // indicates a point
393  ahit->setWafer(quad0); // quadrant number
394 
395  ahit->setIdTruth(idTruth, qaTruth);
396  ahit->setDetectorId(kFtsId); // TODO: use dedicated ID for Ftt when StEvent is updated
397 
398  float Ematrix[] = {
399  dx * dx, 0.f, 0.f,
400  0.f, dy * dy, 0.f,
401  0.f, 0, 0.f, dz * dz};
402  ahit->setErrorMatrix(Ematrix);
403  ftscollection->addHit(ahit);
404 
405  } // loop hit1
406  } // loop hit0
407 
408 
409  // in this case the hits used in the original array were not saved, but copied so we need to delete them
410 
411  for ( size_t i = 0; i < hits.size(); i++ ){
412  delete hits[i];
413  hits[i] = nullptr;
414  }
415  } // make Ghost Hits
416 
417  if (FttGlobal::verbose) {
418  LOG_INFO << "nHits (all FTS) = " << nhits << endm;
419  }
420  if (FttGlobal::verbose) {
421  LOG_INFO << "nSTGC = " << nSTGCHits << endm;
422  }
423  if (FttGlobal::verbose) {
424  LOG_INFO << "nReal = " << sTGCNRealPoints << endm;
425  }
426  if (FttGlobal::verbose) {
427  LOG_INFO << "nGhost = " << sTGCNGhostPoints << endm;
428  }
429 
430 } // fillThinGap
Double_t gauss(const Double_t sigma) const
Return a random number distributed according to a gaussian with specified sigma.
Definition: StarRandom.cxx:72
static StarRandom & Instance()
Obtain the single instance of the random number generator.
Definition: StarRandom.cxx:87
virtual void AddData(TDataSet *data, const char *dir=".data")
User methods.
Definition: StMaker.cxx:332
A class for providing random number generation.
Definition: StarRandom.h:30
Definition: Stypes.h:41