StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
StFgtSlowSimuMaker.cxx
1 // *-- Author : J.Balewski
2 //
3 // $Id: StFgtSlowSimuMaker.cxx,v 1.5 2011/04/11 19:35:38 fisyak Exp $
4 #include <TVector3.h>
5 #include <TH2.h>
6 #include <TF1.h>
7 #include <TFile.h>
8 #include <TLine.h>
9 #include <TPolyLine.h>
10 #include <TCrown.h>
11 #include <TRandom3.h>
12 
13 #include "StFgtSlowSimuMaker.h"
14 #include "HexLatice.h"
15 
16 #include "tables/St_g2t_fgt_hit_Table.h"
17 
18 ClassImp(StFgtSlowSimuMaker)
19 
20 //--------------------------------------------
23  setHList(0);
24  memset(hA,0,sizeof(hA));
25  geom=new StFgtGeom();
26  mRnd = new TRandom3(); // general use random generator
27  // mRnd->SetSeed(0); // activate, assure every set of data is different
28 
29  forcePerpTracks(false); // normal operation
30  meLossTab[0]=-999; // default=uninitialized
31 
32  par_2DpixAmplThres=0.1; // a.u. MIP respons has maxAmpl~200-300== # of electrons
33  par_stripAmplThres=1.0; // a.u., drop strips below it, default=1.0
34  par_XYamplSigma=0.035 ; // cm, for 2D gauss smearing, default=0.035
35 
36  par_radStripGainMean=1.0;par_radStripGainSigma=0.0;// allow unequal energy sharing
37  par_cutoffOfBichel = 9992; // meLossTab[9993-10000]=5.0E+03 to 6.0E+06 (too high) are cut off. They are replaced by meLossTab[9992]=4.78E+03 in simulation.
38  mRadStripRelativeGain=0;// clear pointer
39  mPhiStripRelativeGain=0;// clear pointer
40  hexLat=0;
41 }
42 
43 //--------------------------------------------
44 void
46  int i,j;
47  for(i=0;i<kFgtMxDisk;i++){
48  for(j=0;j<kFgtMxQuad;j++) {
49  mG2tHitList[i][j].clear();
50  }
51  mRadAdcList[i].clear();
52  mPhiAdcList[i].clear();
53  }
55 }
56 
57 
58 //--------------------------------------------
59 StFgtSlowSimuMaker::~StFgtSlowSimuMaker(){
60 
61 }
62 
63 //_______________________________________________
64 //________________________________________________
65 void
66 StFgtSlowSimuMaker::saveHisto(TString fname){
67 
68  CloseHisto();
69 
70  TString outName=fname+".hist.root";
71  TFile f( outName,"recreate");
72  assert(f.IsOpen());
73  printf("%d histos are written to '%s' ...\n",HList->GetEntries(),outName.Data());
74 
75  HList->Write();
76  f.Close();
77 
78 }
79 
80 
81 //--------------------------------------------
82 //--------------------------------------------
83 //--------------------------------------------
84 Int_t
86  LOG_INFO<<"::Finish() \n"<< endm;
87 
88 
89  return StMaker::Finish();
90 }
91 
92 
93 
94 //--------------------------------------------
95 //--------------------------------------------
96 //--------------------------------------------
97 Int_t
98 StFgtSlowSimuMaker::Init(){
99  LOG_INFO<<"::Init() "<< endm;
100  assert(HList);
101  assert( meLossTab[0]>0); //Frank's model of # of electron pairs must be initialized
102  mInpEve=0;
103 
104  /* model transverse response in 1D
105  Frank: However, from test beam data I calculate the RMS of each cluster,
106  and there I get something like 0.5 - 0.6 strips, which is around 350 um.
107  all clusters (both in my diploma thesis and in my email) are 1D. A
108  cluster is defined as something on ONE projection of the detector. So
109  the FWHM and the sigma is all 1D. So you should not divide by Sqrt(2) to
110  get the 1 D value.
111  */
112 
113  amplF= new TF1("Gs","exp( -(x-[0])*(x-[0])/2./[1]/[1])",-1.,1.); // X in cm
114  amplF->SetParNames("X0","sig");
115  amplF ->SetParameters(0.,par_XYamplSigma);
116  amplF ->SetLineWidth(2); amplF->SetLineColor(kMagenta);
117 
118  InitHisto1();
119  InitHisto2();
120 
121  // initialize RAD- gains
122  mRadStripRelativeGain=new double[geom->radStripGBLId_number()+1]; // allocate array
123  memset(mRadStripRelativeGain,0,sizeof(mRadStripRelativeGain));
124  int i;
125  for(i=0;i<geom->radStripGBLId_number();i++) {
126  double del=99999;
127  while(fabs(del)> 2.*par_radStripGainSigma)
128  del= mRnd->Gaus(0,par_radStripGainSigma);
129  mRadStripRelativeGain[i]=par_radStripGainMean+del;
130  // if(i<20) printf("rad%d %.4f\n",i,mRadStripRelativeGain[i]);
131  }
132 
133  // initialize PHI- gains
134  mPhiStripRelativeGain=new double[geom->phiStripGBLId_number()+1]; // allocate array
135  memset(mPhiStripRelativeGain,0,sizeof(mPhiStripRelativeGain));
136  for(i=0;i<geom->phiStripGBLId_number();i++) {
137  double del=99999;
138  while(fabs(del)> 2.*par_phiStripGainSigma)
139  del= mRnd->Gaus(0,par_phiStripGainSigma);
140  mPhiStripRelativeGain[i]=par_phiStripGainMean+del;
141  // if(i<20) printf("phi%d %.4f\n",i,mPhiStripRelativeGain[i]);
142  }
143 
144  // initialize hexagonal Gem latice
145  if(par_hexLaticePitch >0.001) {
146  hexLat=new HexLatice (par_hexLaticePitch, par_hexLaticePhi1deg);
147  } else {
148  LOG_INFO<<Form("::Init hexGemLatice DISABLED, too small pitch")<<endm;
149  par_hexLaticePitch = 0.0;
150  }
151 
152  geom->printParam();
153 
154  LOG_INFO<<Form("::Init params: X,YamplSigma=%.4f cm, 2DpixAmplThres=%.2f a.u., stripAmplThres=%.2f a.u., forcePerpTracks=%d useOnlyDisk=%d RadGain(m=%.2f,sig=%.2f) PhiGain(m=%.2f,sig=%.2f, GemHexLatice: pitch/um=%.1f, phi1/deg=%.1f, transDiffusion=%.1f um/1cmOfPath, cutoffOfBichel=%d)",par_XYamplSigma,par_2DpixAmplThres,par_stripAmplThres,par_forcePerp,par_useOnlyDisk,par_radStripGainMean,par_radStripGainSigma,par_phiStripGainMean,par_phiStripGainSigma,par_hexLaticePitch*1e4, par_hexLaticePhi1deg,par_transDiffusionPerPath*1e4,par_cutoffOfBichel)<< endm; // fix it
155 
156  assert(par_XYamplSigma>0);
157 
158  Info("Init","testing access to TGeoManager");
159 
160  if (gGeoManager) { // Geom already there
161  Info("Load","TGeoManager(%s,%s) is already there"
162  ,gGeoManager->GetName(),gGeoManager->GetTitle());
163  } else {
164  Warning("Init","add TGeoManager");
165  // TString geo="y2009a"; // got it from Victor
166  // TString ts("$STAR/StarDb/VmcGeometry/");
167  // ts+=geo; ts+=".h";
168  TString ts = "SandBox.C(0,0)";
169  //printf("WILL execute macro=%s=\n",ts.Data());
170  int ierr=0;
171  gROOT->Macro(ts, &ierr);
172  assert(!ierr);
173  }
174  assert(gGeoManager);
175 
176  TGeoVolume *geoFgt = gGeoManager ->FindVolumeFast("FGMO");
177  assert(geoFgt);
178  geoFgt -> Print();
179  geoFgt -> InspectMaterial();
180  geoFgt -> InspectShape();
181  printf("XXXXXXXXXXXXXXXXXXXXXXXXX\nXXXXXXXXXXXXX\nXXXXXXXXXX\n");
182 
183 
184 
185  return StMaker::Init();
186 }
187 
188 //--------------------------------------------
189 //--------------------------------------------
190 //--------------------------------------------
191 Int_t
193  mInpEve++;
194 
195  LOG_INFO <<"::Make() inpEve="<< mInpEve<<endm;
196  //============ FGT ==========
197  St_g2t_fgt_hit *fgt_hitT = (St_g2t_fgt_hit *) GetDataSet("g2t_fgt_hit");
198  if(fgt_hitT ==0) {
199  LOG_FATAL<<Form("g2t_Fgt table empty")<<endm;
200  return kStOK;
201  }
202 
203  /* In year 2012 only 6 disks are build and installed in STAR
204  This implementation allows for up to 8 disk to be used in reco and
205  additional disk #9 can exist in GSTR but sort_g2t_hits() will dropp them.
206  If disk #10 or more is reported the code will crash
207  */
208 
209  sort_g2t_hits( fgt_hitT );
210 
211  int iDisk=0,iQuad=0;
212  for(iDisk=0;iDisk<kFgtMxDisk;iDisk++) {
213  digRad->Reset(); digPhi->Reset(); //clear once per disk
214  if(par_useOnlyDisk) if(par_useOnlyDisk-1 != iDisk) continue;
215  for(iQuad=0;iQuad<kFgtMxQuad;iQuad++) {
216  digXY->Reset(); // needs reset for every quadrant
217 
218  printf(" process %d g2t hits in disk=%d quad=%d\n", mG2tHitList[iDisk][iQuad].size(),iDisk,iQuad);
219  // accumulate response in digXY array
220  vector<fgt_g2t_auxil> &L=mG2tHitList[iDisk][iQuad];
221  if(L.size()<=0) continue;// drop if empty quad
222  for(UInt_t
223  i=0;i<L.size();i++) { // populate: digXY
224  //responseLinearModel(h->Rloc,h->Dloc);
225  responseFrankModel(L[i].Rloc,L[i].Dloc);
226  hA[11+iDisk]->Fill(L[i].Rlab.x(),L[i].Rlab.y()); // monitor hit distribution
227  printf("iQ=%d itr=%d R/cm=%.2f phi/deg=%.3f\n",iQuad,i,L[i].Rlab.Perp(), L[i].Rlab.Phi()/3.1416*180); // pi value corrected WMZ
228  }
229  // now response is stored in digXY array
230  if(!projectQuadrant(iQuad)) continue;// drop if empty quad
231  // strip response is generated and projected to 1D stip histos: R & Phi
232  // break; // only 1st quad, tmp
233  }
234  // only once per disk
235  exportStripPlane(digRad,mRadAdcList[iDisk]);
236  exportStripPlane(digPhi,mPhiAdcList[iDisk]);
237  // break;
238  } // end of disk
239 
240  printf(" Summary of fired strips\n disk #Rad-strip #Phi-strip \n");
241  for(iDisk=0;iDisk<kFgtMxDisk;iDisk++) printf("%d %d %d \n",iDisk,mRadAdcList[iDisk].size(),mPhiAdcList[iDisk].size());
242 
243  return kStOK;
244 }
245 
246 //--------------------------------------------
247 //--------------------------------------------
248 //--------------------------------------------
249 void
250 StFgtSlowSimuMaker::sort_g2t_hits( St_g2t_fgt_hit *fgt_hitT){
251  g2t_fgt_hit_st *hitPtr = fgt_hitT->GetTable();
252  assert(hitPtr);
253  LOG_INFO<<Form("Sorting g2t FGT hits, size=%d",fgt_hitT->GetNRows())<<endm;
254 
255  int ntot=0;
256  Int_t nhits = fgt_hitT->GetNRows();
257  for(Int_t ih=0; ih<nhits; ih++,hitPtr++) {
258  Int_t ivid = hitPtr->volume_id;
259 
260  // decode volume_id WMZ
261  Int_t numbv1 = ivid/1000000;
262  //Int_t numbv2 = (ivid/10000)%100;
263  int diskID, iQuad; // diskID and quadID, both start from 0
264 
265 //No Quad ID for now, it assigned to 0 for now
266  diskID = numbv1 - 1;
267  iQuad = 0; //temp
268 //
269 /* Disk9 is not a concer for now, commented out
270  if(numbv2 != 0) {
271  diskID = numbv1 - 1;
272  iQuad = numbv2 - 1;
273  } else {
274  diskID = 8;
275  iQuad = numbv1 - 1;
276  }
277 */
278  cout << " Volume_id diskID QuadID: "
279  << ivid << " " << diskID << " " << iQuad << endl;
280 
281  TVector3 Rlab( hitPtr->x); // entrance point in Lab ref
282  TVector3 Rloc=Rlab;
283 /*
284  IQuad my not match Rlab.Phi() for hits at edges between two quadrants
285  (deadQuadEdge)! The following conversion would rotate Rlab with a wrong
286  angle if a mismatch happens. However, Rloc.x() or Rloc.y() would be still
287  very close to one of two edges of a local quadrant and the cuts on Rloc.x()
288  and Rloc.y() later would reject them. WMZ
289 */
290 
291  Rloc.RotateZ(-geom->phiQuadXaxis(iQuad));
292 
293  hA[3]->Fill(1);
294  if(diskID!=8 && !geom->inDisk(Rlab)) continue; // drop 8 ? JB
295  hA[3]->Fill(2);
296 
297  if(fabs(Rloc.x()) < geom->deadQuadEdge()) continue;
298  hA[3]->Fill(3);
299  if(fabs(Rloc.y()) < geom->deadQuadEdge()) continue;
300  hA[3]->Fill(4);
301 
302  double tof_ns=hitPtr->tof*1.e9;
303  hA[5]->Fill(tof_ns);
304  if(hitPtr->tof> geom-> maxTof() ) continue;
305  hA[3]->Fill(5);
306 
307  TVector3 Plab(hitPtr->p);
308  if(Plab.Mag()>0) hA[7]->Fill(log10(Plab.Mag()*1000.));
309  if(Plab.Mag()< geom-> minPmag() ) continue;
310  hA[3]->Fill(6);
311 
312 
313  /*
314  TVector3 RGeant=Rloc; RGeant.RotateZ(-0.7854);
315 
316  cout << " R = " << Rlab.Perp() << endl;
317  cout << " Rlab_x, _y = " << Rlab.x() << " " << Rlab.y() << endl;
318  cout << " Rloc_x, _y = " << Rloc.x() << " " << Rloc.y() << endl;
319  cout << " RGeant_x, _y = " << RGeant.x() << " " << RGeant.y() << endl;
320  cout << " phiG, phiLoc, phiLab = " << RGeant.Phi()*180/3.14159 << " "
321  << Rloc.Phi()*180/3.14159 << " "
322  << Rlab.Phi()*180/3.14159 << " " << endl;
323  */
324 
325  // Compare quadID from StFgtGeom and the one decoded from Geant WMZ
326  int iQuadChk=geom->getQuad(Rlab.Phi());
327  if(iQuad != iQuadChk) {
328  cout << " Something wrong in quadIDs!! " << endl;
329  cout << " iQuad from StFgtGeom and iQuad from Geant = "
330  << iQuadChk << ", " << iQuad << endl;
331  }
332 
333  // hA[3]->Fill(7...9); free
334 
335  //....... hit is accepted for processing ...............
336  double ds=hitPtr->ds;
337 
338  TVector3 verLab=Plab.Unit(); // direction of track in LAB
339  if(par_forcePerp) verLab=TVector3(0,0,1);// for testing ONLY: make track perp to GEM
340  TVector3 Rloc2=Rlab+ds*verLab; Rloc2.RotateZ(-geom->phiQuadXaxis(iQuad));
341  TVector3 Dloc=Rloc2-Rloc; // local vector along the path
342 
343  fgt_g2t_auxil aux;
344  aux.hitPtr=hitPtr;
345  aux.Rloc=Rloc;
346  aux.Dloc=Dloc;
347  aux.Rlab=Rlab+ds/2.*verLab; // set it in the middle of the track segment
348 
349  aux.iQuad=iQuad;
350  mG2tHitList[diskID][iQuad].push_back(aux); // ID starts from 0, WMZ
351 
352  ntot++;
353 
354  //...... only QA is below .......
355 
356  // QA accpted hits
357  hA[3]->Fill(10+5*diskID);
358  hA[3]->Fill(10+5*diskID+iQuad+1);
359  double de_kev=hitPtr->de*1.e6;
360  hA[0]->Fill(de_kev);
361  hA[1]->Fill(hitPtr->ds);
362  hA[2]->Fill(Rlab.z());
363  hA[4]->Fill(Rlab.x(),Rlab.y());
364  hA[6]->Fill(Rlab.Perp());
365 
366  }// loop over hits
367  LOG_INFO<<Form("Sorting g2g FGT %d hits --> accepted %d",nhits,ntot)<<endm;
368 }
369 
370 
371 //--------------------------------------------
372 //--------------------------------------------
373 //--------------------------------------------
374 bool
375 StFgtSlowSimuMaker::projectQuadrant( int iquad) {
376 
377  double totAmp=digXY->Integral();
378  LOG_INFO<<Form("::digiQuad() totAmp=%g",totAmp)<< endm;
379  if(totAmp <par_stripAmplThres) return false;
380 
381  int nPix=0;
382 
383  double sumAmp=0; //for QA
384 
385  int nx=digXY->GetNbinsX();
386  int ny=digXY->GetNbinsY();
387  int bx,by;
388  for(bx=1;bx<=nx;bx++)
389  for(by=1;by<=ny;by++) {
390  float amp=digXY->GetBinContent(bx,by); // this is not double because histo if float
391  if(amp<par_2DpixAmplThres) continue; // drop too low signal
392  nPix++;
393  sumAmp+=amp;
394  double x=digXY->GetXaxis()->GetBinCenter(bx); // SLOW
395  double y=digXY->GetYaxis()->GetBinCenter(by); // SLOW
396  int iRadID,iPhiID;// strip coordinates
397  if( !geom->localXYtoStripID(iquad,x,y,iRadID, iPhiID)) continue;
398 // printf( "ampl=%f loc: x=%f y=%f iRad=%d iPhi=%d bx=%d by=%d\n",amp,x,y,iRadID, iPhiID,bx,by);
399 
400  //accumulate response of individual strips
401  digRad->Fill(iRadID,amp* mRadStripRelativeGain[iRadID]);
402  digPhi->Fill(iPhiID,amp* mPhiStripRelativeGain[iPhiID]);
403 
404  digRadAll->Fill(iRadID,amp* mRadStripRelativeGain[iRadID]);
405  digPhiAll->Fill(iPhiID,amp* mPhiStripRelativeGain[iPhiID]);
406 
407  }
408  printf("digi: nPix=%d sumAmp=%g\n", nPix,sumAmp);
409 
410  return true;
411 }
412 
413 
414 //--------------------------------------------
415 //--------------------------------------------
416 //--------------------------------------------
417 void
418 StFgtSlowSimuMaker::exportStripPlane(TH1F *h, vector<fgt_strip> &L) {
419  float *y=h->GetArray();
420  y++; // root histo counts bins from 1 - incredible silly
421  float nx=h->GetNbinsX();
422  for(int id=0;id<nx;id++,y++) {
423  double ene=*y;
424  if(ene <par_stripAmplThres) continue;
425  fgt_strip st;
426  st.id=id; // strips IDs are counted from zero
427  st.adc=ene;
428  L.push_back(st);
429  //printf("%s add strID=%d adc=%.1f\n",h->GetName(),st.id,st.adc);
430  }
431 }
432 
433 
434 
435 
436 
439 
440 // $Log: StFgtSlowSimuMaker.cxx,v $
441 // Revision 1.5 2011/04/11 19:35:38 fisyak
442 // Replace uint by UInt_t, use TMath
443 //
444 // Revision 1.4 2011/04/08 22:18:42 balewski
445 // added access to TGeo
446 //
447 // Revision 1.3 2011/04/08 19:25:45 wzhang
448 // Changed diskID assignment for Jan temporarily
449 //
450 // Revision 1.2 2011/04/08 01:14:13 balewski
451 // removed most of FGT from ver 3
452 //
453 // Revision 1.1 2011/04/07 19:31:22 balewski
454 // start
455 //
456 
457 
458 
459 
460 
virtual Int_t Finish()
virtual void Clear(Option_t *option="")
User defined functions.
vector< fgt_g2t_auxil > mG2tHitList[kFgtMxDisk+1][kFgtMxQuad]
accepted track segements
virtual void Clear(Option_t *option="")
User defined functions.
Definition: StMaker.cxx:634
Definition: Stypes.h:40
.... utility c-struct for g2t hits
TVector3 Rloc
hit entrance in LAB
virtual Int_t Finish()
Definition: StMaker.cxx:776
g2t_fgt_hit_st * hitPtr
entrance &amp; path in local ref frame