EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
EtmAzimuthalScan.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file EtmAzimuthalScan.cc
1 
2 #include <assert.h>
3 
4 #include <TRandom.h>
5 #include <TFile.h>
6 
7 #include <EicToyModel.h>
8 #include <EtmAzimuthalScan.h>
9 
10 #ifdef _BFIELD_
11 #include <BeastMagneticField.h>
12 #endif
13 
14 // ---------------------------------------------------------------------------------------
15 // ---------------------------------------------------------------------------------------
16 
17 EtmAzimuthalScan::EtmAzimuthalScan(double etamin, double etamax, unsigned ntheta, unsigned nphi):
18  mEtaMin(etamin), mEtaMax(etamax), mVertexSigma(0.0), mBfield(0.0), mBfieldScanStep(1 * etm::cm),
19  mThetaBinCount(ntheta), mPhiBinCount(nphi), mStat(100), mBeastMagneticField(0)
20 {
22  if (!mPhiBinCount) mPhiBinCount = 1;
23 } // EtmAzimuthalScan::EtmAzimuthalScan()
24 
25 // ---------------------------------------------------------------------------------------
26 
27 //
28 // These two will cancel each other;
29 //
30 
32 {
33  mBfield = field;
34 
35 #ifdef _BFIELD_
36  delete mBeastMagneticField;
38 #endif
39 
40  return this;
41 } // EtmAzimuthalScan::SetBfield()
42 
44 {
45  // Otherwise do nothing;
46 #ifdef _BFIELD_
48  // Turn linear interpolation on;
51 
52  mBfield = 0.0;
53  } //if
54 #endif
55 
56  return this;
57 } // EtmAzimuthalScan::SetBfield()
58 
59 // ---------------------------------------------------------------------------------------
60 
61 TVector3 EtmAzimuthalScan::GetBfield(const TVector3 &xx) const
62 {
63 #ifdef _BFIELD_
65  double bx, by, bz;
66  bool ok = mBeastMagneticField->GetFieldValue(xx[0], xx[1], xx[2], bx, by, bz);
67  if (ok) return TVector3(bx, by, bz);
68 
69  return TVector3(0,0,0);
70  } //if
71 #endif
72 
73  // Last resort: constant field;
74  return TVector3(0.0, 0.0, mBfield);
75 } // EtmAzimuthalScan::GetBfield()
76 
77 // ---------------------------------------------------------------------------------------
78 
79 void EtmAzimuthalScan::DoIt(const char *fout)
80 {
81  auto eic = EicToyModel::Instance();
82  auto model = eic->GetVacuumChamber()->GetWorld();
83 
84  // So yes, for now assume only endcaps are of interest;
85  assert(mEtaMin*mEtaMax > 0.0);
86  auto stack = mEtaMin > 0.0 ? eic->fwd() : eic->bck();
87  auto marker = stack->get(_MARKER_); if (marker->IsDummy()) return;
88 
89  bool eside = mEtaMin < 0.0;
90  double sign = (eside ? -1 : 1);
91  // The global location in the IR;
92  double zmarker = marker ? sign*marker->GetActualDistance() + eic->GetIpLocation().X() : 0.0;
93 
94  double crossing = eside ? 0.0 : eic->GetCrossingAngle();
95  double thetamin = Eta2Theta(fabs(mEtaMin > 0.0 ? mEtaMax : mEtaMin));
96  double thetamax = Eta2Theta(fabs(mEtaMin > 0.0 ? mEtaMin : mEtaMax));
97  double thetastep = (thetamax - thetamin)/mThetaBinCount;
98  double phistep = 2*M_PI/mPhiBinCount;
99 
100  // [eta, phi]; FIXME: memory leak;
101  mRL = new TH2D("RL", "RL", mPhiBinCount, -M_PI, M_PI, mThetaBinCount, thetamin*1000, thetamax*1000);
102  mZL = new TH2D("ZL", "ZL", mPhiBinCount, -M_PI, M_PI, mThetaBinCount, thetamin*1000, thetamax*1000);
103  mBdl = new TH2D("Bdl", "Bdl", mPhiBinCount, -M_PI, M_PI, mThetaBinCount, thetamin*1000, thetamax*1000);
104 
105  // If vertex smearing is not required, scan is deterministic -> stat=1;
106  unsigned qstat = mVertexSigma ? mStat : 1;
107 
108  for(unsigned itheta=0; itheta<mThetaBinCount; itheta++) {
109  double theta = thetamin + (itheta+0.5)*thetastep;
110 
111  for(unsigned iphi=0; iphi<mPhiBinCount; iphi++) {
112  double phi = -M_PI + (iphi+0.5)*phistep;
113 
114  // FIXME: this should be written better;
115  double nn[3] = {sin(theta)*cos(phi), sin(theta)*sin(phi), sign*cos(theta)};
116  if (!eside) {
117  // '-' sign here: want to "look along the outgoing beam line" for both
118  // electron and hadron cases;
119  double qnn[3] = {-sin(theta)*cos(phi), sin(theta)*sin(phi), sign*cos(theta)};
120  // By hand, the easiest;
121  nn[0] = qnn[0]*cos(crossing) + qnn[2]*sin(crossing);
122  nn[1] = qnn[1];
123  nn[2] = -qnn[0]*sin(crossing) + qnn[2]*cos(crossing);
124  } //if
125 
126  double accu = 0.0, thicku = 0.0, zair = 0.0, bdl = 0.0;
127 
128  for(unsigned ev=0; ev<qstat; ev++) {
129  TVector3 curr;
130  double xx[3] = {0.0, 0.0, eic->GetIpLocation().X() + gRandom->Gaus(0.0, mVertexSigma)};
131 
132  model->SetCurrentPoint (xx);
133  model->SetCurrentDirection(nn);
134 
135  for(auto node = model->GetCurrentNode(); ; ) {
136  auto material = node->GetVolume()->GetMaterial();
137 
138  model->FindNextBoundary();
139  double thickness = model->GetStep();
140  double radlen = material->GetRadLen();
141  //if (material != model->GetMaterial("Vacuum")) {
142  if (material != model->GetMaterial(_ACCELERATOR_VACUUM_) &&
143  material != model->GetMaterial(_UNIVERSE_VACUUM_)) {
144  thicku += thickness;
145  accu += thickness / radlen;
146  } //if
147  // Switch to next node along {xx, nn[]} 3D line;
148  node = model->Step();
149 
150  //if (material != model->GetMaterial("Vacuum"))
151  //curr = model->GetCurrentPoint();
152  // FIXME: do it better later;
153  if (material == model->GetMaterial("Be") ||
154  material == model->GetMaterial("Al"))
155  curr = model->GetCurrentPoint();
156 
157  //assert(model->IsEntering());
158 
159  // Once out of volume, break;
160  if (model->IsOutside()) break;
161  } //for inf
162 
163  zair += curr[2];
164 
165  // Magnetic field scan;
166  if (marker) {
167  double btsum = 0.0;
168  TVector3 x0 = curr, n0(nn);
169 
170  for(unsigned ist=0; ; ist++) {
171  TVector3 pt = x0 + ist*mBfieldScanStep*n0;
172  if (fabs(pt[2]) > fabs(zmarker)) break;
173 
174  TVector3 B = GetBfield(pt);
175  double scal = n0*B;
176  TVector3 Bt = B - scal*n0;
177 
178  btsum += mBfieldScanStep*Bt.Mag();
179  } //for inf
180 
181  bdl += btsum;
182  }
183  } //for ev
184 
185  accu /= qstat; thicku /= qstat; zair /= qstat; bdl /= qstat;
186 
187  if (marker) {
188  double zbudget = sign*(zmarker - zair); if (zbudget < 0.0) zbudget = 0.0;
189 
190  mZL ->SetBinContent(iphi+1, itheta+1, zbudget);
191  mBdl->SetBinContent(iphi+1, itheta+1, bdl/100);
192  } //if
193 
194  mRL->SetBinContent(iphi+1, itheta+1, accu*100);
195  } //for iphi
196  } //for itheta
197 
198  {
199  TFile hfile(fout ? fout : (TString(eic->GetName()) + ".scan.root").Data(), "RECREATE");
200 
201  mRL->Write(); mZL->Write(); mBdl->Write();
202 
203  hfile.Close();
204  }
205 } // EtmAzimuthalScan::DoIt()
206 
207 // ---------------------------------------------------------------------------------------
208 // ---------------------------------------------------------------------------------------
209