SND@LHC Software
Loading...
Searching...
No Matches
GenieGenerator.cxx
Go to the documentation of this file.
1#include <math.h>
2#include "TSystem.h"
3#include "TROOT.h"
4#include "TMath.h"
5#include "TFile.h"
6#include "TRandom.h"
7#include "TCut.h"
8#include "TEventList.h"
9#include "FairPrimaryGenerator.h"
10#include "GenieGenerator.h"
11#include "TGeoVolume.h"
12#include "TGeoNode.h"
13#include "TGeoManager.h"
14#include "TGeoEltu.h"
15#include "TGeoCompositeShape.h"
16#include "TParticle.h"
17#include "TClonesArray.h"
18#include "FairMCEventHeader.h"
19
20using std::cout;
21using std::endl;
22// read events from ntuples produced with GENIE
23// http://genie.hepforge.org/manuals/GENIE_PhysicsAndUserManual_20130615.pdf
24// Genie momentum GeV
25// Vertex in SI units, assume this means m
26// important to read back number of events to give to FairRoot
27
28// ----- Default constructor -------------------------------------------
30 fGenOption = 0; //default value, standard Genie Generator used in SHiP
31}
32// -------------------------------------------------------------------------
33// ----- Default constructor -------------------------------------------
34Bool_t GenieGenerator::Init(const char* fileName) {
35 return Init(fileName, 0);
36}
37// ----- Default constructor -------------------------------------------
38Bool_t GenieGenerator::Init(const char* fileName, const int firstEvent) {
39 fNuOnly = false;
40 fcrossingangle = 0.; //default value, no xsec angle
41 if (0 == strncmp("/eos",fileName,4) ) {
42 TString tmp = gSystem->Getenv("EOSSHIP");
43 tmp+=fileName;
44 fInputFile = TFile::Open(tmp);
45 LOGF(info, "Opening input file on eos %s", tmp.Data());
46 }else{
47 fInputFile = new TFile(fileName);
48 LOGF(info, "Opening input file %s", fileName);
49 }
50 if (fInputFile->IsZombie() or !fInputFile) {
51 LOG(FATAL) << "Error opening input file";
52 return kFALSE; }
53 fTree = (TTree *)fInputFile->Get("gst");
54 fNevents = fTree->GetEntries();
55 fn = firstEvent;
56 fTree->SetBranchAddress("FlukaRun",&runN); // run number
57 fTree->SetBranchAddress("evtNumber",&eventN); // event number
58 fTree->SetBranchAddress("Ev",&Ev); // incoming neutrino energy
59 fTree->SetBranchAddress("pxv",&pxv);
60 fTree->SetBranchAddress("pyv",&pyv);
61 fTree->SetBranchAddress("pzv",&pzv);
62 fTree->SetBranchAddress("neu",&neu); // incoming neutrino PDG code
63 fTree->SetBranchAddress("cc",&cc); // Is it a CC event?
64 fTree->SetBranchAddress("nuel",&nuel); // Is it a NUEEL event?
65 fTree->SetBranchAddress("vtxx",&vtxx); // vertex in SI units
66 fTree->SetBranchAddress("vtxy",&vtxy);
67 fTree->SetBranchAddress("vtxz",&vtxz);
68 fTree->SetBranchAddress("vtxt",&vtxt);
69 fTree->SetBranchAddress("El",&El); // outgoing lepton momentum
70 fTree->SetBranchAddress("pxl",&pxl);
71 fTree->SetBranchAddress("pyl",&pyl);
72 fTree->SetBranchAddress("pzl",&pzl);
73 fTree->SetBranchAddress("Ef",&Ef); // outgoing hadronic momenta
74 fTree->SetBranchAddress("pxf",&pxf);
75 fTree->SetBranchAddress("pyf",&pyf);
76 fTree->SetBranchAddress("pzf",&pzf);
77 fTree->SetBranchAddress("nf",&nf); // nr of outgoing hadrons
78 fTree->SetBranchAddress("pdgf",&pdgf); // pdg code of hadron
79
80 if (fGenOption < 0 || fGenOption > 3){
81 LOG(FATAL) <<"Invalid GenieGen Option: "<<fGenOption<<" Please check the option provided with --Genie "<<endl;
82 return kFALSE;
83 }
84 if (fGenOption == 1){
85 fFLUKANuTree = (TTree *)fInputFile->Get("fluka_neutrinos_selected");
86 //check if TTree is actually present
87 if (!fFLUKANuTree){
88 LOG(FATAL) <<"No TTree of interacting neutrinos present. Did you run extract_interacting_neutrinos.py from the macro folder?";
89 return kFALSE;
90 }
91 fNevents = fFLUKANuTree->GetEntries();
92 //setting branches for input neutrino tree.
93 //Nota Bene: I get only the angles and positions,
94 //for the energy I keep the GENIE one, otherwise I lose energy conservation
95 fFLUKANuTree->SetBranchAddress("x_cos",&FLUKA_x_cos);
96 fFLUKANuTree->SetBranchAddress("y_cos",&FLUKA_y_cos);
97 fFLUKANuTree->SetBranchAddress("x",&FLUKA_x);
98 fFLUKANuTree->SetBranchAddress("y",&FLUKA_y);
99 fDeltaE_GenieFLUKA_nu = 10.; //Default value for energy range of FLUKA->Genie matching, 10 GeV.
100 }
101 if (fGenOption == 2){ //pythia tree
102 ancstr = new TClonesArray("TParticle");
103 fFLUKANuTree = (TTree*)fInputFile->Get("NuTauTree");
104 fNevents = fFLUKANuTree->GetEntries();
105 fFLUKANuTree->SetBranchAddress("Ancstr",&ancstr);
106 fDeltaE_GenieFLUKA_nu = 10.; //Default value for energy range of FLUKA->Genie matching, 10 GeV.
107 }
108 fFirst=kTRUE;
109 return kTRUE;
110}
111// -------------------------------------------------------------------------
112Double_t GenieGenerator::MeanMaterialBudget(const Double_t *start, const Double_t *end, Double_t *mparam)
113{
114 //
115 // Calculate mean material budget and material properties between
116 // the points "start" and "end".
117 //
118 // "mparam" - parameters used for the energy and multiple scattering
119 // corrections:
120 //
121 // mparam[0] - mean density: sum(x_i*rho_i)/sum(x_i) [g/cm3]
122 // mparam[1] - equivalent rad length fraction: sum(x_i/X0_i) [adimensional]
123 // mparam[2] - mean A: sum(x_i*A_i)/sum(x_i) [adimensional]
124 // mparam[3] - mean Z: sum(x_i*Z_i)/sum(x_i) [adimensional]
125 // mparam[4] - length: sum(x_i) [cm]
126 // mparam[5] - Z/A mean: sum(x_i*Z_i/A_i)/sum(x_i) [adimensional]
127 // mparam[6] - number of boundary crosses
128 // mparam[7] - maximum density encountered (g/cm^3)
129 // mparam[8] - equivalent interaction length fraction: sum(x_i/I0_i) [adimensional]
130 // mparam[9] - maximum cross section encountered (mbarn)
131 //
132 // Origin: Marian Ivanov, Marian.Ivanov@cern.ch
133 //
134 // Corrections and improvements by
135 // Andrea Dainese, Andrea.Dainese@lnl.infn.it,
136 // Andrei Gheata, Andrei.Gheata@cern.ch
137 // Thomas Ruf, Thomas.Ruf@cern.ch
138 //
139
140 mparam[0]=0; mparam[1]=1; mparam[2]=0; mparam[3]=0; mparam[4]=0;
141 mparam[5]=0; mparam[6]=0; mparam[7]=0; mparam[8]=0; mparam[9]=0;
142 //
143 Double_t bparam[7]; // total parameters
144 Double_t lparam[7]; // local parameters
145 Double_t mbarn = 1E-3*1E-24*TMath::Na(); // cm^2 * Avogadro
146
147 for (Int_t i=0;i<7;i++) bparam[i]=0;
148
149 if (!gGeoManager) {
150 //AliFatalClass("No TGeo\n");
151 return 0.;
152 }
153 //
154 Double_t length;
155 Double_t dir[3];
156 length = TMath::Sqrt((end[0]-start[0])*(end[0]-start[0])+
157 (end[1]-start[1])*(end[1]-start[1])+
158 (end[2]-start[2])*(end[2]-start[2]));
159 mparam[4]=length;
160 if (length<TGeoShape::Tolerance()) return 0.0;
161 Double_t invlen = 1./length;
162 dir[0] = (end[0]-start[0])*invlen;
163 dir[1] = (end[1]-start[1])*invlen;
164 dir[2] = (end[2]-start[2])*invlen;
165
166 // Initialize start point and direction
167 TGeoNode *currentnode = 0;
168 TGeoNode *startnode = gGeoManager->InitTrack(start, dir);
169 if (!startnode) {
170 //AliErrorClass(Form("start point out of geometry: x %f, y %f, z %f",
171 // start[0],start[1],start[2]));
172 return 0.0;
173 }
174 TGeoMaterial *material = startnode->GetVolume()->GetMedium()->GetMaterial();
175 lparam[0] = material->GetDensity();
176 if (lparam[0] > mparam[7]) mparam[7]=lparam[0];
177 lparam[1] = material->GetRadLen();
178 lparam[2] = material->GetA();
179 lparam[3] = material->GetZ();
180 lparam[4] = length;
181 lparam[5] = lparam[3]/lparam[2];
182 lparam[6] = material->GetIntLen();
183 Double_t n = lparam[0]/lparam[2];
184 Double_t sigma = 1./(n*lparam[6])/mbarn;
185 if (sigma > mparam[9]) mparam[9]=sigma;
186 if (material->IsMixture()) {
187 TGeoMixture * mixture = (TGeoMixture*)material;
188 lparam[5] =0;
189 Double_t sum =0;
190 for (Int_t iel=0;iel<mixture->GetNelements();iel++){
191 sum += mixture->GetWmixt()[iel];
192 lparam[5]+= mixture->GetZmixt()[iel]*mixture->GetWmixt()[iel]/mixture->GetAmixt()[iel];
193 }
194 lparam[5]/=sum;
195 }
196
197 // Locate next boundary within length without computing safety.
198 // Propagate either with length (if no boundary found) or just cross boundary
199 gGeoManager->FindNextBoundaryAndStep(length, kFALSE);
200 Double_t step = 0.0; // Step made
201 Double_t snext = gGeoManager->GetStep();
202 // If no boundary within proposed length, return current density
203 if (!gGeoManager->IsOnBoundary()) {
204 mparam[0] = lparam[0];
205 mparam[1] = lparam[4]/lparam[1];
206 mparam[2] = lparam[2];
207 mparam[3] = lparam[3];
208 mparam[4] = lparam[4];
209 mparam[8] = lparam[4]/lparam[6];
210 return lparam[0];
211 }
212 // Try to cross the boundary and see what is next
213 Int_t nzero = 0;
214 while (length>TGeoShape::Tolerance()) {
215 currentnode = gGeoManager->GetCurrentNode();
216 if (snext<2.*TGeoShape::Tolerance()) nzero++;
217 else nzero = 0;
218 if (nzero>3) {
219 // This means navigation has problems on one boundary
220 // Try to cross by making a small step
221 //AliErrorClass("Cannot cross boundary\n");
222 mparam[0] = bparam[0]/step;
223 mparam[1] = bparam[1];
224 mparam[2] = bparam[2]/step;
225 mparam[3] = bparam[3]/step;
226 mparam[5] = bparam[5]/step;
227 mparam[8] = bparam[6];
228 mparam[4] = step;
229 mparam[0] = 0.; // if crash of navigation take mean density 0
230 mparam[1] = 1000000; // and infinite rad length
231 return bparam[0]/step;
232 }
233 mparam[6]+=1.;
234 step += snext;
235 bparam[1] += snext/lparam[1];
236 bparam[2] += snext*lparam[2];
237 bparam[3] += snext*lparam[3];
238 bparam[5] += snext*lparam[5];
239 bparam[6] += snext/lparam[6];
240 bparam[0] += snext*lparam[0];
241
242 if (snext>=length) break;
243 if (!currentnode) break;
244 length -= snext;
245 material = currentnode->GetVolume()->GetMedium()->GetMaterial();
246 lparam[0] = material->GetDensity();
247 if (lparam[0] > mparam[7]) mparam[7]=lparam[0];
248 lparam[1] = material->GetRadLen();
249 lparam[2] = material->GetA();
250 lparam[3] = material->GetZ();
251 lparam[5] = lparam[3]/lparam[2];
252 lparam[6] = material->GetIntLen();
253 n = lparam[0]/lparam[2];
254 sigma = 1./(n*lparam[6])/mbarn;
255 if (sigma > mparam[9]) mparam[9]=sigma;
256 if (material->IsMixture()) {
257 TGeoMixture * mixture = (TGeoMixture*)material;
258 lparam[5]=0;
259 Double_t sum =0;
260 for (Int_t iel=0;iel<mixture->GetNelements();iel++){
261 sum+= mixture->GetWmixt()[iel];
262 lparam[5]+= mixture->GetZmixt()[iel]*mixture->GetWmixt()[iel]/mixture->GetAmixt()[iel];
263 }
264 lparam[5]/=sum;
265 }
266 gGeoManager->FindNextBoundaryAndStep(length, kFALSE);
267 snext = gGeoManager->GetStep();
268 }
269 mparam[0] = bparam[0]/step;
270 mparam[1] = bparam[1];
271 mparam[2] = bparam[2]/step;
272 mparam[3] = bparam[3]/step;
273 mparam[5] = bparam[5]/step;
274 mparam[8] = bparam[6];
275 return bparam[0]/step;
276}
277
278std::vector<double> GenieGenerator::Rotate(Double_t x, Double_t y, Double_t z, Double_t px, Double_t py, Double_t pz)
279{
280 //rotate vector px,py,pz to point at x,y,z at origin.
281 Double_t theta=atan(sqrt(x*x+y*y)/z);
282 Double_t c=cos(theta);
283 Double_t s=sin(theta);
284 //rotate around y-axis
285 Double_t px1=c*px+s*pz;
286 Double_t pzr=-s*px+c*pz;
287 Double_t phi=atan2(y,x);
288 c=cos(phi);
289 s=sin(phi);
290 //rotate around z-axis
291 Double_t pxr=c*px1-s*py;
292 Double_t pyr=s*px1+c*py;
293 std::vector<double> pout;
294 pout.push_back(pxr);
295 pout.push_back(pyr);
296 pout.push_back(pzr);
297 //cout << "Info GenieGenerator: rotated" << pout[0] << " " << pout[1] << " " << pout[2] << " " << x << " " << y << " " << z <<endl;
298 return pout;
299}
300
301Int_t GenieGenerator::ExtractEvent_Ekin(Double_t Ekin, Double_t DeltaE){
302
303 //TCut nucut(Form("Ekin >= (%f - %f) && Ekin < (%f + %f)",Ekin,DeltaE/2., Ekin, DeltaE/2.));
304 //fFLUKANuTree->Draw(">>nulist", nucut );
305 TCut nucut(Form("pzv >= (%f - %f) && pzv < (%f + %f)",Ekin,DeltaE/2., Ekin, DeltaE/2.));
306 fTree->Draw(">>nulist",nucut);
307
308 TEventList *nulist = (TEventList*)gDirectory->GetList()->FindObject("nulist");
309 Int_t nselectedevents = nulist->GetN();
310 //integer function returns randomly integer between 0 e nselectedevents;
311 Int_t myevent = nulist->GetEntry(gRandom->Integer(nselectedevents+1));
312
313 nulist->Reset(); //resetting list for next call of the function.
314 return myevent;
315}
316
317
318// ----- Destructor ----------------------------------------------------
320{
321 fInputFile->Close();
322 fInputFile->Delete();
323 delete fInputFile;
324}
325// -------------------------------------------------------------------------
326void GenieGenerator::AddBox(TVector3 dVec, TVector3 box)
327{
328 dVecs.push_back(dVec);
329 boxs.push_back(box);
330 cout << "Debug GenieGenerator: "<< dVec.X() << " "<<box.Z() << endl;
331}
332// ----- Passing the event ---------------------------------------------
333Bool_t GenieGenerator::OldReadEvent(FairPrimaryGenerator* cpg)
334{
335 if (fFirst){
336 TGeoVolume *top=gGeoManager->GetTopVolume();
337 TGeoNode *linner = top->FindNode("lidT1I_1");
338 TGeoNode *scint = top->FindNode("lidT1lisci_1");
339 TGeoNode *louter = top->FindNode("lidT1O_1");
340 TGeoNode *lidT6I = top->FindNode("lidT6I_1");
341 TGeoNode *t2I = top->FindNode("T2I_1");
342 TGeoNode *t1I = top->FindNode("T1I_1");
343 TGeoEltu *temp = dynamic_cast<TGeoEltu*>(linner->GetVolume()->GetShape());
344 fEntrDz_inner = temp->GetDZ();
345 temp = dynamic_cast<TGeoEltu*>(louter->GetVolume()->GetShape());
346 fEntrDz_outer = temp->GetDZ();
347 fEntrA = temp->GetA();
348 fEntrB = temp->GetB();
349 fEntrZ_inner = linner->GetMatrix()->GetTranslation()[2];
350 fEntrZ_outer = louter->GetMatrix()->GetTranslation()[2];
351 Lvessel = lidT6I->GetMatrix()->GetTranslation()[2] - fEntrZ_inner - fEntrDz_inner;
352 TGeoCompositeShape *tempC = dynamic_cast<TGeoCompositeShape*>(t2I->GetVolume()->GetShape());
353 Xvessel = tempC->GetDX() - 2*fEntrDz_inner ;
354 Yvessel = tempC->GetDY() - 2*fEntrDz_inner ;
355 tempC = dynamic_cast<TGeoCompositeShape*>(t1I->GetVolume()->GetShape());
356 fL1z = tempC->GetDZ()*2;
357 temp = dynamic_cast<TGeoEltu*>(scint->GetVolume()->GetShape());
358 fScintDz = temp->GetDZ()*2;
359 cout << "Info GenieGenerator: geo inner " << fEntrDz_inner << " "<< fEntrZ_inner << endl;
360 cout << "Info GenieGenerator: geo outer " << fEntrDz_outer << " "<< fEntrZ_outer << endl;
361 cout << "Info GenieGenerator: A and B " << fEntrA << " "<< fEntrB << endl;
362 cout << "Info GenieGenerator: vessel length heig<ht width " << Lvessel << " "<<Yvessel<< " "<< Xvessel << endl;
363 cout << "Info GenieGenerator: scint thickness " << fScintDz << endl;
364 cout << "Info GenieGenerator: rextra " << fScintDz/2.+2*fEntrDz_inner << " "<< 2*fEntrDz_outer << " "<<2*fEntrDz_inner << endl;
365 for(int j=0; j<boxs.size(); j++) {
366 cout << "Info GenieGenerator: nuMu X" << j << " - "<< -boxs[j].X()+dVecs[j].X() << " "<< boxs[j].X()+dVecs[j].X() << endl;
367 cout << "Info GenieGenerator: nuMu Y" << j << " - "<< -boxs[j].Y()+dVecs[j].Y() << " "<< boxs[j].Y()+dVecs[j].Y() << endl;
368 cout << "Info GenieGenerator: nuMu Z" << j << " - "<< -boxs[j].Z()+dVecs[j].Z() << " "<< boxs[j].Z()+dVecs[j].Z() << endl;
369 }
370 fFirst = kFALSE;
371 }
372 if (fn==fNevents) {LOG(WARNING) << "End of input file. Rewind.";}
373 fTree->GetEntry(fn%fNevents);
374 fn++;
375 if (fn%1000==0) {
376 cout << "Info GenieGenerator: neutrino event-nr "<< fn << endl;
377 }
378// generate a random point on the vessel, take veto z, and calculate outer lid position
379 //Double_t Yvessel=500.;
380 //Double_t Lvessel=5.*Yvessel+3500.;
381 //Double_t ztarget=zentrance-6350.;
382 //Double_t ea=250.; //inside inner wall vessel
383 Double_t eb=Yvessel; //inside inner wall vessel
384 Double_t x;
385 Double_t y;
386 Double_t z;
387 Double_t where=gRandom->Uniform(0.,1.);
388 if (where<0.03) {
389 // point on entrance lid
390 Double_t ellip=2.;
391 while (ellip>1.){
392 x = gRandom->Uniform(-fEntrA,fEntrA);
393 y = gRandom->Uniform(-fEntrB,fEntrB);
394 ellip=(x*x)/(fEntrA*fEntrA)+(y*y)/(fEntrB*fEntrB);
395 }
396 if (gRandom->Uniform(0.,1.)<0.5){
397 z=fEntrZ_inner + gRandom->Uniform(-fEntrDz_inner,fEntrDz_inner);
398 }else{
399 z=fEntrZ_outer + gRandom->Uniform(-fEntrDz_outer,fEntrDz_outer);
400 }
401 }else if (where<0.64){
402 //point on tube, place over 1 cm radius at 2 radii, separated by 10. cm
403 // first vessel has smaller size
404 Double_t ea = Xvessel;
405 Double_t zrand = gRandom->Uniform(0,Lvessel);
406 if (zrand < fL1z){
407 ea = fEntrA;
408 }
409 z = fEntrZ_outer-fEntrDz_outer + zrand;
410 Double_t theta = gRandom->Uniform(0.,TMath::Pi());
411 Double_t rextra;
412 if ( gRandom->Uniform(0.,1.)>0.5) {
413 // outer vessel
414 rextra = fScintDz/2.+2*fEntrDz_inner + gRandom->Uniform(0,2*fEntrDz_outer);
415 }else{
416 // inner vessel
417 rextra = gRandom->Uniform(0.,2*fEntrDz_inner);
418 }
419 x = (ea+rextra)*cos(theta);
420 y = sqrt(1.-(x*x)/((ea+rextra)*(ea+rextra)))*(eb+rextra);
421 if (gRandom->Uniform(-1.,1.)>0.) y=-y;
422 }else{
423 //point in nu-tau detector area
424 int j = int(gRandom->Uniform(0.,boxs.size()+0.5));
425 x=gRandom->Uniform(-boxs[j].X()+dVecs[j].X(),boxs[j].X()+dVecs[j].X());
426 y=gRandom->Uniform(-boxs[j].Y()+dVecs[j].Y(),boxs[j].Y()+dVecs[j].Y());
427 z=gRandom->Uniform(-boxs[j].Z()+dVecs[j].Z(),boxs[j].Z()+dVecs[j].Z());
428 }
429// first, incoming neutrino
430 //rotate the particle
431 Double_t zrelative=z-ztarget;
432 //cout << "Info GenieGenerator: x,y,z " << x <<" " << y << " " << zrelative << endl;
433 //cout << "Info GenieGenerator: neutrino " << neu << "p-in "<< pxv << pyv << pzv << " nf "<< nf << endl;
434 std::vector<double> pout = Rotate(x,y,zrelative,pxv,pyv,pzv);
435 //cpg->AddTrack(neu,pxv,pyv,pzv,vtxx,vtxy,vtxz,-1,false);
436 //cout << "Info GenieGenerator: neutrino " << neu << "p-rot "<< pout[0] << " fn "<< fn << endl;
437 cpg->AddTrack(neu,pout[0],pout[1],pout[2],x,y,z,-1,false);
438
439
440// second, outgoing lepton
441 pout = Rotate(x,y,zrelative,pxl,pyl,pzl);
442 Int_t oLPdgCode = neu;
443 if (cc){oLPdgCode = copysign(TMath::Abs(neu)-1,neu);}
444 if (nuel){oLPdgCode = 11;}
445 cpg->AddTrack(oLPdgCode,pout[0],pout[1],pout[2],x,y,z,0,true);
446// last, all others
447 for(int i=0; i<nf; i++)
448 {
449 pout = Rotate(x,y,zrelative,pxf[i],pyf[i],pzf[i]);
450 cpg->AddTrack(pdgf[i],pout[0],pout[1],pout[2],x,y,z,0,true);
451 // cout << "f " << pdgf[i] << " pz "<< pzf[i] << endl;
452 }
453
454 return kTRUE;
455}
456
457// ----- Passing the event ---------------------------------------------
458Bool_t GenieGenerator::ReadEvent(FairPrimaryGenerator* cpg)
459{
460
461 if (fGenOption == 3){
462 // Use GENIE geometry driver.
463
464 // Get event from GENIE TTree. If we reach the end of the file, return false.
465 if (fTree->GetEntry(fn) == 0 ) return kFALSE;
466
467 if (fn%100==0) {
468 cout << "Info GenieGenerator: neutrino event-nr "<< fn << endl;
469 }
470
471 fn++;
472
473 // Add the neutrino to the MCTrack stack:
474 cpg->AddTrack(neu, // Neutrino PDG
475 pxv, pyv, pzv, // Neutrino momentum
476 vtxx*100, vtxy*100, vtxz*100, // Event vertex [in cm!]
477 -1, // Parent
478 false); // Don't track this particle
479
480 // Add final state lepton to the MCTrack stack:
481 int outgoing_lepton_pdg = neu;
482 if (cc) outgoing_lepton_pdg = copysign(TMath::Abs(neu)-1,neu);
483 if (nuel) outgoing_lepton_pdg = 11;
484
485 bool track_outgoing_lepton = (cc || nuel) ? true : false;
486 cpg->AddTrack(outgoing_lepton_pdg,
487 pxl, pyl, pzl,
488 vtxx*100, vtxy*100, vtxz*100,
489 0,
490 track_outgoing_lepton);
491
492 // Add final state hadrons to the MCTrack stack
493 for (int i_hadron = 0; i_hadron < nf; i_hadron++){
494 cpg->AddTrack(pdgf[i_hadron],
495 pxf[i_hadron], pyf[i_hadron], pzf[i_hadron],
496 vtxx*100, vtxy*100, vtxz*100,
497 0,
498 true);
499 }
500
501 // Set the generation run and event numbers through the MC event header
502 FairMCEventHeader* header = cpg->GetEvent();
503 header->SetEventID(eventN);
504 header->SetRunID(runN);
505
506 return kTRUE;
507
508 } else {
509 //some start/end positions in z (emulsion to Tracker 1)
510 Double_t start[3]={0.,0.,startZ};
511 Double_t end[3]={0.,0.,endZ};
512 char ts[20];
513 //cout << "Enter GenieGenerator " << endl;
514 //pick histogram: 1100=100 momentum bins, 1200=25 momentum bins.
515 Int_t idbase=1200;
516 if (fFirst){
517 Double_t bparam=0.;
518 Double_t mparam[10];
519 bparam=MeanMaterialBudget(start, end, mparam);
520 cout << "Info GenieGenerator: MaterialBudget " << start[2] << " - "<< end[2] << endl;
521 cout << "Info GenieGenerator: MaterialBudget " << bparam << endl;
522 cout << "Info GenieGenerator: MaterialBudget 0 " << mparam[0] << endl;
523 cout << "Info GenieGenerator: MaterialBudget 1 " << mparam[1] << endl;
524 cout << "Info GenieGenerator: MaterialBudget 2 " << mparam[2] << endl;
525 cout << "Info GenieGenerator: MaterialBudget 3 " << mparam[3] << endl;
526 cout << "Info GenieGenerator: MaterialBudget 4 " << mparam[4] << endl;
527 cout << "Info GenieGenerator: MaterialBudget 5 " << mparam[5] << endl;
528 cout << "Info GenieGenerator: MaterialBudget 6 " << mparam[6] << endl;
529 cout << "Info GenieGenerator: MaterialBudget " << mparam[0]*mparam[4] << endl;
530 //read the (log10(p),log10(pt)) hists to be able to draw a pt for every neutrino momentum
531 //loop over neutrino types
532 printf("Reading (log10(p),log10(pt)) Hists from file: %s\n",fInputFile->GetName());
533 for (Int_t idnu=12;idnu<17;idnu+=2){
534 for (Int_t idadd=-1;idadd<2;idadd+=2){
535 Int_t idhnu=idbase+idnu;
536 if (idadd<0) idhnu+=1000;
537 sprintf(ts,"%d",idhnu);
538 //pickup corresponding (log10(p),log10(pt)) histogram
539 if (fInputFile->FindObjectAny(ts)){
540 TH2F* h2tmp = (TH2F*) fInputFile->Get(ts);
541 printf("HISTID=%d, Title:%s\n",idhnu,h2tmp->GetTitle());
542 sprintf(ts,"px_%d",idhnu);
543 //make its x-projection, to later be able to convert log10(p) to its bin-number
544 pxhist[idhnu]=h2tmp->ProjectionX(ts,1,-1);
545 Int_t nbinx=h2tmp->GetNbinsX();
546 //printf("idhnu=%d ts=%s nbinx=%d\n",idhnu,ts,nbinx);
547 //project all slices on the y-axis
548 for (Int_t k=1;k<nbinx+1;k+=1){
549 sprintf(ts,"h%d%d",idhnu,k);
550 //printf("idnu %d idhnu %d bin%d ts=%s\n",idnu,idhnu,k,ts);
551 pyslice[idhnu][k]=h2tmp->ProjectionY(ts,k,k);
552 }
553 }
554 }
555 }
556 fFirst = kFALSE;
557 }
558 if (fn==fNevents) {LOG(WARNING) << "End of input file. Rewind.";}
559 if (fGenOption>0) fFLUKANuTree->GetEntry(fn%fNevents); //1 or 2
560 else if (fGenOption == 0) fTree->GetEntry(fn%fNevents);
561 fn++;
562 if (fn%100==0) {
563 cout << "Info GenieGenerator: neutrino event-nr "<< fn << endl;
564 }
565
566// Incoming neutrino, get a random px,py
567 //cout << "Info GenieGenerator: neutrino " << neu << "p-in "<< pzv << " nf "<< nf << endl;
568 //cout << "Info GenieGenerator: ztarget " << ztarget << endl;
569 Double_t bparam=0.;
570 Double_t mparam[10];
571 Double_t pout[3];
572 pout[2]=-1.;
573 Double_t txnu=0;
574 Double_t tynu=0;
575 //Does this neutrino fly through material? Otherwise draw another pt..
576 //cout << "Info GenieGenerator Start bparam while loop" << endl;
577 while (pout[2]<0.) {
578 //***OLD**** Keep for comparison maybe??
579 //generate pt of ~0.3 GeV
580 //pout[0] = gRandom->Exp(0.2);
581 //pout[1] = gRandom->Exp(0.2);
582 //pout[2] = pzv*pzv-pout[0]*pout[0]-pout[1]*pout[1];
583 if(fGenOption == 1){
584 int nuevent = ExtractEvent_Ekin(pzv, 10.);
585 fTree->GetEntry(nuevent);
586 //getting tri-momentum
587 pout[0] = FLUKA_x_cos * pzv;
588 pout[1] = FLUKA_y_cos * pzv;
589 double pt = sqrt(pout[0]*pout[0] + pout[1]*pout[1]);
590 pout[2] = pzv*pzv-pt*pt;
591 }
592 else if(fGenOption == 2){
593 //getting neutrino information
594 TParticle *nuparticle = (TParticle*) ancstr->At(0);
595 TVector3 * nup = new TVector3(nuparticle->Px(), nuparticle->Py(), nuparticle->Pz());
596 //rotating of xsec
597 nup->RotateX(fcrossingangle);
598 //getting associated interaction
599 int nuevent = ExtractEvent_Ekin(nup->Mag(), 10.);
600 fTree->GetEntry(nuevent);
601 //getting GENIE tri-momentum in this reference
602 pout[0] = nup->Px()/nup->Pz() * pzv;
603 pout[1] = nup->Py()/nup->Pz() * pzv;
604 double pt = sqrt(pout[0]*pout[0] + pout[1]*pout[1]);
605 pout[2] = pzv*pzv-pt*pt;
606 }
607
608 else if( fGenOption == 0 ){
609 //**NEW** get pt of this neutrino from 2D hists.
610 Int_t idhnu=TMath::Abs(neu)+idbase;
611 if (neu<0) idhnu+=1000;
612 Int_t nbinmx=pxhist[idhnu]->GetNbinsX();
613 Double_t pl10=log10(pzv);
614 Int_t nbx=pxhist[idhnu]->FindBin(pl10);
615 //printf("idhnu %d, p %f log10(p) %f bin,binmx %d %d \n",idhnu,pzv,pl10,nbx,nbinmx);
616 if (nbx<1) nbx=1;
617 if (nbx>nbinmx) nbx=nbinmx;
618 Double_t ptlog10=pyslice[idhnu][nbx]->GetRandom();
619 //hist was filled with: log10(pt+0.01)
620 Double_t pt=pow(10.,ptlog10)-0.01;
621 //rotate pt in phi:
622 Double_t phi=gRandom->Uniform(0.,2*TMath::Pi());
623 pout[0] = cos(phi)*pt;
624 pout[1] = sin(phi)*pt;
625 pout[2] = pzv*pzv-pt*pt;
626 //printf("p= %f pt=%f px,py,pz**2=%f,%f,%f\n",pzv,pt,pout[0],pout[1],pout[2]);
627 }
628 if (pout[2]>=0.) {
629 pout[2]=TMath::Sqrt(pout[2]);
630 //random chance of reflecting momentum, we do not modify momentum components in SND@LHC physics case
631 if (fGenOption == 0){
632 if (gRandom->Uniform(-1.,1.)<0.) pout[0]=-pout[0];
633 if (gRandom->Uniform(-1.,1.)<0.) pout[1]=-pout[1];
634 }
635 //cout << "Info GenieGenerator: neutrino pxyz " << pout[0] << ", " << pout[1] << ", " << pout[2] << endl;
636 // xyz at start and end
637 start[0]=(pout[0]/pout[2])*(start[2]-ztarget);
638 start[1]=(pout[1]/pout[2])*(start[2]-ztarget);
639 //adding offset from neutrino production point (only for SND@LHC physics case)
640 if (fGenOption == 1){
641 start[0] += FLUKA_x;
642 start[1] += FLUKA_y;
643 }
644 //cout << "Info GenieGenerator: neutrino xyz-start " << start[0] << "-" << start[1] << "-" << start[2] << endl;
645 txnu=pout[0]/pout[2];
646 tynu=pout[1]/pout[2];
647 end[0]=txnu*(end[2]-ztarget);
648 end[1]=tynu*(end[2]-ztarget);
649 //adding offset from neutrino production point (only for SND@LHC phys
650 if (fGenOption == 1){
651 end[0] += FLUKA_x;
652 end[1] += FLUKA_y;
653 }
654 //cout << "Info GenieGenerator: neutrino xyz-end " << end[0] << "-" << end[1] << "-" << end[2] << endl;
655 //get material density between these two points
656 bparam=MeanMaterialBudget(start, end, mparam);
657 //printf("param %e %e %e \n",bparam,mparam[6],mparam[7]);
658 }
659 }
660 //loop over trajectory between start and end to pick an interaction point
661 Double_t prob2int = -1.;
662 Double_t x;
663 Double_t y;
664 Double_t z;
665 Int_t count=0;
666 while (prob2int<gRandom->Uniform(0.,1.)) {
667 //place x,y,z uniform along path
668 z=gRandom->Uniform(start[2],end[2]);
669 x=txnu*(z-ztarget);
670 y=tynu*(z-ztarget);
671 //adding offset from neutrino production point (only for SND@LHC physics case)
672 if (fGenOption == 1){
673 x += FLUKA_x;
674 y += FLUKA_y;
675 }
676 if (mparam[6]<0.5){
677 //mparam is number of boundaries along path. mparam[6]=0.: uniform material budget along path, use present x,y,z
678 prob2int=2.;
679 }else{
680 //get local material at this point, to calculate probability that interaction is at this point.
681 TGeoNode *node = gGeoManager->FindNode(x,y,z);
682 TGeoMaterial *mat = 0;
683 if (node && !gGeoManager->IsOutside()) {
684 mat = node->GetVolume()->GetMaterial();
685 //cout << "Info GenieGenerator: mat " << count << ", " << mat->GetName() << ", " << mat->GetDensity() << endl;
686 //density relative to Prob largest density along this trajectory, i.e. use rho(Pt)
687 prob2int= mat->GetDensity()/mparam[7];
688 if (prob2int>1.) cout << "***WARNING*** GenieGenerator: prob2int > Maximum density????" << prob2int << " maxrho:" << mparam[7] << " material: " << mat->GetName() << endl;
689 count+=1;
690 }else{
691 prob2int=0.;
692 }
693 }
694 }
695 //cout << "Info GenieGenerator: prob2int " << prob2int << ", " << count << endl;
696
697 Double_t zrelative=z-ztarget;
698 Double_t tof=TMath::Sqrt(x*x+y*y+zrelative*zrelative)/2.99792458e+6;
699 cpg->AddTrack(neu,pout[0],pout[1],pout[2],x,y,z,-1,false,TMath::Sqrt(pout[0]*pout[0]+pout[1]*pout[1]+pout[2]*pout[2]),tof,mparam[0]*mparam[4]);
700 if (not fNuOnly){
701 // second, outgoing lepton
702 std::vector<double> pp = Rotate(x,y,zrelative,pxl,pyl,pzl);
703 Int_t oLPdgCode = neu;
704 if (cc){oLPdgCode = copysign(TMath::Abs(neu)-1,neu);}
705 if (nuel){oLPdgCode = 11;}
706 cpg->AddTrack(oLPdgCode,pp[0],pp[1],pp[2],x,y,z,0,true,El,tof,mparam[0]*mparam[4]);
707// last, all others
708 for(int i=0; i<nf; i++)
709 {
710 pp = Rotate(x,y,zrelative,pxf[i],pyf[i],pzf[i]);
711 cpg->AddTrack(pdgf[i],pp[0],pp[1],pp[2],x,y,z,0,true,Ef[i],tof,mparam[0]*mparam[4]);
712 //cout << "f " << pdgf[i] << " pz "<< pzf[i] << endl;
713 }
714 //cout << "Info GenieGenerator Return from GenieGenerator" << endl;
715 }
716 }
717
718 // Set the generation run and event numbers through the MC event header
719 FairMCEventHeader* header = cpg->GetEvent();
720 header->SetEventID(eventN);
721 header->SetRunID(runN);
722
723 return kTRUE;
724}
725// -------------------------------------------------------------------------
727{
728 return fNevents;
729}
730
731
const Double_t mbarn
Double_t pzf[500]
TClonesArray * ancstr
Double_t fDeltaE_GenieFLUKA_nu
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)
virtual ~GenieGenerator()
Double_t fEntrDz_outer
Double_t fEntrZ_outer
Int_t pdgf[500]
virtual Bool_t Init(const char *, int)
TH1D * pyslice[3000][500]
std::vector< TVector3 > dVecs
TH1D * pxhist[3000]
Double_t pxf[500]
Bool_t ReadEvent(FairPrimaryGenerator *)
Double_t MeanMaterialBudget(const Double_t *start, const Double_t *end, Double_t *mparam)
Bool_t OldReadEvent(FairPrimaryGenerator *)
Double_t FLUKA_y_cos
Double_t pyf[500]
void AddBox(TVector3 dVec, TVector3 box)
std::vector< TVector3 > boxs
Double_t fcrossingangle
Int_t ExtractEvent_Ekin(Double_t Ekin, Double_t DeltaE)
Double_t fEntrDz_inner
Double_t Ef[500]
don't make it persistent, magic ROOT command
Double_t FLUKA_x_cos
ClassImp(ecalContFact) ecalContFact