StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
StEpdFastSim.cxx
1 #include "./StEpdFastSim.h"
2 #include "TClonesArray.h"
3 #include "TRandom3.h"
4 #include "../StEpdGeom.h"
5 #include "TVector3.h"
6 #include "TMath.h"
7 //#include "../../StPicoEvent/StPicoEpdHit.h" <---- on your laptop, need explicit path.
8 #include "StRoot/StPicoEvent/StPicoEpdHit.h"
9 #include <iostream>
10 
11 StEpdFastSim::StEpdFastSim(double WID){
12  mRan = new TRandom3();
13  mRan->SetSeed();
14 
15  mTheHits = new TClonesArray("StPicoEpdHit",1000);
16 
17  mGeom = new StEpdGeom();
18  mWID = WID;
19 
20 
21  // set look-up table for ring radii....
22  double xcorner[5],ycorner[5];
23  int ncorners;
24  // first, INNERMOST of ring 1
25  mGeom->GetCorners(1,1,0,&ncorners,xcorner,ycorner);
26 
27  double rmin(200.0);
28  mGeom->GetCorners(1,1,0,&ncorners,xcorner,ycorner);
29  for (int icorn=0; icorn<ncorners; icorn++){
30  double rad = sqrt(pow(xcorner[icorn],2)+pow(ycorner[icorn],2));
31  if (rad<rmin) rmin=rad;
32  }
33  RingRadii[0] = rmin;
34  // from now on, I am finding the OUTERMOST radii of the rings
35  for (int Ring=1; Ring<=16; Ring++){
36  int TT = Ring*2 - 1;
37  mGeom->GetCorners(1,TT,0,&ncorners,xcorner,ycorner);
38  double rmax(0.0);
39  for (int icorn=0; icorn<ncorners; icorn++){
40  double rad = sqrt(pow(xcorner[icorn],2)+pow(ycorner[icorn],2));
41  if (rad>rmax) rmax=rad;
42  }
43  RingRadii[Ring]=rmax;
44  }
45 
46 }
47 
48 
49 StEpdFastSim::~StEpdFastSim(){
50  /* no op */
51 }
52 
53 
54 /* =================================================================================================== */
55 TClonesArray* StEpdFastSim::GetPicoHits(TClonesArray* momenta, TVector3 PrimVertex){
56  double zEPD=375.0; // cm
57  if (fabs(PrimVertex.Z()>zEPD) || fabs(PrimVertex.X()>0.5) || fabs(PrimVertex.Y()>0.5)){
58  std::cout << "Invalid vertex --- I'm giving you an empty event - Tchau!\n";
59  return 0;
60  }
61 
62  // important!
63  for (int uniqueID=101; uniqueID<1232; uniqueID++){
64  mHitsEast[uniqueID] = 0;
65  mHitsWest[uniqueID] = 0;
66  }
67 
68  mTheHits->Clear();
69 
70  // TClonesArray* theHits = new TClonesArray("StPicoEpdHit",1000);
71 
72  for (int itrk=0; itrk<momenta->GetEntries(); itrk++){
73  // project to EPD...
74  TVector3* mom = (TVector3*)momenta->At(itrk);
75  int EW = (mom->Z()<0.0)?0:1;
76  double zWheel = (mom->Z()<0.0)?-zEPD:zEPD; // east or west
77  double deltaZ = abs(zWheel-PrimVertex.Z()); // how far to project -- the abs is important!!
78 
79  double xHit = PrimVertex.X() + deltaZ*fabs(tan(mom->Theta()))*cos(mom->Phi());//Fixed bug: sin(theta)->fabs(tan(theta)) Xiaoyu Liu 03/09/2021
80  double yHit = PrimVertex.Y() + deltaZ*fabs(tan(mom->Theta()))*sin(mom->Phi());//Xiaoyu Liu 03/09/2021
81  TVector3 xyHit(xHit,yHit,zWheel);
82 
83  short UniqueID = FindStruckTile(xyHit); // returns the unique ID of the struck tile (see comments in StEpdHit), or zero if the EPD is not struck at all.
84 
85  if (UniqueID==0){
86  // cout << "Huh, this hit missed the EPD altogether!\n";
87  continue;
88  }
89 
90  float dE = mRan->Landau(1.0,mWID); // energy loss to add to the hit. This is added to nMIP
91 
92  StPicoEpdHit* theHit;
93  if (EW<=0) { // east
94  if (mHitsEast[abs(UniqueID)]!=0){ // this tile has already been struck -- ADD to the nMIP value of this existing StPicoEpdHit
95  theHit = mHitsEast[abs(UniqueID)];
96  float nMIP = theHit->nMIP() + dE;
97  theHit->setnMIP(nMIP);
98  }
99  else{ // this tile has not yet been struck-- make a StPicoEpdHit
100  theHit = (StPicoEpdHit*)mTheHits->ConstructedAt(mTheHits->GetEntriesFast());
101  theHit->setId(UniqueID);
102  theHit->setnMIP(dE);
103  theHit->setQTdata(pow(2,30));//w/o this step, theHit->nMIP() will return zero. Xiaoyu Liu 03/09/2021
104  mHitsEast[abs(UniqueID)] = theHit;
105  }
106  }
107  else{ // west
108  if (mHitsWest[abs(UniqueID)]!=0){ // this tile has already been struck -- ADD to the nMIP value of this existing StPicoEpdHit
109  theHit = mHitsWest[abs(UniqueID)];
110  float nMIP = theHit->nMIP() + dE;
111  theHit->setnMIP(nMIP);
112  }
113  else{ // this tile has not yet been struck-- make a StPicoEpdHit
114  theHit = (StPicoEpdHit*)mTheHits->ConstructedAt(mTheHits->GetEntriesFast());
115  theHit->setId(UniqueID);
116  theHit->setnMIP(dE);
117  theHit->setQTdata(pow(2,30));//w/o this step, theHit->nMIP() will return zero. Xiaoyu Liu 03/09/2021
118  mHitsWest[abs(UniqueID)] = theHit;
119  }
120  }
121  } // end loop over particles
122 
123  return mTheHits;
124 }
125 
126 /* =====================================================================================================================
127  Find the tile that is struck, and return its unique ID
128  you know, you might think to set up a quick "boundaries of the tiles" and quickly find which tile was hit...
129  but if you want to do it right, and you want to allow for arbitrary primary vertex, then I'm afraid it is
130  a bit less trivial. Before you try to get more "clever" than what I've done below, think about it...
131 */
132 short StEpdFastSim::FindStruckTile(TVector3 xyHit){
133  int PPmapWest[12] = {10,11,12,1,2,3,4,5,6,7,8,9}; // the index here is iphi (see below) and the value is PP number
134  int PPmapEast[12] = {3,2,1,12,11,10,9,8,7,6,5,4}; // the index here is iphi (see below) and the value is PP number
135  double PhiCenterWest[12] = {1.8326,2.35619,2.87979,3.40339,3.92699,4.45059,4.97419,5.49779,6.02139,0.261799,0.785398,1.309}; // index here is (PP-1) and value is phi of center of SS
136  double PhiCenterEast[12] = {1.309,0.785398,0.261799,6.02139,5.49779,4.97419,4.45059,3.92699,3.40339,2.87979,2.35619,1.8326}; // index here is (PP-1) and value is phi of center of SS
137 
138  int EW = (xyHit.Z()<0)?0:1;
139 
140  // find ring based on radius
141  double rHit = xyHit.Perp();
142  if (rHit<RingRadii[0]) return 0; //{std::cout << "Hit goes thru hole\n"; return 0;} // hit is smaller radius than EPD inner radius (not necessarily a bug)
143  if (rHit>RingRadii[16])return 0; //{std::cout << "Hit too large radius\n"; return 0;} // hit is bigger radius than EPD outer radius (not necessarily a bug)
144  int iRing;
145  for (iRing=1; iRing<=16; iRing++){
146  if (rHit<RingRadii[iRing]) break; // got it
147  }
148 
149  // now find PP based on phi
150  double phiHit = xyHit.Phi();
151  if (phiHit<0.0) phiHit += 2.0*TMath::Pi();
152  int iphi = (int)(phiHit/(2.0*TMath::Pi()/12.0));
153  int PP = (EW<=0)?PPmapEast[iphi]:PPmapWest[iphi];
154 
155  // now find TT based on ring and on phi
156  int TT;
157  if (iRing==1){
158  TT=1;
159  }
160  else{
161  if (EW<=0){ // on the East wheel, if phiHit is larger than the average phi of the supersector, then TT is the LARGER of the two possibilities
162  if (phiHit>PhiCenterEast[PP-1]) {TT=2*(iRing-1) + 1;}
163  else {TT=2*(iRing-1);}
164  }
165  else{ // on the West wheel, if phiHit is larger than the average phi of the supersector, then TT is the SMALLER of the two possibilities
166  if (phiHit>PhiCenterWest[PP-1]) {TT=2*(iRing-1);}
167  else {TT=2*(iRing-1) + 1;}
168 
169  }
170  }
171 
172  // Finally, return the UniqueID of the tile
173  int uniqueID = 100*PP+TT;
174  if (EW<=0) uniqueID*=-1;
175 
176  // std::cout << "EW,Ring,PP,TT = " << EW << " " << iRing << " " << PP << " " << TT << " rHIT,phi = " << rHit << " " << phiHit << "\n";
177 
178  /* and, you know, if you really wanted to be careful, and take account of the gaps between tiles, you would do a
179  * if (!(mGeom->IsInTile(UniqueID,xyHit.X(),yyHit.Y()))) return 0;
180  * I imagine we'll want to skip this, but it can be done, just like that.
181  */
182 
183  return uniqueID;
184 }
185 
186 
187 
Definition: T.h:18
void setnMIP(Float_t nMIP)
Definition: StPicoEpdHit.h:123
void setId(Short_t id)
Definition: StPicoEpdHit.h:121
void setQTdata(Int_t packedData)
Definition: StPicoEpdHit.h:118
Float_t nMIP() const
Definition: StPicoEpdHit.h:104