StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
StFstFastSimMaker.cxx
1 #include "StFstFastSimMaker.h"
2 
3 #include "St_base/StMessMgr.h"
4 
5 #include "StEvent/StEvent.h"
6 #include "StEvent/StRnDHit.h"
7 #include "StEvent/StRnDHitCollection.h"
8 
9 #include "tables/St_g2t_fts_hit_Table.h"
10 #include "tables/St_g2t_track_Table.h"
11 
12 #include "StarClassLibrary/StThreeVectorF.hh"
13 #include "StarGenerator/UTIL/StarRandom.h"
14 
15 #include "TCanvas.h"
16 #include "TCernLib.h"
17 #include "TH2F.h"
18 #include "TLine.h"
19 #include "TRandom3.h"
20 #include "TString.h"
21 #include "TVector2.h"
22 #include "TVector3.h"
23 
24 #include <array>
25 #define _USE_MATH_DEFINES
26 #include <cmath>
27 #include <map>
28 #include <algorithm>
29 
30 
31 // lets not polute the global scope
32 namespace FstGlobal{
33  // converts the position error to a cov mat
34  StMatrixF Hack1to6(const StHit *stHit);
35  // used to convert between uniform and 1 sigma error
36  constexpr float SQRT12 = sqrt(12.0);
37 
38  // Disk segmentation
39  //
40  float RMIN[] = {0.95 * 4.3, 0.95 * 4.3, 0.95 * 4.3, 0.95 * 5.0, 0.95 * 5.0, 0.95 * 5.0};
41  float RMAX[] = {1.05 * 15.0, 1.05 * 25.0, 1.05 * 25.0, 1.05 * 28.0, 1.05 * 28.0, 1.05 * 28.0};
42 
43  //NEXT IS only for disk ARRAY 456 with the radius from 5 to 28.
44  float RSegment[] = {5., 7.875, 10.75, 13.625, 16.5, 19.375, 22.25, 25.125, 28.};
45 
46  // controls some extra output
47  const bool verbose = false;
48 
49  // key type for lookup tables on disk r-phi strip
50  typedef std::tuple<int, int, int> FstKeyTriple;
51 
52 
53 }
54 
55 StFstFastSimMaker::StFstFastSimMaker(const Char_t *name)
56  : StMaker{name},
57  mNumR{8},
58  mNumPHI{128},
59  mNumSEC{12},
60  mRaster{0},
61  mInEff{0},
62  mHist{false},
63  mQAFileName(0),
64  hTrutHitYXDisk(0),
65  hTrutHitRDisk(0),
66  hTrutHitRShower{0},
67  hTrutHitPhiDisk(0),
68  hTrutHitPhiZ(0),
69  hRecoHitYXDisk(0),
70  hRecoHitRDisk(0),
71  hRecoHitPhiDisk(0),
72  hRecoHitPhiZ(0),
73  hGlobalDRDisk(0),
74  hGlobalZ(0),
75  h2GlobalXY(0),
76  h2GlobalSmearedXY(0),
77  h2GlobalDeltaXY(0),
78  h3GlobalDeltaXYDisk(0),
79  h3GlobalDeltaXYR(0) { }
80 
81 int StFstFastSimMaker::Init() {
82 
83  if(mHist){
84  fOut = new TFile(mQAFileName.Data(), "RECREATE");
85  AddHist(hTrutHitYXDisk = new TH3F("hTrutHitYXDisk", "Global hits before segmentation", 151, -75.5, 75.5, 151, -75.5, 75.5, 10, 0, 10));
86  AddHist(hTrutHitRDisk = new TH2F("hTrutHitRDisk", "Global hits before segmentation", 400, 0, 40, 10, 0, 10));
87  AddHist(hTrutHitRShower[0] = new TH2F("hTrutHitRShower_4", "Global hits before segmentation", 400, 0, 40, 20, -10, 10));
88  AddHist(hTrutHitRShower[1] = new TH2F("hTrutHitRShower_5", "Global hits before segmentation", 400, 0, 40, 20, -10, 10));
89  AddHist(hTrutHitRShower[2] = new TH2F("hTrutHitRShower_6", "Global hits before segmentation", 400, 0, 40, 20, -10, 10));
90  AddHist(hTrutHitPhiDisk = new TH2F("hTrutHitPhiDisk", "Global hits before segmentation", 360, 0, 360, 10, 0, 10));
91  AddHist(hTrutHitPhiZ = new TH2F("hTrutHitPhiZ", "Global hits before segmentation", 360, 0, 360, 6000, 0, 600));
92  AddHist(hRecoHitYXDisk = new TH3F("hRecoHitYXDisk", "Global hits after segmentation", 151, -75.5, 75.5, 151, -75.5, 75.5, 10, 0, 10));
93  AddHist(hRecoHitRDisk = new TH2F("hRecoHitRDisk", "Global hits after segmentation", 400, 0, 40, 10, 0, 10));
94  AddHist(hRecoHitPhiDisk = new TH2F("hRecoHitPhiDisk", "Global hits after segmentation", 360, 0, 360, 10, 0, 10));
95  AddHist(hRecoHitPhiZ = new TH2F("hRecoHitPhiZ", "Global hits after segmentation", 360, 0, 360, 6000, 0, 600));
96  AddHist(hGlobalDRDisk = new TH2F("hGlobalDRDisk", "; Reco. r - MC r [cm]; Events;", 1000, -50, 50, 10, 0, 10));
97  AddHist(hGlobalZ = new TH1F("hGlobalZ", "; Z [cm]; Events;", 6000, 0, 600));
98  AddHist(h3GlobalDeltaXYR = new TH3F("h3GlobalDeltaXYR", ";globalDeltaX; globalDeltaY; R", 300, -0.3, 0.3, 300, -3, 3, 100, 0, 30));
99  AddHist(h2GlobalXY = new TH2F("h2GlobalXY", ";globalX; globalY", 1510, -75.5, 75.5, 1510, -75.5, 75.5));
100  AddHist(h2GlobalSmearedXY = new TH2F("h2GlobalSmearedXY", ";globalSmearedX; globalSmearedY", 1510, -75.5, 75.5, 1510, -75.5, 75.5));
101  AddHist(h2GlobalDeltaXY = new TH2F("h2GlobalDeltaXY", ";globalDeltaX; globalDeltaY", 151, -75.5, 75.5, 151, -75.5, 75.5));
102  AddHist(h3GlobalDeltaXYDisk = new TH3F("h3GlobalDeltaXYDisk", ";globalDeltaX; globalDeltaY; Disk", 151, -75.5, 75.5, 151, -75.5, 75.5, 10, 0, 10));
103  }
104  return StMaker::Init();
105 }
106 
107 void StFstFastSimMaker::SetDisk(const int i, const float rmn, const float rmx) {
108  FstGlobal::RMIN[i] = rmn;
109  FstGlobal::RMAX[i] = rmx;
110 }
111 
113  LOG_DEBUG << "StFstFastSimMaker::Make" << endm;
114 
115  // Get the existing StEvent, or add one if it doesn't exist.
116  StEvent *event = static_cast<StEvent *>(GetDataSet("StEvent"));
117  if (!event) {
118  event = new StEvent;
119  AddData(event);
120  LOG_DEBUG << "Creating StEvent" << endm;
121  }
122 
123  if (0 == event->rndHitCollection()) {
124  event->setRnDHitCollection(new StRnDHitCollection());
125  LOG_DEBUG << "Creating StRnDHitCollection for FTS" << endm;
126  }
127 
128  // Digitize GEANT FTS hits
129  FillSilicon(event);
130 
131  return kStOk;
132 }
133 
134 /* Fill an event with StFtsHits. */
135 /* This should fill StFtsStrip for realistic simulator and let clustering fill StFtsHit */
136 /* For now skipping StFtsStrip and clustering, and fill StFtsHits directly here*/
137 
138 void StFstFastSimMaker::FillSilicon(StEvent *event) {
139 
140  StRnDHitCollection *fsicollection = event->rndHitCollection();
141 
142  const int MAXR = mNumR;
143  const int MAXPHI = mNumPHI * mNumSEC;
144 
145  float X0[] = {0, 0, 0, 0, 0, 0};
146  float Y0[] = {0, 0, 0, 0, 0, 0};
147 
148  if (mRaster > 0)
149  for (int i = 0; i < 6; i++) {
150  X0[i] = mRaster * TMath::Cos(i * 60 * TMath::DegToRad());
151  Y0[i] = mRaster * TMath::Sin(i * 60 * TMath::DegToRad());
152  }
153 
154 
155  // maps for hit and energy for each disk's r-phi strip
156  std::map< FstGlobal::FstKeyTriple, StRnDHit* > hitMap;
157  std::map< FstGlobal::FstKeyTriple, double > energySum;
158  std::map< FstGlobal::FstKeyTriple, double > energyMax;
159 
160  // Read the g2t table
161  St_g2t_fts_hit *hitTable = static_cast<St_g2t_fts_hit *>(GetDataSet("g2t_fsi_hit"));
162  if (!hitTable) {
163  LOG_INFO << "g2t_fsi_hit table is empty" << endm;
164  return; // Nothing to do
165  }
166 
167  const Int_t nHits = hitTable->GetNRows();
168  LOG_DEBUG << "g2t_fsi_hit table has " << nHits << " hits" << endm;
169  const g2t_fts_hit_st *hit = hitTable->GetTable();
170 
171  StPtrVecRnDHit hits;
172 
173  // track table
174  St_g2t_track *trkTable = static_cast<St_g2t_track *>(GetDataSet("g2t_track"));
175  if (!trkTable) {
176  LOG_INFO << "g2t_track table is empty" << endm;
177  return; // Nothing to do
178  }
179 
180  const Int_t nTrks = trkTable->GetNRows();
181 
182  LOG_DEBUG << "g2t_track table has " << nTrks << " tracks" << endm;
183 
184  const g2t_track_st *trk = trkTable->GetTable();
185 
186 
187  int count = 0;
188  for (Int_t i = 0; i < nHits; ++i) {
189 
190  hit = (g2t_fts_hit_st *)hitTable->At(i);
191 
192  // skip bad hits
193  if (!hit)
194  continue;
195 
196 
197  int volume_id = hit->volume_id;
198  LOG_DEBUG << "volume_id = " << volume_id << endm;
199  int disk = volume_id / 1000; // disk id
200  int wedge = (volume_id % 1000) / 10; // wedge id
201  int sensor = volume_id % 10; // sensor id
202 
203  // used as an index for various arrays
204  size_t disk_index = disk - 1;
205 
206  LOG_DEBUG << "disk = " << disk << ", wedge = " << wedge << ", sensor = " << sensor << endm;
207 
208  // skip non-FST hits
209  if ( disk > 6 ) continue;
210 
211 
212  double energy = hit->de;
213  int track = hit->track_p;
214 
215  trk = (g2t_track_st *)trkTable->At(track);
216  int isShower = false;
217  if (trk)
218  isShower = trk->is_shower;
219 
220  // raster coordinate offsets
221  double xc = X0[disk_index];
222  double yc = Y0[disk_index];
223 
224  // hit coordinates
225  double x = hit->x[0];
226  double y = hit->x[1];
227  double z = hit->x[2];
228 
229  if (z > 200)
230  continue; // skip large disks
231 
232  // rastered
233  double rastered_x = x - xc;
234  double rastered_y = y - yc;
235 
236  double r = sqrt(x * x + y * y);
237  double p = atan2(y, x);
238 
239  // rastered
240  double rr = sqrt(rastered_x * rastered_x + rastered_y * rastered_y);
241  double pp = atan2(rastered_y, rastered_x);
242 
243 
244  // wrap an angle between 0 and 2pi
245  auto wrapAngle = [&]( double angle ) {
246  angle = fmod( angle, 2.0 * M_PI );
247  if ( angle < 0 )
248  angle += 2.0 * M_PI;
249  return angle;
250  };
251 
252  p = wrapAngle( p );
253  pp = wrapAngle( pp );
254 
255  LOG_DEBUG << "rr = " << rr << " pp=" << pp << endm;
256  LOG_DEBUG << "RMIN = " << FstGlobal::RMIN[disk_index] << " RMAX= " << FstGlobal::RMAX[disk_index] << endm;
257 
258  // Cuts made on rastered value to require the r value is within limits
259  if (rr < FstGlobal::RMIN[disk_index] || rr > FstGlobal::RMAX[disk_index])
260  continue;
261 
262  LOG_DEBUG << "rr = " << rr << endm;
263 
264  // Strip numbers on rastered value
265  int r_index = floor(MAXR * (rr - FstGlobal::RMIN[disk_index]) / (FstGlobal::RMAX[disk_index] - FstGlobal::RMIN[disk_index]));
266 
267  // this gives a different conflicting answer for r_index and does not handle r outside of range
268  for (int ii = 0; ii < MAXR; ii++)
269  if (rr > FstGlobal::RSegment[ii] && rr <= FstGlobal::RSegment[ii + 1])
270  r_index = ii;
271 
272  // Phi number
273  int phi_index = int(MAXPHI * pp / 2.0 / M_PI);
274 
275  if (r_index >= 8)
276  continue;
277 
278  if (MAXR)
279  assert(r_index < MAXR);
280  if (MAXPHI)
281  assert(phi_index < MAXPHI);
282 
283  StRnDHit *fsihit = nullptr;
284 
285  // key of this disk's r & phi strip
286  auto threeKey = std::tie( disk_index, r_index, phi_index );
287 
288  if (hitMap.count( threeKey ) == 0) { // New hit
289 
290  if (FstGlobal::verbose){
291  LOG_INFO << Form("NEW d=%1d xyz=%8.4f %8.4f %8.4f r=%8.4f phi=%8.4f iR=%2d iPhi=%4d dE=%8.4f[MeV] truth=%d",
292  disk, x, y, z, r, p, r_index, phi_index, energy * 1000.0, track)
293  << endm;
294  }
295 
296  count++;
297  fsihit = new StRnDHit();
298  fsihit->setDetectorId(kFtsId);
299  fsihit->setLayer(disk);
300 
301  //
302  // Set position and position error based on radius-constant bins
303  //
304  double p0 = (phi_index + 0.5) * 2.0 * M_PI / double(MAXPHI);
305  double dp = 2.0 * M_PI / double(MAXPHI) / FstGlobal::SQRT12;
306 
307  // ONLY valid for the disk array 456, no difference for each disk
308  double r0 = (FstGlobal::RSegment[r_index] + FstGlobal::RSegment[r_index + 1]) * 0.5;
309  double dr = FstGlobal::RSegment[r_index + 1] - FstGlobal::RSegment[r_index];
310 
311  double x0 = r0 * cos(p0) + xc;
312  double y0 = r0 * sin(p0) + yc;
313  assert(TMath::Abs(x0) + TMath::Abs(y0) > 0);
314  double dz = 0.03 / FstGlobal::SQRT12;
315  double er = dr / FstGlobal::SQRT12;
316  fsihit->setPosition(StThreeVectorF(x0, y0, z));
317 
318  fsihit->setPositionError(StThreeVectorF(er, dp, dz));
319  // set covariance matrix
320  fsihit->setErrorMatrix(&FstGlobal::Hack1to6(fsihit)[0][0]);
321 
322  fsihit->setCharge(energy);
323  fsihit->setIdTruth(track, 100);
324  hits.push_back(fsihit);
325 
326  hitMap[ threeKey ] = fsihit;
327  energySum[ threeKey ] = energy;
328  energyMax[ threeKey ] = energy;
329 
330  if (FstGlobal::verbose){
331  LOG_INFO << Form("NEW d=%1d xyz=%8.4f %8.4f %8.4f ", disk, x, y, z) << endm;
332  LOG_INFO << Form("smeared xyz=%8.4f %8.4f %8.4f ", fsihit->position().x(), fsihit->position().y(), fsihit->position().z()) << endm;
333  }
334 
335  if(mHist){
336  TVector2 hitpos_mc(x, y);
337  TVector2 hitpos_rc(fsihit->position().x(), fsihit->position().y());
338 
339  hTrutHitYXDisk->Fill(x, y, disk);
340  hTrutHitRDisk->Fill(hitpos_mc.Mod(), disk);
341 
342  if (disk == 4)
343  hTrutHitRShower[0]->Fill(hitpos_mc.Mod(), isShower);
344  if (disk == 5)
345  hTrutHitRShower[1]->Fill(hitpos_mc.Mod(), isShower);
346  if (disk == 6)
347  hTrutHitRShower[2]->Fill(hitpos_mc.Mod(), isShower);
348 
349  hTrutHitPhiDisk->Fill(hitpos_mc.Phi() * 180.0 / TMath::Pi(), disk);
350  hTrutHitPhiZ->Fill(hitpos_mc.Phi() * 180.0 / TMath::Pi(), z);
351  hRecoHitYXDisk->Fill(fsihit->position().x(), fsihit->position().y(), disk);
352  hRecoHitRDisk->Fill(hitpos_rc.Mod(), disk);
353  hRecoHitPhiDisk->Fill(hitpos_rc.Phi() * 180.0 / TMath::Pi(), disk);
354  hRecoHitPhiZ->Fill(hitpos_rc.Phi() * 180.0 / TMath::Pi(), z);
355  hGlobalDRDisk->Fill(hitpos_rc.Mod() - hitpos_mc.Mod(), disk);
356  hGlobalZ->Fill(fsihit->position().z());
357 
358  // cout << "CHECK : " << fsihit->position().x()-x << " ||| "<< fsihit->position().y()-y << endl;
359  h2GlobalXY->Fill(x, y);
360  h2GlobalSmearedXY->Fill(fsihit->position().x(), fsihit->position().y());
361  h2GlobalDeltaXY->Fill(fsihit->position().x() - x, fsihit->position().y() - y);
362  h3GlobalDeltaXYDisk->Fill(fsihit->position().x() - x, fsihit->position().y() - y, disk);
363 
364  h3GlobalDeltaXYR->Fill(fsihit->position().x() - x, fsihit->position().y() - y, sqrt(pow(fsihit->position().x(), 2) + pow(fsihit->position().y(), 2)));
365  }
366  }
367  else { // Hit on this strip already exists, adding energy to old hit
368  // get hit from the map
369  fsihit = hitMap[ threeKey ] ;
370  fsihit->setCharge(fsihit->charge() + energy);
371 
372  // Add energy to running sum
373  energySum[ threeKey ] = energySum[ threeKey ] + energy;
374 
375  if (energy> energyMax[ threeKey ])
376  energyMax[ threeKey ] = energy;
377 
378  // keep idtruth but dilute it...
379  track = fsihit->idTruth();
380 
381  fsihit->setIdTruth(track, 100 * (energyMax[ threeKey ] / energySum[ threeKey ]));
382  }
383  } // loop on hits
384  int nfsihit = hits.size();
385 
387 
388  // NOW run back through the hits and add them if they pass an efficiency roll
389  for (int i = 0; i < nfsihit; i++) {
390  double rnd_save = rand.flat();
391  if (rnd_save > mInEff){
392  fsicollection->addHit(hits[i]);
393  }
394  }
395  if (FstGlobal::verbose) {
396  LOG_DEBUG << Form("Found %d/%d g2t hits in %d cells, created %d hits with ADC>0", count, nHits, nfsihit, fsicollection->numberOfHits()) << endm;
397  }
398 
399 }
400 //
401 
403  if(mHist){
404  fOut->cd();
405  hTrutHitYXDisk->Write();
406  hTrutHitRDisk->Write();
407  hTrutHitRShower[0]->Write();
408  hTrutHitRShower[1]->Write();
409  hTrutHitRShower[2]->Write();
410  hTrutHitPhiDisk->Write();
411  hTrutHitPhiZ->Write();
412  hRecoHitYXDisk->Write();
413  hRecoHitRDisk->Write();
414  hRecoHitPhiDisk->Write();
415  hRecoHitPhiZ->Write();
416  hGlobalDRDisk->Write();
417  hGlobalZ->Write();
418  h3GlobalDeltaXYR->Write();
419  h2GlobalXY->Write();
420  h2GlobalSmearedXY->Write();
421  h2GlobalDeltaXY->Write();
422  h3GlobalDeltaXYDisk->Write();
423  fOut->Close();
424  }
425  return kStOK;
426 }
427 
428 //_____________________________________________________________________________
429 StMatrixF FstGlobal::Hack1to6(const StHit *stHit) {
430  // X = R*cos(Fi), Y=R*sin(Fi), Z = z
431  // dX/dR = ( cos(Fi) ,sin(Fi),0)
432  // dX/dFi = (-R*sin(Fi), R*cos(Fi),0)
433  // dX/dZ = ( 0, 0,1)
434 
435  auto hiPos = stHit->position();
436  auto hiErr = stHit->positionError();
437  double Rxy = sqrt(hiPos[0] * hiPos[0] + hiPos[1] * hiPos[1]);
438  double cosFi = hiPos[0] / Rxy;
439  double sinFi = hiPos[1] / Rxy;
440  double T[3][3] = {{cosFi, -Rxy * sinFi, 0}, {sinFi, Rxy * cosFi, 0}, {0, 0, 1}};
441  double Ginp[6] = {hiErr[0] * hiErr[0], 0, hiErr[1] * hiErr[1], 0, 0, hiErr[2] * hiErr[2]};
442  double Gout[6];
443 
444  TCL::trasat(T[0], Ginp, Gout, 3, 3);
445  StMatrixF mtxF(3, 3);
446 
447  for (int i = 0, li = 0; i < 3; li += ++i) {
448  for (int j = 0; j <= i; j++) {
449  mtxF[i][j] = Gout[li + j];
450  mtxF[j][i] = mtxF[i][j];
451  }
452  }
453 
454  return mtxF;
455 }
static StarRandom & Instance()
Obtain the single instance of the random number generator.
Definition: StarRandom.cxx:87
Definition: StHit.h:125
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
Double_t flat() const
Return a random number uniformly distributed between 0 and 1.
Definition: StarRandom.cxx:68
static float * trasat(const float *a, const float *s, float *r, int m, int n)
Definition: TCernLib.cxx:540
Definition: Stypes.h:40
void SetDisk(const int i, const float rmn, const float rmx)
Set min/max active radii for each disk.
Definition: Stypes.h:41