18#include "BDSBunchEventGenerator.hh"
20#include "BDSException.hh"
21#include "BDSOutputLoaderSampler.hh"
22#include "BDSPrimaryGeneratorFileSampler.hh"
23#include "BDSParticleCoords.hh"
24#include "BDSParticleCoordsFull.hh"
25#include "BDSParticleCoordsFullGlobal.hh"
26#include "BDSPhysicalConstants.hh"
27#include "BDSPrimaryVertexInformation.hh"
28#include "BDSPrimaryVertexInformationV.hh"
29#include "BDSUtilities.hh"
30#include "BDSWarning.hh"
33#include "G4EventManager.hh"
34#include "G4LorentzVector.hh"
35#include "G4PrimaryParticle.hh"
36#include "G4PrimaryVertex.hh"
38#include "CLHEP/Units/SystemOfUnits.h"
45 const G4String& fileNameIn,
48 G4bool removeUnstableWithoutDecayIn,
49 G4bool warnAboutSkippedParticlesIn):
53 removeUnstableWithoutDecay(removeUnstableWithoutDecayIn),
54 warnAboutSkippedParticles(warnAboutSkippedParticlesIn)
57 samplerName = ba.second;
58 G4cout << __METHOD_NAME__ <<
"reading sampler named: \"" << samplerName <<
"\"" << G4endl;
61 nEventsInFile = reader->NEventsInFile();
62 bunch->SetNEventsInFile(nEventsInFile);
63 bunch->SetNOriginalEvents(reader->NOriginalEvents());
64 G4cout << __METHOD_NAME__ << nEventsInFile <<
" events found in file" << G4endl;
66 {
throw BDSException(__METHOD_NAME__,
"must be constructed with a valid BDSBunchEventGenerator instance");}
70BDSPrimaryGeneratorFileSampler::~BDSPrimaryGeneratorFileSampler()
78 {
throw BDSException(__METHOD_NAME__,
"no file reader available");}
80 currentVertices.clear();
83 if (currentFileEventIndex >= nEventsInFile)
85 endOfFileReached =
true;
86 G4cout << __METHOD_NAME__ <<
"End of file reached. ";
92 G4cout <<
"Returning to beginning of file for next event." << G4endl;
93 currentFileEventIndex = 0;
94 endOfFileReached =
false;
98 BDS::Warning(__METHOD_NAME__,
"file looping requested, but 0 events passed filters - ending.");
114 G4cout <<
"BDSROOTSamplerLoader::RecreateAdvanceToEvent> Advancing file to event: " << eventOffset << G4endl;
122 const auto sampler = reader->SamplerDataFloat(index);
125 for (
int i = 0; i < n; i++)
127 G4int pdgID = (G4int)sampler->partID[i];
128 G4double xp = (G4double)sampler->xp[i];
129 G4double yp = (G4double)sampler->yp[i];
130 G4double zp = (G4double)sampler->zp[i];
131 G4double p = (G4double)sampler->p[i];
132 G4ThreeVector momentum = G4ThreeVector(xp,yp,zp) * p * CLHEP::GeV;
133 G4double x = (G4double)sampler->x[i] * CLHEP::m;
134 G4double y = (G4double)sampler->y[i] * CLHEP::m;
135 G4double T = (G4double)sampler->T[i] * CLHEP::s;
136 G4ThreeVector localPosition(x,y,0);
137 G4double weight = (G4double)sampler->weight[i];
138 auto g4prim =
new G4PrimaryParticle(pdgID, momentum.x(), momentum.y(), momentum.z());
139 g4prim->SetWeight(weight);
144void BDSPrimaryGeneratorFileSampler::ReadPrimaryParticlesDouble(G4long index)
147 const auto sampler = reader->SamplerDataDouble(index);
150 for (
int i = 0; i < n; i++)
152 G4int pdgID = (G4int)sampler->partID[i];
153 G4double xp = (G4double)sampler->xp[i];
154 G4double yp = (G4double)sampler->yp[i];
155 G4double zp = (G4double)sampler->zp[i];
156 G4double p = (G4double)sampler->p[i];
157 G4ThreeVector momentum = G4ThreeVector(xp,yp,zp) * p;
158 G4double x = (G4double)sampler->x[i] * CLHEP::m;
159 G4double y = (G4double)sampler->y[i] * CLHEP::m;
160 G4double T = (G4double)sampler->T[i] * CLHEP::s;
161 G4ThreeVector localPosition(x,y,0);
162 G4double weight = (G4double)sampler->weight[i];
163 auto g4prim =
new G4PrimaryParticle(pdgID, momentum.x(), momentum.y(), momentum.z());
164 g4prim->SetWeight(weight);
165 vertices.emplace_back(DisplacedVertex{localPosition, T, g4prim});
171 if (reader->DoublePrecision())
172 {ReadPrimaryParticlesDouble(index);}
176 G4int nParticlesSkipped = 0;
177 for (
const auto& xyzVertex :
vertices)
179 const auto vertex = xyzVertex.vertex;
184 const G4ParticleDefinition* pd = vertex->GetParticleDefinition();
185 G4bool deleteIt = !pd;
186 if (pd && removeUnstableWithoutDecay)
187 {deleteIt = !(pd->GetPDGStable()) && !pd->GetDecayTable();}
195 G4ThreeVector unitMomentum = vertex->GetMomentumDirection();
196 unitMomentum.transform(referenceBeamMomentumOffset);
197 G4double rp = unitMomentum.perp();
200 centralCoords.
AddOffset(xyzVertex.xyz, xyzVertex.T);
210 vertex->GetTotalEnergy(),
211 vertex->GetWeight());
213 if (!bunch->
AcceptParticle(local, rp, vertex->GetKineticEnergy(), vertex->GetPDGcode()))
221 auto g4vtx =
new G4PrimaryVertex(fullCoordsGlobal.global.x,
222 fullCoordsGlobal.global.y,
223 fullCoordsGlobal.global.z,
224 fullCoordsGlobal.global.T);
235 G4double charge = vertex->GetCharge();
236 G4double momentum = vertex->GetTotalMomentum();
240 brho *= CLHEP::tesla*CLHEP::m;
243 vertex->GetTotalMomentum(),
247 vertex->GetPDGcode());
250 auto prim =
new G4PrimaryParticle(*vertex);
251 prim->SetMomentumDirection(G4ThreeVector(fullCoordsGlobal.global.xp,
252 fullCoordsGlobal.global.yp,
253 fullCoordsGlobal.global.zp));
254 g4vtx->SetPrimary(prim);
255 g4vtx->SetUserInformation(vertexInfo);
256 currentVertices.push_back(g4vtx);
259 if (nParticlesSkipped > 0 && warnAboutSkippedParticles)
260 {G4cout << __METHOD_NAME__ << nParticlesSkipped <<
" particles skipped" << G4endl;}
262 if (currentVertices.empty())
265 if (warnAboutSkippedParticles)
266 {G4cout << __METHOD_NAME__ <<
"no particles found in event number: " << currentFileEventIndex <<
" in the file" << G4endl;}
270 vertexGeneratedSuccessfully =
true;
271 nEventsReadThatPassedFilters++;
279 currentFileEventIndex++;
281 for (
auto* v : currentVertices)
282 {anEvent->AddPrimaryVertex(v);}
283 currentVertices.clear();
288 if (nEventsToSkip > 0)
289 {G4cout << __METHOD_NAME__ <<
"skipping " << nEventsToSkip <<
" into file." << G4endl;}
293 G4long nAvailable = nEventsInFile * distrFileLoopNTimes;
294 if ((G4long)nEventsToSkip > nAvailable)
296 G4String msg =
"number of events to skip (" + std::to_string(nEventsToSkip) +
") is greater than the number of events (";
297 msg += std::to_string(nEventsInFile);
298 if (distrFileLoopNTimes > 1)
299 {msg +=
" x " + std::to_string(distrFileLoopNTimes) +
" loops of file";}
300 msg +=
") in this file.";
301 throw BDSException(
"BDSBunchUserFile::RecreateAdvanceToEvent>", msg);
303 G4long nToSkipSinglePass = nEventsToSkip % nEventsInFile;
304 currentFileEventIndex = nToSkipSinglePass;
A wrapper of BDSBunch to include a filter for the events loaded by an event generator.
G4RotationMatrix ReferenceBeamMomentumOffset() const
Get a rotation matrix according to Xp0 and Yp0.
G4int eventGeneratorNEventsSkip
Cache of limit.
G4bool AcceptParticle(const BDSParticleCoordsFull &coords, G4double rpOriginal, G4double kineticEnergy, G4int pdgID)
G4int DistrFileLoopNTimes() const
Accessor.
BDSParticleCoordsFullGlobal ApplyTransform(const BDSParticleCoordsFull &localIn) const
virtual BDSParticleCoordsFull GetNextParticleLocal()
General exception with possible name of object and message.
Loader of ROOT Event output for receating events.
A set of particle coordinates in both local and global.
A set of particle coordinates including energy and weight.
G4double s
TODO - remove this. Unused. S (global) is calculated from S0 + z.
void AddOffset(const G4ThreeVector &offset, G4double offsetT=0)
Apply an offset to the spatial and T coordinates only - assignment.
virtual void RecreateAdvanceToEvent(G4int eventOffset)
Advance to the correct event number in the file for recreation.
void ReadSingleEvent(G4long index, G4Event *anEvent)
Read sampler hits and put into primary vertices if they pass filters.
std::vector< DisplacedVertex > vertices
Used for transiently loading information.
BDSPrimaryGeneratorFileSampler()=delete
Do not require default constructor.
void ReadPrimaryParticlesFloat(G4long index)
Conversion from HepMC::GenEvent to G4Event.
void SkipEvents(G4long nEventsToSkip)
virtual void GeneratePrimaryVertex(G4Event *anEvent)
Read the next non-empty sampler entry from the file.
Common interface for any primary generators that are file based.
void ThrowExceptionIfRecreateOffsetTooHigh(G4long eventOffset) const
G4bool VertexInsideWorld(const G4ThreeVector &pos) const
Utility function for derived classes to check a position is inside the world.
G4bool OKToLoopFile() const
std::pair< G4String, G4String > SplitOnColon(const G4String &formatAndPath)
static const G4double cOverGeV
speed of light / 1 GeV, used for scaling in brho calculation
G4bool IsFinite(G4double value, G4double tolerance=std::numeric_limits< double >::epsilon())