EDepSimRooTrackerKinematicsGenerator.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////
2 //
3 
4 #include <iostream>
5 #include <sstream>
6 #include <string>
7 #include <algorithm>
8 #include <stdexcept>
9 #include <random>
10 #include <chrono>
11 
12 #include <globals.hh>
13 #include <G4Event.hh>
14 #include <G4PrimaryVertex.hh>
15 #include <G4PrimaryParticle.hh>
16 #include <G4ParticleTable.hh>
17 #include <G4IonTable.hh>
18 #include <G4ParticleDefinition.hh>
19 #include <G4Tokenizer.hh>
20 #include <G4UnitsTable.hh>
21 
22 #include <TFile.h>
23 #include <TBits.h>
24 #include <TObjString.h>
25 #include <TTree.h>
26 
27 #include "EDepSimVertexInfo.hh"
29 
31 
32 #include "EDepSimLog.hh"
33 
34 
36  const G4String& name, const G4String& filename,
37  const G4String& treeName, const G4String& order,
38  int firstEvent)
39  : EDepSim::VKinematicsGenerator(name), fInput(NULL), fTree(NULL),
40  fNextEntry(0) {
41 
42  fInput = TFile::Open(filename,"OLD");
43  if (!fInput->IsOpen()) {
44  throw std::runtime_error("EDepSim::RooTrackerKinematicsGenerator::"
45  " File Not Open");
46  }
47 
48  EDepSimLog("Open a RooTracker tree from " << filename);
49 
50  fTree = dynamic_cast<TTree*>(fInput->Get(treeName));
51  if (!fTree) {
52  throw std::runtime_error("EDepSim::RooTrackerKinematicsGenerator::"
53  " Tree not found by constructor");
54  }
55  EDepSimNamedInfo("rooTracker",
56  " File has " << fTree->GetEntries() << " entries");
57 
58  // Find the basename of the input filename.
59  std::string::size_type start_pos = filename.rfind("/");
60  if (start_pos == std::string::npos) start_pos = 0; else ++start_pos;
61  std::string basename(filename,start_pos);
62  fFilename = basename + ":" + treeName;
63 
64  fEvtFlags = NULL;
65  fTree->SetBranchAddress("EvtFlags", &fEvtFlags);
66  fEvtCode = NULL;
67  fTree->SetBranchAddress("EvtCode", &fEvtCode);
68  fTree->SetBranchAddress("EvtNum", &fEvtNum);
69  fTree->SetBranchAddress("EvtXSec", &fEvtXSec);
70  fTree->SetBranchAddress("EvtDXSec", &fEvtDXSec);
71  fTree->SetBranchAddress("EvtWght", &fEvtWght);
72  fTree->SetBranchAddress("EvtProb", &fEvtProb);
73  fTree->SetBranchAddress("EvtVtx", fEvtVtx);
74  fTree->SetBranchAddress("StdHepN", &fStdHepN);
75  fTree->SetBranchAddress("StdHepPdg", fStdHepPdg);
76  fTree->SetBranchAddress("StdHepStatus", fStdHepStatus);
77  fTree->SetBranchAddress("StdHepX4", fStdHepX4);
78  fTree->SetBranchAddress("StdHepP4", fStdHepP4);
79  fTree->SetBranchAddress("StdHepPolz", fStdHepPolz);
80  fTree->SetBranchAddress("StdHepFd", fStdHepFd);
81  fTree->SetBranchAddress("StdHepLd", fStdHepLd);
82  fTree->SetBranchAddress("StdHepFm", fStdHepFm);
83  fTree->SetBranchAddress("StdHepLm", fStdHepLm);
84 #define PARENT_PARTICLE_PASS_THROUGH
85 #ifdef PARENT_PARTICLE_PASS_THROUGH
86  fTree->SetBranchAddress("NuParentPdg", &fNuParentPdg);
87  fTree->SetBranchAddress("NuParentDecMode",&fNuParentDecMode);
88  fTree->SetBranchAddress("NuParentDecP4", fNuParentDecP4);
89  fTree->SetBranchAddress("NuParentDecX4", fNuParentDecX4);
90  fTree->SetBranchAddress("NuParentProP4", fNuParentProP4);
91  fTree->SetBranchAddress("NuParentProX4", fNuParentProX4);
92  fTree->SetBranchAddress("NuParentProNVtx",&fNuParentProNVtx);
93 #endif
94 
95  // Set the input tree to the current rootracker tree that this class is
96  // using.
98  filename,
99  GetName());
100 
101  // Generate a vector of entries to be used by this generator.
102 
103  // Calculate the stride through the file. This could be cached, but
104  // recalculate each time for simplicity. Note that the stride should be a
105  // prime number, and not a divisor of the number of entries in the tree.
106  int entries = fTree->GetEntries();
107  fEntryVector.resize(entries);
108  int stride = 1;
109  while (order == "stride") {
110  stride = 17;
111  if (0 != entries%stride) break;
112  stride = 19;
113  if (0 != entries%stride) break;
114  stride = 23;
115  if (0 != entries%stride) break;
116  stride = 29;
117  if (0 != entries%stride) break;
118  throw std::runtime_error("EDepSim::RooTrackerKinematicsGenerator:: "
119  "File size cannot be divisible by 215441");
120  break; // throw std::runtime_error doesn't actually return
121  }
122  int entry = 0;
123  for (int i=0; i<entries; ++i) {
124  fEntryVector[i] = entry;
125  entry = (entry + stride)%entries;
126  }
127  if (order == "random") {
128  unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
129  std::shuffle(fEntryVector.begin(), fEntryVector.end(),std::default_random_engine(seed));
130  }
131 
132  if (firstEvent > 0) {
133  EDepSimLog(" FIRST EVENT WILL BE " << firstEvent);
134  if (firstEvent >= entries) {
135  throw std::runtime_error("EDepSim::RooTrackerKinematicsGenerator::"
136  " First event after last event");
137  }
138  fEntryVector.erase(std::copy(fEntryVector.begin()+firstEvent,
139  fEntryVector.end(),fEntryVector.begin()),
140  fEntryVector.end());
141  }
142 }
143 
145 
147  if (!fInput) return G4String("not-open");
148  return G4String(fInput->GetName());
149 }
150 
153  G4Event* anEvent,
154  const G4LorentzVector&) {
155  if (!fInput) {
156  throw std::runtime_error("EDepSim::RooTrackerKinematicsGenerator::"
157  " File Not Open");
158  }
159 
160  /// Check to see if the next event is there.
161  if (fNextEntry >= fEntryVector.size()) {
162  EDepSimLog("EDepSim::RooTrackerKinematicsGenerator: input file end.");
163  throw EDepSim::NoMoreEvents();
164  }
165 
166  fInput->cd();
167 
168  int entry = fEntryVector.at(fNextEntry);
169  // Get current entry to be used as new vertex - see comment below.
170  fTree->GetEntry(entry);
171  // Store current entry in the pass-through obj. N.B. To avoid mismatch
172  // and false results call EDepSim::KinemPassThrough::AddEntry(fTreePtr, X)
173  // where X is same as X in most recent call to fTreePtr->GetEntry(X).
175  EDepSimVerbose("Use rooTracker event number " << fEvtNum
176  << " (entry #" << entry << " in tree)");
177 
178  // Increment the next entry counter.
179  ++fNextEntry;
180 
181  // Set the default generator status. This should be overridden if the
182  // state changes.
183  GeneratorStatus generatorStatus = kSuccess;
184 
185  // Check if this is an end-of-sequence marker.
186  if (fStdHepN == 1 && fStdHepStatus[0]<0) {
187  return kEndEvent;
188  }
189 
190  // Create a new vertex to add the new particles, and add the vertex to the
191  // event.
192  G4PrimaryVertex* theVertex
193  = new G4PrimaryVertex(G4ThreeVector(fEvtVtx[0]*m,
194  fEvtVtx[1]*m,
195  fEvtVtx[2]*m),
196  fEvtVtx[3]*second);
197  anEvent->AddPrimaryVertex(theVertex);
198  EDepSimNamedInfo("rooTracker","Vertex @ "
199  << G4BestUnit(theVertex->GetPosition(), "Length")
200  << " Time: " << G4BestUnit(theVertex->GetT0(), "Time"));
201 
202  // Add an information field to the vertex.
203  EDepSim::VertexInfo *vertexInfo = new EDepSim::VertexInfo;
204  theVertex->SetUserInformation(vertexInfo);
205 
206  // Fill the information fields for this vertex.
207  vertexInfo->SetReaction(std::string(fEvtCode->String().Data()));
208  // Set the file name for this event.
209  std::ostringstream fs;
210  fs << fFilename << ":" << entry;
211  vertexInfo->SetFilename(fs.str());
212  // Set the interaction number to that of the RooTracker pass-through tree.
213  vertexInfo->SetInteractionNumber(
214  EDepSim::KinemPassThrough::GetInstance()->LastEntryNumber());
215  vertexInfo->SetCrossSection(fEvtXSec*1E-38*cm2);
216  vertexInfo->SetDiffCrossSection(fEvtDXSec*1E-38*cm2);
217  vertexInfo->SetWeight(fEvtWght);
218  vertexInfo->SetProbability(fEvtProb);
219 
220  // Add an informational vertex for storing the incoming
221  // neutrino particle and target nucleus.
222  G4PrimaryVertex* theIncomingVertex
223  = new G4PrimaryVertex(G4ThreeVector(fEvtVtx[0]*m,
224  fEvtVtx[1]*m,
225  fEvtVtx[2]*m),
226  fEvtVtx[3]*second);
227  vertexInfo->AddInformationalVertex(theIncomingVertex);
228 
229  // Add an information field to the vertex.
230  EDepSim::VertexInfo *incomingVertexInfo = new EDepSim::VertexInfo;
231  incomingVertexInfo->SetName("initial-state");
232  incomingVertexInfo->SetReaction(std::string(fEvtCode->String().Data()));
233  theIncomingVertex->SetUserInformation(incomingVertexInfo);
234 
235  // Fill the particles to be tracked (status ==1). These particles are
236  // attached to the primary vertex. Also save the incident neutrino
237  // particle and the incident target nucleus; these particles are attached
238  // to informational vertex.
239  G4ParticleTable* particleTable = G4ParticleTable::GetParticleTable();
240  for (int cnt = 0; cnt < fStdHepN; ++cnt) {
241  G4ParticleDefinition* particleDef
242  = particleTable->FindParticle(fStdHepPdg[cnt]);
243  if (!particleDef) {
244  //maybe we have an ion; figure out if it makes any sense
245  int ionA = (fStdHepPdg[cnt]/10) % 1000;
246  int ionZ = (fStdHepPdg[cnt]/10000) % 1000;
247  int type = (fStdHepPdg[cnt]/100000000);
248  if (type == 10 && ionZ > 0 && ionA > ionZ) {
249  G4IonTable* ionTable = particleTable->GetIonTable();
250  particleDef = ionTable->GetIon(ionZ, ionA);
251  }
252  else if (type == 20) {
253  // This is a pseudo-particle so skip it.
254  continue;
255  }
256  }
257 
258  // Determine a name for the particle.
259  std::string particleName =
260  particleDef ? particleDef->GetParticleName(): "unknown";
261 
262  // Get the momentum.
263  G4LorentzVector momentum(fStdHepP4[cnt][0]*GeV,
264  fStdHepP4[cnt][1]*GeV,
265  fStdHepP4[cnt][2]*GeV,
266  fStdHepP4[cnt][3]*GeV);
267 
268  if (fStdHepStatus[cnt] != 1) {
269  EDepSimVerbose("Untracked particle: " << cnt
270  << " " << particleName
271  << " with " << momentum.e()/MeV
272  << " MeV "
273  << " w/ mothers " << fStdHepFm[cnt]
274  << " to " << fStdHepLm[cnt]);
275  }
276 
277  // We are only interested in particles to be tracked (status==1)
278  // or incident neutrino/target nucleus (status==0).
279  if( !(fStdHepStatus[cnt] == 0 || fStdHepStatus[cnt] == 1)) {
280  continue;
281  }
282 
283  if (!particleDef) {
284  EDepSimSevere(" Particle code " << fStdHepPdg[cnt]
285  << " not recognized (not tracking)");
286  continue;
287  }
288 
289  // create the particle.
290  G4PrimaryParticle* theParticle
291  = new G4PrimaryParticle(particleDef,
292  momentum.px(),
293  momentum.py(),
294  momentum.pz());
295  theParticle->SetPolarization(fStdHepPolz[cnt][0],
296  fStdHepPolz[cnt][1],
297  fStdHepPolz[cnt][2]);
298 
299  if (fStdHepStatus[cnt] == 0) {
301  "rooTracker",
302  "Incoming "
303  << particleDef->GetParticleName()
304  << " " << theParticle->GetPDGcode()
305  << " " << momentum.e()/MeV << " MeV"
306  << " " << momentum.m()/MeV << " MeV/c^2");
307  theIncomingVertex->SetPrimary(theParticle);
308  }
309  else if (fStdHepStatus[cnt] == 1){
311  "rooTracker",
312  "Tracking "
313  << particleDef->GetParticleName()
314  << " " << theParticle->GetPDGcode()
315  << " " << momentum.e()/MeV << " MeV"
316  << " " << momentum.m()/MeV << " MeV/c^2");
317  theVertex->SetPrimary(theParticle);
318  }
319  }
320 
321 #ifdef PARENT_PARTICLE_PASS_THROUGH
322  // Fill the particles at the decay vertex. These are the first info
323  // vertex.
324  G4PrimaryVertex* theDecayVertex
325  = new G4PrimaryVertex(G4ThreeVector(fNuParentDecX4[0]*m,
326  fNuParentDecX4[1]*m,
327  fNuParentDecX4[2]*m),
328  fNuParentDecX4[3]*second);
329  vertexInfo->AddInformationalVertex(theDecayVertex);
330 
331  // Add an information field to the vertex.
332  EDepSim::VertexInfo *decayVertexInfo = new EDepSim::VertexInfo;
333  decayVertexInfo->SetName("beam-particle:Decay");
334  {
335  std::ostringstream tmp;
336  tmp << fNuParentDecMode;
337  decayVertexInfo->SetReaction(tmp.str());
338  }
339  theDecayVertex->SetUserInformation(decayVertexInfo);
340 
341  G4PrimaryParticle* theDecayParticle
342  = new G4PrimaryParticle(fNuParentPdg,
343  fNuParentDecP4[0]*GeV,
344  fNuParentDecP4[1]*GeV,
345  fNuParentDecP4[2]*GeV);
346  theDecayVertex->SetPrimary(theDecayParticle);
347 
348  // Fill the particles at the production vertex.
349  G4PrimaryVertex* theProductionVertex
350  = new G4PrimaryVertex(G4ThreeVector(fNuParentProX4[0]*m,
351  fNuParentProX4[1]*m,
352  fNuParentProX4[2]*m),
353  fNuParentProX4[3]*second);
354  decayVertexInfo->AddInformationalVertex(theProductionVertex);
355 
356  // Add information about the production vertex.
357  EDepSim::VertexInfo *productionVertexInfo = new EDepSim::VertexInfo;
358  productionVertexInfo->SetName("beam-particle:Production");
359  productionVertexInfo->SetInteractionNumber(fNuParentProNVtx);
360  theProductionVertex->SetUserInformation(productionVertexInfo);
361 
362  G4PrimaryParticle* theProductionParticle
363  = new G4PrimaryParticle(fNuParentPdg,
364  fNuParentProP4[0]*GeV,
365  fNuParentProP4[1]*GeV,
366  fNuParentProP4[2]*GeV);
367  theProductionVertex->SetPrimary(theProductionParticle);
368 #endif
369 
370  return generatorStatus;
371 }
static QCString name
Definition: declinfo.cpp:673
#define EDepSimLog(outStream)
Definition: EDepSimLog.hh:717
#define EDepSimNamedInfo(trace, outStream)
Definition: EDepSimLog.hh:770
void SetFilename(const G4String &f)
Set the file that this vertex came from.
double fStdHepP4[kNPmax][4]
The 4-momentum (px, py, pz, E) of the particle in the LAB frame (GeV)
int fNuParentPdg
The PDG code of the particle which created the parent neutrino.
QList< Entry > entry
void SetCrossSection(double xs)
int fStdHepN
The number of particles in the particle arrays to track.
virtual void AddInformationalVertex(G4PrimaryVertex *vtx)
Add an informational vertex to this event.
std::string string
Definition: nybbler.cc:12
void SetWeight(double w)
std::string fFilename
The static part of the file name field.
static constexpr double fs
Definition: Units.h:100
TObjString * fEvtCode
The generator-specific string with the &#39;event code&#39;.
int fNuParentProNVtx
The vertex ID of the parent particle vertex.
int fStdHepLd[kNPmax]
The index last daughter of the particle in the arrays.
static constexpr double MeV
Definition: Units.h:129
#define EDepSimSevere(outStream)
Definition: EDepSimLog.hh:539
string filename
Definition: train.py:213
GeneratorStatus
A status value that can be returned by GeneratePrimaryVertex.
TBits * fEvtFlags
The generator-specific event flags.
int fStdHepFd[kNPmax]
The index of the first daughter of the particle in the arrays.
bool AddEntry(const TTree *inputTreePtr, const int origEntry)
double fEvtXSec
The cross section for the event (1E-38 cm2)
double fStdHepPolz[kNPmax][3]
The particle polarization vector.
static EDepSim::KinemPassThrough * GetInstance()
Construct a module from components.
Definition: TG4HitSegment.h:10
static constexpr double cm2
Definition: Units.h:69
static constexpr double GeV
Definition: Units.h:28
A vertex was successfully generated.
int fEvtNum
The sequence number of the event (the event number).
TTree * fTree
The event tree that contains the output events.
string tmp
Definition: languages.py:63
bool AddInputTree(const TTree *inputTreePtr, const char *inputFileName, const char *generatorName)
void SetDiffCrossSection(double xs)
#define EDepSimVerbose(outStream)
Definition: EDepSimLog.hh:787
void SetProbability(double p)
void SetInteractionNumber(int i)
Set the index of the interaction within the input interaction file.
RooTrackerKinematicsGenerator(const G4String &name, const G4String &fileName, const G4String &treeName, const G4String &order, int firstEvent)
int fStdHepFm[kNPmax]
The index of the first mother of the particle in there arrays.
T copy(T const &v)
def momentum(x1, x2, x3, scale=1.)
second_as<> second
Type of time stored in seconds, in double precision.
Definition: spacetime.h:85
G4String GetName() const
Return the name of the generator.
virtual G4String GetInputName()
Get the name of the open kinematics file.
int fStdHepLm[kNPmax]
The index of the last mother of the particle in the arrays.
void SetReaction(const G4String &r)
void SetName(const G4String &name)
virtual GeneratorStatus GeneratePrimaryVertex(G4Event *evt, const G4LorentzVector &position)
Add a primary vertex to the event.