FairShip
Loading...
Searching...
No Matches
GenieGenerator.cxx
Go to the documentation of this file.
1// SPDX-License-Identifier: LGPL-3.0-or-later
2// SPDX-FileCopyrightText: Copyright CERN for the benefit of the SHiP
3// Collaboration
4
5#include "GenieGenerator.h"
6
7#include <cmath>
8
9#include "FairPrimaryGenerator.h"
10#include "MeanMaterialBudget.h"
11#include "TFile.h"
12#include "TGeoCompositeShape.h"
13#include "TGeoEltu.h"
14#include "TGeoManager.h"
15#include "TGeoNode.h"
16#include "TGeoVolume.h"
17#include "TMath.h"
18#include "TROOT.h"
19#include "TRandom.h"
20#include "TSystem.h"
21
22using std::cout;
23using std::endl;
24// read events from ntuples produced with GENIE
25// http://genie.hepforge.org/manuals/GENIE_PhysicsAndUserManual_20130615.pdf
26// Genie momentum GeV
27// Vertex in SI units, assume this means m
28// important to read back number of events to give to FairRoot
29
30// ----- Default constructor -------------------------------------------
32// -------------------------------------------------------------------------
33// ----- Default constructor -------------------------------------------
34Bool_t GenieGenerator::Init(const char* fileName) { return Init(fileName, 0); }
35// ----- Default constructor -------------------------------------------
36Bool_t GenieGenerator::Init(const char* fileName, const int startEvent) {
37 fNuOnly = false;
38 fInputFile = TFile::Open(fileName);
39 LOG(info) << "Opening input file " << fileName;
40 if (!fInputFile) {
41 LOG(fatal) << "Error opening input file.";
42 return kFALSE;
43 }
44 fTree = dynamic_cast<TTree*>(fInputFile->Get("gst"));
45 fNevents = fTree->GetEntries();
46 fn = startEvent;
47 fTree->SetBranchAddress("Ev", &Ev); // incoming neutrino energy
48 fTree->SetBranchAddress("pxv", &pxv);
49 fTree->SetBranchAddress("pyv", &pyv);
50 fTree->SetBranchAddress("pzv", &pzv);
51 fTree->SetBranchAddress("neu", &neu); // incoming neutrino PDG code
52 fTree->SetBranchAddress("cc", &cc); // Is it a CC event?
53 fTree->SetBranchAddress("nuel", &nuel); // Is it a NUEEL event?
54 fTree->SetBranchAddress("vtxx", &vtxx); // vertex in SI units
55 fTree->SetBranchAddress("vtxy", &vtxy);
56 fTree->SetBranchAddress("vtxz", &vtxz);
57 fTree->SetBranchAddress("vtxt", &vtxt);
58 fTree->SetBranchAddress("El", &El); // outgoing lepton momentum
59 fTree->SetBranchAddress("pxl", &pxl);
60 fTree->SetBranchAddress("pyl", &pyl);
61 fTree->SetBranchAddress("pzl", &pzl);
62 fTree->SetBranchAddress("Ef", &Ef); // outgoing hadronic momenta
63 fTree->SetBranchAddress("pxf", &pxf);
64 fTree->SetBranchAddress("pyf", &pyf);
65 fTree->SetBranchAddress("pzf", &pzf);
66 fTree->SetBranchAddress("nf", &nf); // nr of outgoing hadrons
67 fTree->SetBranchAddress("pdgf", &pdgf); // pdg code of hadron
68 fFirst = kTRUE;
69 return kTRUE;
70}
71// -------------------------------------------------------------------------
72std::vector<double> GenieGenerator::Rotate(Double_t x, Double_t y, Double_t z,
73 Double_t px, Double_t py,
74 Double_t pz) {
75 // rotate vector px,py,pz to point at x,y,z at origin.
76 Double_t theta = atan(sqrt(x * x + y * y) / z);
77 Double_t c = cos(theta);
78 Double_t s = sin(theta);
79 // rotate around y-axis
80 Double_t px1 = c * px + s * pz;
81 Double_t pzr = -s * px + c * pz;
82 Double_t phi = atan2(y, x);
83 c = cos(phi);
84 s = sin(phi);
85 // rotate around z-axis
86 Double_t pxr = c * px1 - s * py;
87 Double_t pyr = s * px1 + c * py;
88 // cout << "Info GenieGenerator: rotated" << pxr << " " << pyr << " "
89 // << pzr << " " << x << " " << y << " " << z <<endl;
90 return {pxr, pyr, pzr};
91}
92
93// ----- Destructor ----------------------------------------------------
95 fInputFile->Close();
96 fInputFile->Delete();
97 delete fInputFile;
98}
99// -------------------------------------------------------------------------
100void GenieGenerator::AddBox(TVector3 dVec, TVector3 box) {
101 dVecs.push_back(dVec);
102 m_boxes.push_back(box);
103 cout << "Debug GenieGenerator: " << dVec.X() << " " << box.Z() << endl;
104}
105// ----- Passing the event ---------------------------------------------
106Bool_t GenieGenerator::OldReadEvent(FairPrimaryGenerator* cpg) {
107 if (fFirst) {
108 TGeoVolume* top = gGeoManager->GetTopVolume();
109 TGeoNode* linner = top->FindNode("lidT1I_1");
110 TGeoNode* scint = top->FindNode("lidT1lisci_1");
111 TGeoNode* louter = top->FindNode("lidT1O_1");
112 TGeoNode* lidT6I = top->FindNode("lidT6I_1");
113 TGeoNode* t2I = top->FindNode("T2I_1");
114 TGeoNode* t1I = top->FindNode("T1I_1");
115 TGeoEltu* temp = dynamic_cast<TGeoEltu*>(linner->GetVolume()->GetShape());
116 fEntrDz_inner = temp->GetDZ();
117 temp = dynamic_cast<TGeoEltu*>(louter->GetVolume()->GetShape());
118 fEntrDz_outer = temp->GetDZ();
119 fEntrA = temp->GetA();
120 fEntrB = temp->GetB();
121 fEntrZ_inner = linner->GetMatrix()->GetTranslation()[2];
122 fEntrZ_outer = louter->GetMatrix()->GetTranslation()[2];
123 Lvessel =
124 lidT6I->GetMatrix()->GetTranslation()[2] - fEntrZ_inner - fEntrDz_inner;
125 TGeoCompositeShape* tempC =
126 dynamic_cast<TGeoCompositeShape*>(t2I->GetVolume()->GetShape());
127 Xvessel = tempC->GetDX() - 2 * fEntrDz_inner;
128 Yvessel = tempC->GetDY() - 2 * fEntrDz_inner;
129 tempC = dynamic_cast<TGeoCompositeShape*>(t1I->GetVolume()->GetShape());
130 fL1z = tempC->GetDZ() * 2;
131 temp = dynamic_cast<TGeoEltu*>(scint->GetVolume()->GetShape());
132 fScintDz = temp->GetDZ() * 2;
133 cout << "Info GenieGenerator: geo inner " << fEntrDz_inner << " "
134 << fEntrZ_inner << endl;
135 cout << "Info GenieGenerator: geo outer " << fEntrDz_outer << " "
136 << fEntrZ_outer << endl;
137 cout << "Info GenieGenerator: A and B " << fEntrA << " " << fEntrB << endl;
138 cout << "Info GenieGenerator: vessel length heig<ht width " << Lvessel
139 << " " << Yvessel << " " << Xvessel << endl;
140 cout << "Info GenieGenerator: scint thickness " << fScintDz << endl;
141 cout << "Info GenieGenerator: rextra " << fScintDz / 2. + 2 * fEntrDz_inner
142 << " " << 2 * fEntrDz_outer << " " << 2 * fEntrDz_inner << endl;
143 for (size_t j = 0; j < m_boxes.size(); j++) {
144 cout << "Info GenieGenerator: nuMu X" << j << " - "
145 << -m_boxes[j].X() + dVecs[j].X() << " "
146 << m_boxes[j].X() + dVecs[j].X() << endl;
147 cout << "Info GenieGenerator: nuMu Y" << j << " - "
148 << -m_boxes[j].Y() + dVecs[j].Y() << " "
149 << m_boxes[j].Y() + dVecs[j].Y() << endl;
150 cout << "Info GenieGenerator: nuMu Z" << j << " - "
151 << -m_boxes[j].Z() + dVecs[j].Z() << " "
152 << m_boxes[j].Z() + dVecs[j].Z() << endl;
153 }
154 fFirst = kFALSE;
155 }
156 if (fn == fNevents) {
157 LOG(warning) << "End of input file. Rewind.";
158 }
159 fTree->GetEntry(fn % fNevents);
160 fn++;
161 if (fn % 1000 == 0) {
162 cout << "Info GenieGenerator: neutrino event-nr " << fn << endl;
163 }
164 // generate a random point on the vessel, take veto z, and calculate outer lid
165 // position
166 // Double_t Yvessel=500.;
167 // Double_t Lvessel=5.*Yvessel+3500.;
168 // Double_t ztarget=zentrance-6350.;
169 // Double_t ea=250.; //inside inner wall vessel
170 Double_t eb = Yvessel; // inside inner wall vessel
171 Double_t x;
172 Double_t y;
173 Double_t z;
174 Double_t where = gRandom->Uniform(0., 1.);
175 if (where < 0.03) {
176 // point on entrance lid
177 Double_t ellip = 2.;
178 while (ellip > 1.) {
179 x = gRandom->Uniform(-fEntrA, fEntrA);
180 y = gRandom->Uniform(-fEntrB, fEntrB);
181 ellip = (x * x) / (fEntrA * fEntrA) + (y * y) / (fEntrB * fEntrB);
182 }
183 if (gRandom->Uniform(0., 1.) < 0.5) {
184 z = fEntrZ_inner + gRandom->Uniform(-fEntrDz_inner, fEntrDz_inner);
185 } else {
186 z = fEntrZ_outer + gRandom->Uniform(-fEntrDz_outer, fEntrDz_outer);
187 }
188 } else if (where < 0.64) {
189 // point on tube, place over 1 cm radius at 2 radii, separated by 10. cm
190 // first vessel has smaller size
191 Double_t ea = Xvessel;
192 Double_t zrand = gRandom->Uniform(0, Lvessel);
193 if (zrand < fL1z) {
194 ea = fEntrA;
195 }
196 z = fEntrZ_outer - fEntrDz_outer + zrand;
197 Double_t theta = gRandom->Uniform(0., TMath::Pi());
198 Double_t rextra;
199 if (gRandom->Uniform(0., 1.) > 0.5) {
200 // outer vessel
201 rextra = fScintDz / 2. + 2 * fEntrDz_inner +
202 gRandom->Uniform(0, 2 * fEntrDz_outer);
203 } else {
204 // inner vessel
205 rextra = gRandom->Uniform(0., 2 * fEntrDz_inner);
206 }
207 x = (ea + rextra) * cos(theta);
208 y = sqrt(1. - (x * x) / ((ea + rextra) * (ea + rextra))) * (eb + rextra);
209 if (gRandom->Uniform(-1., 1.) > 0.) y = -y;
210 } else {
211 // point in nu-tau detector area
212 int j = static_cast<int>(gRandom->Uniform(0., m_boxes.size() + 0.5));
213 x = gRandom->Uniform(-m_boxes[j].X() + dVecs[j].X(),
214 m_boxes[j].X() + dVecs[j].X());
215 y = gRandom->Uniform(-m_boxes[j].Y() + dVecs[j].Y(),
216 m_boxes[j].Y() + dVecs[j].Y());
217 z = gRandom->Uniform(-m_boxes[j].Z() + dVecs[j].Z(),
218 m_boxes[j].Z() + dVecs[j].Z());
219 }
220 // first, incoming neutrino
221 // rotate the particle
222 Double_t zrelative = z - ztarget;
223 // cout << "Info GenieGenerator: x,y,z " << x <<" " << y << " " << zrelative
224 // << endl; cout << "Info GenieGenerator: neutrino " << neu << "p-in "<< pxv
225 // << pyv << pzv << " nf "<< nf << endl;
226 std::vector<double> pout = Rotate(x, y, zrelative, pxv, pyv, pzv);
227 // cpg->AddTrack(neu,pxv,pyv,pzv,vtxx,vtxy,vtxz,-1,false);
228 // cout << "Info GenieGenerator: neutrino " << neu << "p-rot "<< pout[0] << "
229 // fn "<< fn << endl;
230 cpg->AddTrack(neu, pout[0], pout[1], pout[2], x, y, z, -1, false);
231
232 // second, outgoing lepton
233 pout = Rotate(x, y, zrelative, pxl, pyl, pzl);
234 Int_t oLPdgCode = neu;
235 if (cc) {
236 oLPdgCode = copysign(TMath::Abs(neu) - 1, neu);
237 }
238 if (nuel) {
239 oLPdgCode = 11;
240 }
241 cpg->AddTrack(oLPdgCode, pout[0], pout[1], pout[2], x, y, z, 0, true);
242 // last, all others
243 for (int i = 0; i < nf; i++) {
244 pout = Rotate(x, y, zrelative, pxf[i], pyf[i], pzf[i]);
245 cpg->AddTrack(pdgf[i], pout[0], pout[1], pout[2], x, y, z, 0, true);
246 // cout << "f " << pdgf[i] << " pz "<< pzf[i] << endl;
247 }
248
249 return kTRUE;
250}
251
252// ----- Passing the event ---------------------------------------------
253Bool_t GenieGenerator::ReadEvent(FairPrimaryGenerator* cpg) {
254 // some start/end positions in z (emulsion to Tracker 1)
255 Double_t start[3] = {0., 0., startZ};
256 Double_t end[3] = {0., 0., endZ};
257 char ts[20];
258 // cout << "Enter GenieGenerator " << endl;
259 // pick histogram: 1100=100 momentum bins, 1200=25 momentum bins.
260 Int_t idbase = 1200;
261 if (fFirst) {
262 Double_t bparam = 0.;
263 Double_t mparam[10];
264 bparam = shipgen::MeanMaterialBudget(start, end, mparam);
265 cout << "Info GenieGenerator: MaterialBudget " << start[2] << " - "
266 << end[2] << endl;
267 cout << "Info GenieGenerator: MaterialBudget " << bparam << endl;
268 cout << "Info GenieGenerator: MaterialBudget 0 " << mparam[0] << endl;
269 cout << "Info GenieGenerator: MaterialBudget 1 " << mparam[1] << endl;
270 cout << "Info GenieGenerator: MaterialBudget 2 " << mparam[2] << endl;
271 cout << "Info GenieGenerator: MaterialBudget 3 " << mparam[3] << endl;
272 cout << "Info GenieGenerator: MaterialBudget 4 " << mparam[4] << endl;
273 cout << "Info GenieGenerator: MaterialBudget 5 " << mparam[5] << endl;
274 cout << "Info GenieGenerator: MaterialBudget 6 " << mparam[6] << endl;
275 cout << "Info GenieGenerator: MaterialBudget " << mparam[0] * mparam[4]
276 << endl;
277 // read the (log10(p),log10(pt)) hists to be able to draw a pt for every
278 // neutrino momentum loop over neutrino types
279 printf("Reading (log10(p),log10(pt)) Hists from file: %s\n",
280 fInputFile->GetName());
281 for (Int_t idnu = 12; idnu < 17; idnu += 2) {
282 for (Int_t idadd = -1; idadd < 2; idadd += 2) {
283 Int_t idhnu = static_cast<int>(idbase + idnu);
284 if (idadd < 0) idhnu += 1000;
285 sprintf(ts, "%d", idhnu);
286 // pickup corresponding (log10(p),log10(pt)) histogram
287 if (fInputFile->FindObjectAny(ts)) {
288 TH2* h2tmp = dynamic_cast<TH2*>(fInputFile->Get(ts));
289 printf("HISTID=%d, Title:%s\n", idhnu, h2tmp->GetTitle());
290 sprintf(ts, "px_%d", idhnu);
291 // make its x-projection, to later be able to convert log10(p) to its
292 // bin-number
293 pxhist[idhnu] = h2tmp->ProjectionX(ts, 1, -1);
294 Int_t nbinx = h2tmp->GetNbinsX();
295 // printf("idhnu=%d ts=%s nbinx=%d\n",idhnu,ts,nbinx);
296 // project all slices on the y-axis
297 for (Int_t k = 1; k < nbinx + 1; k += 1) {
298 sprintf(ts, "h%d%d", idhnu, k);
299 // printf("idnu %d idhnu %d bin%d ts=%s\n",idnu,idhnu,k,ts);
300 pyslice[idhnu][k] = h2tmp->ProjectionY(ts, k, k);
301 }
302 }
303 }
304 }
305 fFirst = kFALSE;
306 }
307
308 if (fn == fNevents) {
309 LOG(warning) << "End of input file. Rewind.";
310 }
311 fTree->GetEntry(fn % fNevents);
312 fn++;
313 if (fn % 100 == 0) {
314 cout << "Info GenieGenerator: neutrino event-nr " << fn << endl;
315 }
316
317 // Incoming neutrino, get a random px,py
318 // cout << "Info GenieGenerator: neutrino " << neu << "p-in "<< pzv << " nf
319 // "<< nf << endl; cout << "Info GenieGenerator: ztarget " << ztarget << endl;
320 Double_t mparam[10];
321 Double_t pout[3] = {0., 0., -1.};
322 Double_t txnu = 0;
323 Double_t tynu = 0;
324 // Does this neutrino fly through material? Otherwise draw another pt..
325 // cout << "Info GenieGenerator Start bparam while loop" << endl;
326 while (pout[2] < 0.) {
327 //***OLD**** Keep for comparison maybe??
328 // generate pt of ~0.3 GeV
329 // pout[0] = gRandom->Exp(0.2);
330 // pout[1] = gRandom->Exp(0.2);
331 // pout[2] = pzv*pzv-pout[0]*pout[0]-pout[1]*pout[1];
332
333 //**NEW** get pt of this neutrino from 2D hists.
334 Int_t idhnu = TMath::Abs(neu) + idbase;
335 if (neu < 0) idhnu += 1000;
336 Int_t nbinmx = pxhist[idhnu]->GetNbinsX();
337 Double_t pl10 = log10(pzv);
338 Int_t nbx = pxhist[idhnu]->FindBin(pl10);
339 // printf("idhnu %d, p %f log10(p) %f bin,binmx %d %d
340 // \n",idhnu,pzv,pl10,nbx,nbinmx);
341 if (nbx < 1) nbx = 1;
342 if (nbx > nbinmx) nbx = nbinmx;
343 Double_t ptlog10 = pyslice[idhnu][nbx]->GetRandom();
344 // hist was filled with: log10(pt+0.01)
345 Double_t pt = pow(10., ptlog10) - 0.01;
346 // rotate pt in phi:
347 Double_t phi = gRandom->Uniform(0., 2 * TMath::Pi());
348 pout[0] = cos(phi) * pt;
349 pout[1] = sin(phi) * pt;
350 pout[2] = pzv * pzv - pt * pt;
351 // printf("p= %f pt=%f
352 // px,py,pz**2=%f,%f,%f\n",pzv,pt,pout[0],pout[1],pout[2]);
353
354 if (pout[2] >= 0.) {
355 pout[2] = TMath::Sqrt(pout[2]);
356 if (gRandom->Uniform(-1., 1.) < 0.) pout[0] = -pout[0];
357 if (gRandom->Uniform(-1., 1.) < 0.) pout[1] = -pout[1];
358 // cout << "Info GenieGenerator: neutrino pxyz " << pout[0] << ", " <<
359 // pout[1] << ", " << pout[2] << endl;
360 // xyz at start and end
361 start[0] = (pout[0] / pout[2]) * (start[2] - ztarget);
362 start[1] = (pout[1] / pout[2]) * (start[2] - ztarget);
363 // cout << "Info GenieGenerator: neutrino xyz-start " << start[0] << "-"
364 // << start[1] << "-" << start[2] << endl;
365 txnu = pout[0] / pout[2];
366 tynu = pout[1] / pout[2];
367 end[0] = txnu * (end[2] - ztarget);
368 end[1] = tynu * (end[2] - ztarget);
369 // cout << "Info GenieGenerator: neutrino xyz-end " << end[0] << "-" <<
370 // end[1] << "-" << end[2] << endl; get material density between these two
371 // points
372 shipgen::MeanMaterialBudget(start, end, mparam);
373 // printf("param %e %e %e \n",bparam,mparam[6],mparam[7]);
374 }
375 }
376 // loop over trajectory between start and end to pick an interaction point
377 Double_t prob2int = -1.;
378 Double_t x = 0.;
379 Double_t y = 0.;
380 Double_t z = 0.;
381 while (prob2int < gRandom->Uniform(0., 1.)) {
382 // place x,y,z uniform along path
383 z = gRandom->Uniform(start[2], end[2]);
384 x = txnu * (z - ztarget);
385 y = tynu * (z - ztarget);
386 if (mparam[6] < 0.5) {
387 // mparam is number of boundaries along path. mparam[6]=0.: uniform
388 // material budget along path, use present x,y,z
389 prob2int = 2.;
390 } else {
391 // get local material at this point, to calculate probability that
392 // interaction is at this point.
393 TGeoNode* node = gGeoManager->FindNode(x, y, z);
394 TGeoMaterial* mat = nullptr;
395 if (node && !gGeoManager->IsOutside()) {
396 mat = node->GetVolume()->GetMaterial();
397 // cout << "Info GenieGenerator: mat " << count << ", " <<
398 // mat->GetName() << ", " << mat->GetDensity() << endl; density relative
399 // to Prob largest density along this trajectory, i.e. use rho(Pt)
400 prob2int = mat->GetDensity() / mparam[7];
401 if (prob2int > 1.)
402 cout << "***WARNING*** GenieGenerator: prob2int > Maximum density????"
403 << prob2int << " maxrho:" << mparam[7]
404 << " material: " << mat->GetName() << endl;
405 } else {
406 prob2int = 0.;
407 }
408 }
409 }
410 // cout << "Info GenieGenerator: prob2int " << prob2int << ", " << count <<
411 // endl;
412
413 Double_t zrelative = z - ztarget;
414 Double_t tof = TMath::Sqrt(x * x + y * y + zrelative * zrelative) /
415 2.99792458e+10; // speed of light in cm/s
416 cpg->AddTrack(
417 neu, pout[0], pout[1], pout[2], x, y, z, -1, false,
418 TMath::Sqrt(pout[0] * pout[0] + pout[1] * pout[1] + pout[2] * pout[2]),
419 tof, mparam[0] * mparam[4]);
420 if (!fNuOnly) {
421 // second, outgoing lepton
422 std::vector<double> pp = Rotate(x, y, zrelative, pxl, pyl, pzl);
423 Int_t oLPdgCode = neu;
424 if (cc) {
425 oLPdgCode = copysign(TMath::Abs(neu) - 1, neu);
426 }
427 if (nuel) {
428 oLPdgCode = 11;
429 }
430 cpg->AddTrack(oLPdgCode, pp[0], pp[1], pp[2], x, y, z, 0, true, El, tof,
431 mparam[0] * mparam[4]);
432 // last, all others
433 for (int i = 0; i < nf; i++) {
434 pp = Rotate(x, y, zrelative, pxf[i], pyf[i], pzf[i]);
435 cpg->AddTrack(pdgf[i], pp[0], pp[1], pp[2], x, y, z, 0, true, Ef[i], tof,
436 mparam[0] * mparam[4]);
437 // cout << "f " << pdgf[i] << " pz "<< pzf[i] << endl;
438 }
439 // cout << "Info GenieGenerator Return from GenieGenerator" << endl;
440 }
441 return kTRUE;
442}
443// -------------------------------------------------------------------------
Double_t ztarget
Double_t pzf[500]
std::vector< TVector3 > m_boxes
Double_t Lvessel
Double_t Xvessel
Double_t fEntrZ_inner
std::vector< double > Rotate(Double_t x, Double_t y, Double_t z, Double_t px, Double_t py, Double_t pz)
~GenieGenerator() override
Double_t fEntrDz_outer
Double_t fEntrZ_outer
Bool_t ReadEvent(FairPrimaryGenerator *) override
Int_t pdgf[500]
std::vector< TVector3 > dVecs
TH1D * pxhist[3000]
Double_t pxf[500]
Bool_t OldReadEvent(FairPrimaryGenerator *)
Bool_t Init(const char *, int) override
Double_t pyf[500]
void AddBox(TVector3 dVec, TVector3 box)
TFile * fInputFile
don't make it persistent, magic ROOT command
TH1D * pyslice[3000][100]
Double_t fEntrDz_inner
Double_t fScintDz
Double_t Ef[500]
Double_t Yvessel
double MeanMaterialBudget(std::span< const double, 3 > start, std::span< const double, 3 > end, std::span< double, 10 > mparam)