Class Reference for E1039 Core & Analysis Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
SQPrimaryVertexGen.C
Go to the documentation of this file.
1 /*====================================================================
2 Author: Abinash Pun, Kun Liu
3 Sep, 2019
4 Goal: Import the primary vertex generator of E906 experiment(DPVertexGenerator)
5 from Kun to E1039 experiment in Fun4All framework
6 =========================================================================*/
7 
8 #include <iostream>
9 #include <phgeom/PHGeomUtility.h>
10 #include <TGeoTube.h>
11 #include <TGeoManager.h>
12 #include <TGeoBBox.h>
13 #include <TRandom3.h>
14 #include <TMath.h>
15 #include <TFile.h>
16 #include <phool/PHRandomSeed.h>
17 #include "SQPrimaryVertexGen.h"
18 //#include "SQBeamlineObject.h"
19 
21 {
22 inited = false;
23 
24 }
26 
28 
29 }
30 
32 {
33  beam_profile= true;
34  beamProfile = NULL;
35  beamProfile = new TF2("beamProfile", "exp(-0.5*(x-[0])*(x-[0])/[1]/[1])*exp(-0.5*(y-[2])*(y-[2])/[3]/[3])", -10., 10., -10., 10.);
36  beamProfile->SetParameter(0, 0.0);
37  beamProfile->SetParameter(1, 0.68);
38  beamProfile->SetParameter(2, 0.0);
39  beamProfile->SetParameter(3, 0.76);
40 
41  gRandom->SetSeed(PHRandomSeed());
42  // beamProfile = new TF2("beamProfile", "exp(-0.5*(x-0.)*(x-0.)/0.414/0.414)*exp(-0.5*(y-0.)*(y-0.)/0.343/0.343)", -10., 10., -10., 10.);
43 
44  nPieces=0;
45 
46 }
47 
48 void SQPrimaryVertexGen::traverse(TGeoNode* node, double&xvertex,double&yvertex,double&zvertex)
49 {
50  if(node == NULL) return;
51 
52  //Generate perpendicular vtx by sampling beam profile or random guassian
53  double x=0.;
54  double y=0.;
55 
56  generateVtxPerp(x, y);
57 
58 
59 
60  for(int i = 0; i < node->GetNdaughters(); ++i) // Loop over daughter volumes
61  {
62 
63  TGeoVolume* pv= node->GetDaughter(i)->GetVolume();
64  TGeoMatrix* mat= node->GetDaughter(i)->GetMatrix();
65  const Double_t* pos= mat->GetTranslation();
66 
67  TGeoVolumeMulti* pv_multi;
68  pv_multi = (TGeoVolumeMulti*)pv;
69 
70  TGeoShape *shape = pv->GetShape();
71  TGeoTube* tube;
72  TGeoBBox* box;
73  tube= (TGeoTube*)shape;
74  box=(TGeoBBox*)shape;
75 
76  // Select those volumes in beamline; not beyond FMAG and not ahead of collimator
77  if(fabs(pos[0]) > 1. || fabs(pos[1]) > 7.|| pos[2]>500. || pos[2]<-800.) continue;
78 
79  if (node->GetDaughter(i)->GetNdaughters()==0){ // Condition for the volumes with zero subvolumes starts
80 
81  TString name = pv->GetName();
82  SQBeamlineObject newObj= SQBeamlineObject(pv->GetMaterial());
83 
84  newObj.name = name;
85  newObj.z0 = pos[2];
86 
87  if(name.Contains("Shielding"))
88  {
89  newObj.length = 2.*box->GetDZ();
90  newObj.z_down = newObj.z0 + 0.5*newObj.length;
91  newObj.z_up = newObj.z0 - 0.5*newObj.length;
92 
93  if (x*x+y*y<5.*5.){//Manually get a hole of 10 cm for all shieldings
94  newObj.nucIntLen = 65932.038;
95  newObj.density = 0.001;
96  newObj.A = 14.364;
97  newObj.Z = 7.179;
98  newObj.N = newObj.A-newObj.Z;
99  }
100  }
101  else // only gets target
102  {
103  newObj.length = 2.*tube->GetDZ();
104  newObj.z_down = newObj.z0 + 0.5*newObj.length;
105  newObj.z_up = newObj.z0 - 0.5*newObj.length;
106  newObj.radiusX = tube->GetRmax();//outer radius
107  newObj.radiusY = newObj.radiusX;
108 
109  if (x*x+y*y>1.*1.){//to make sure target is not contributing beyond its dimenstion (20 mm diameter)
110  newObj.nucIntLen = 65932.038;
111  newObj.density = 0.001;
112  newObj.A = 14.364;
113  newObj.Z = 7.179;
114  newObj.N = newObj.A-newObj.Z;
115  }
116 
117  }
118 
119  interactables.push_back(newObj);
120 
121  }//Condition for the volumes with zero subvolumes ends
122 
123  if(node->GetDaughter(i)->GetNdaughters()>0){ //Condition for volumes with multiple subvolumes starts
124 
125  for(int j=0; j<node->GetDaughter(i)->GetNdaughters();++j){ // Loop for the subvolumes Starts
126 
127  TGeoVolume* pv1= node->GetDaughter(i)->GetDaughter(j)->GetVolume();
128  TGeoMatrix* mat1= node->GetDaughter(i)->GetDaughter(j)->GetMatrix();
129  const Double_t* pos1= mat1->GetTranslation();
130 
131  TGeoShape *shape1 = pv1->GetShape();
132  TGeoTube* tube1;
133  TGeoBBox* box1;
134  tube1= (TGeoTube*)shape1;
135  box1=(TGeoBBox*)shape1;
136 
137 
138  // choose those volumes in beamlines
139  if(fabs(pos1[0]+pos[0]) > 1. || fabs(pos1[1]+pos[1]) > 1.|| (pos1[2]+pos[2])>500.) continue;
140 
141  TString name = pv1->GetName();
142  SQBeamlineObject newObj1= SQBeamlineObject(pv1->GetMaterial());
143 
144  newObj1.name = name;
145  newObj1.z0 = pos1[2]+pos[2];
146 
147  if(name.Contains("fmag"))
148  {
149 
150  newObj1.length = 2.*box1->GetDZ();
151  newObj1.z_down = newObj1.z0 + 0.5*newObj1.length;
152  newObj1.z_up = newObj1.z0 - 0.5*newObj1.length + 10.*2.54;// Drilling a hole with air upto 25 cm
153  newObj1.length = newObj1.length - 10.*2.54;
154  newObj1.radiusX = 500.;
155  newObj1.radiusY = 500.;
156 
157  //Manually hard coded by Abi for Iron
158  // newObj1.nucIntLen = 16.77;
159  // newObj1.density = 7.87;
160  // newObj1.A = 55.845;
161  // newObj1.Z = 26;
162  // newObj1.N = newObj1.A-newObj1.Z;
163  }
164 
165  else{//gets the collimeter (depending upon the upstream cut)
166 
167  newObj1.length = 2.*box1->GetDZ();
168  newObj1.z_down = newObj1.z0 + 0.5*newObj1.length;
169  newObj1.z_up = newObj1.z0 - 0.5*newObj1.length;
170 
171  if (fabs(x)<3.9 && fabs(y)<1.7){//Manually get a rectangular hole
172  newObj1.nucIntLen = 65932.038;
173  newObj1.density = 0.001;
174  newObj1.A = 14.364;
175  newObj1.Z = 7.179;
176  newObj1.N = newObj1.A-newObj1.Z;
177  }
178 
179  // continue;
180  }
181  interactables.push_back(newObj1);
182  } // Loop for the subvolumes Ends
183 
184  std::sort(interactables.begin(), interactables.end());
185 
186  } //Condition for volumes with multiple subvolumes Ends
187 
188  }
189 
190  //sort the vectors by position
191  std::sort(interactables.begin(), interactables.end());
192 
193 
194  //===Fill the gaps betwen the volumes with air
195  TGeoMaterial* air = new TGeoMaterial("Air");
196  SQBeamlineObject airgap(air);
197  int nGaps = 0;
198  unsigned int n_temp = interactables.size();
199  for(unsigned int i = 1; i < n_temp; ++i)
200  {
201  if(fabs(interactables[i-1].z_down - interactables[i].z_up) < 0.1) continue;
202 
203  airgap.z_up = interactables[i-1].z_down;
204  airgap.z_down = interactables[i].z_up;
205  airgap.z0 = 0.5*(airgap.z_up + airgap.z_down);
206  airgap.length = airgap.z_down - airgap.z_up;
207  airgap.name = Form("AirGap_%d", nGaps++);
208  airgap.A = 14.364;
209  airgap.Z= 7.179;
210  airgap.N= airgap.A- airgap.Z;
211  airgap.nucIntLen = 65932.038;
212  airgap.density=0.001;
213 
214  interactables.push_back(airgap);
215  }
216  std::sort(interactables.begin(), interactables.end());
217 
218 
219  //===set the quanties that rely on its neighbours
220  double attenuationSum = 0.;
221  for(unsigned int i = 0; i < interactables.size(); ++i)
222  {
223  interactables[i].attenuationSelf = 1. - TMath::Exp(-interactables[i].length/interactables[i].nucIntLen);
224  interactables[i].attenuation = (1. - attenuationSum)*interactables[i].attenuationSelf;
225  interactables[i].prob = interactables[i].attenuation*interactables[i].density*interactables[i].nucIntLen;
226 
227  attenuationSum += interactables[i].attenuation;
228 
229  }
230 
231  //===set the accumulatedProbs
232  nPieces = interactables.size();
233 
234  interactables[0].accumulatedProb = 0.;
235  accumulatedProbs[0] = 0.;
236  for(unsigned int i = 1; i < nPieces; ++i)
237  {
238  interactables[i].accumulatedProb = interactables[i-1].accumulatedProb + interactables[i-1].prob;
239  accumulatedProbs[i] = interactables[i].accumulatedProb;
240  }
241 
242  accumulatedProbs[nPieces] = accumulatedProbs[nPieces-1] + interactables.back().prob;
243  probSum = accumulatedProbs[nPieces];
244 
245 
246  //===Normalize the accumulated probability
247  for(int i = 0; i < nPieces+1; ++i)
248  {
249  accumulatedProbs[i] = accumulatedProbs[i]/accumulatedProbs[nPieces];
250 
251  }
252 
253  // for(int i = 0; i < nPieces; ++i)
254  // {
255  // std::cout << i << " " << interactables[i] << std::endl;
256  // std::cout<<"=====Accumulated Probs=="<<accumulatedProbs[i]<<std::endl;
257  // }
258 
259  //===Generate vertices and store them
260  double vtx = generateVertex();
261  xvertex= x;
262  yvertex= y;
263  zvertex= vtx;
264 
265  interactables.clear(); //clear the vector in order to run the multiple events ; Abi
266 
267 }
268 
269 
270 //==============
272 {
273 
275 
276  //Generate z-vtx
277  double zOffset =0.;
278  double z = interactables[index].getZ() + zOffset;
279 
280  return z;
281 }
282 
283 void SQPrimaryVertexGen::generateVtxPerp(double& x, double& y)
284 {
285  if(beam_profile)
286  {
287  beamProfile->GetRandom2(x, y);
288  }
289  else
290  {
291  x=gRandom->Gaus(0.,0.414);
292  y=gRandom->Gaus(0.,0.343);
293  }
294 }
295 
297 {
298  //randomly find the index based on their accum probs
299  index = TMath::BinarySearch(nPieces+1, accumulatedProbs,gRandom->Uniform(0,1));
300 
301 }
void traverse(TGeoNode *node, double &xvertex, double &yvertex, double &zvertex)
double nucIntLen
radiusY
double Z
density in g/cm3
#define NULL
Definition: Pdb.h:9
double length
the z position of upstram/downstream face and center
double density
nuclear interaction length in cm
void InitRun(PHCompositeNode *topNode)
void generateVtxPerp(double &x, double &y)
double radiusX
length of the stuff
double radiusY
radiusX