21#include "BDSBunchEventGenerator.hh"
23#include "BDSEventGeneratorFileType.hh"
24#include "BDSException.hh"
25#include "BDSPrimaryGeneratorFileHEPMC.hh"
26#include "BDSParticleCoords.hh"
27#include "BDSParticleCoordsFull.hh"
28#include "BDSParticleCoordsFullGlobal.hh"
29#include "BDSPhysicalConstants.hh"
30#include "BDSPrimaryVertexInformation.hh"
31#include "BDSPrimaryVertexInformationV.hh"
32#include "BDSUtilities.hh"
33#include "BDSWarning.hh"
36#include "G4LorentzVector.hh"
37#include "G4ParticleDefinition.hh"
38#include "G4PrimaryParticle.hh"
39#include "G4PrimaryVertex.hh"
43#include "HepMC3/Attribute.h"
44#include "HepMC3/GenParticle.h"
45#include "HepMC3/GenVertex.h"
46#include "HepMC3/Reader.h"
47#include "HepMC3/ReaderAscii.h"
48#include "HepMC3/ReaderAsciiHepMC2.h"
49#include "HepMC3/ReaderHEPEVT.h"
50#include "HepMC3/ReaderLHEF.h"
51#ifdef USE_HEPMC3_ROOTIO
52#include "HepMC3/ReaderRoot.h"
53#include "HepMC3/ReaderRootTree.h"
56#include "CLHEP/Units/SystemOfUnits.h"
66 const G4String& fileNameIn,
69 G4bool removeUnstableWithoutDecayIn,
70 G4bool warnAboutSkippedParticlesIn):
75 removeUnstableWithoutDecay(removeUnstableWithoutDecayIn),
76 warnAboutSkippedParticles(warnAboutSkippedParticlesIn)
80 G4cout << __METHOD_NAME__ <<
"event generator file format to be " << fileType.ToString() << G4endl;
83 bunch->SetNEventsInFile(nEventsInFile);
86 {
throw BDSException(__METHOD_NAME__,
"must be constructed with a valid BDSBunchEventGenerator instance");}
90BDSPrimaryGeneratorFileHEPMC::~BDSPrimaryGeneratorFileHEPMC()
99 {
throw BDSException(__METHOD_NAME__,
"no file reader available");}
108 G4cout << __METHOD_NAME__ <<
"advancing file to event: " << eventOffset << G4endl;
115 currentFileEventIndex = 0;
116 endOfFileReached =
false;
118 {G4cout << __METHOD_NAME__ <<
"Opening file: " << fileName << G4endl;}
121 case BDSEventGeneratorFileType::hepmc2:
122 {reader =
new HepMC3::ReaderAsciiHepMC2(fileName);
break;}
123 case BDSEventGeneratorFileType::hepmc3:
124 {reader =
new HepMC3::ReaderAscii(fileName);
break;}
125 case BDSEventGeneratorFileType::hpe:
126 {reader =
new HepMC3::ReaderHEPEVT(fileName);
break;}
127#ifdef USE_HEPMC3_ROOTIO
128 case BDSEventGeneratorFileType::root:
129 {reader =
new HepMC3::ReaderRoot(fileName);
break;}
130 case BDSEventGeneratorFileType::treeroot:
131 {reader =
new HepMC3::ReaderRootTree(fileName);
break;}
133 case BDSEventGeneratorFileType::root:
134 case BDSEventGeneratorFileType::treeroot:
136 throw BDSException(__METHOD_NAME__,
"HEPMC3 installation not compiled with ROOT support so can't load root file.");
140 case BDSEventGeneratorFileType::lhef:
141 {reader =
new HepMC3::ReaderLHEF(fileName);
break;}
153 currentFileEventIndex = 0;
154 endOfFileReached =
true;
159 G4cout << __METHOD_NAME__ <<
"counting number of events" << G4endl;
162 while (!reader->failed())
164 auto tempEvent =
new HepMC3::GenEvent();
165 bool readEventOK = reader->read_event(*tempEvent);
167 {G4cout << __METHOD_NAME__ <<
"error in reading event index " << nEvents << G4endl;}
170 if (reader->failed())
176 G4cout << __METHOD_NAME__ << nEvents <<
" events found in file" << G4endl;
183 hepmcEvent =
new HepMC3::GenEvent();
187 bool readEventOK = reader->read_event(*hepmcEvent);
191 hepmcEvent =
nullptr;
192 throw BDSException(__METHOD_NAME__,
"problem with event generator file \"" + fileName +
"\"");
195 if (reader->failed())
198 hepmcEvent =
nullptr;
205 G4cout << __METHOD_NAME__ <<
"Returning to beginning of file for next event." << G4endl;
209 {BDS::Warning(__METHOD_NAME__,
"file looping requested, but 0 events passed filters - ending.");}
215 currentFileEventIndex++;
222 if (nEventsToSkip > 0)
223 {G4cout << __METHOD_NAME__ <<
"skipping " << nEventsToSkip <<
" into file." << G4endl;}
227 G4long nAvailable = nEventsInFile * distrFileLoopNTimes;
228 if ((G4long)nEventsToSkip > nAvailable)
230 G4String msg =
"number of events to skip (" + std::to_string(nEventsToSkip) +
") is greater than the number of events (";
231 msg += std::to_string(nEventsInFile);
232 if (distrFileLoopNTimes > 1)
233 {msg +=
" x " + std::to_string(distrFileLoopNTimes) +
" loops of file";}
234 msg +=
") in this file.";
235 throw BDSException(
"BDSBunchUserFile::RecreateAdvanceToEvent>", msg);
237 G4long nToSkipSinglePass = nAvailable % nEventsToSkip;
238 for (G4int i = 0; i < nToSkipSinglePass; i++)
248 G4PrimaryVertex* g4vtx =
new G4PrimaryVertex(centralCoordsGlobal.global.x,
249 centralCoordsGlobal.global.y,
250 centralCoordsGlobal.global.z,
251 centralCoordsGlobal.global.T);
253 double overallWeight = 1.0;
254 if (!(hepmcevt->weights().empty()))
255 {overallWeight = hepmcevt->weight();}
256 std::vector<BDSPrimaryVertexInformation> vertexInfos;
257 G4int nParticlesSkipped = 0;
258 for (
const auto& particlePtr : hepmcevt->particles())
260 const HepMC3::GenParticle* particle = particlePtr.get();
261 if (!particle->children().empty())
264 int pdgcode = particle->pdg_id();
265 const HepMC3::FourVector& fv = particle->momentum();
266 G4LorentzVector p(fv.px(), fv.py(), fv.pz(), fv.e());
267 G4double px = p.x() * CLHEP::GeV;
268 G4double py = p.y() * CLHEP::GeV;
269 G4double pz = p.z() * CLHEP::GeV;
270 G4ThreeVector originalUnitMomentum(px,py,pz);
272 originalUnitMomentum = originalUnitMomentum.unit();
273 G4double rp = std::hypot(originalUnitMomentum.x(), originalUnitMomentum.y());
276 G4ThreeVector unitMomentum = originalUnitMomentum;
277 unitMomentum.transform(referenceBeamMomentumOffset);
280 G4PrimaryParticle* g4prim =
new G4PrimaryParticle(pdgcode, px, py, pz);
285 const G4ParticleDefinition* pd = g4prim->GetParticleDefinition();
286 G4bool deleteIt = !pd;
287 if (pd && removeUnstableWithoutDecay)
288 {deleteIt = !(pd->GetPDGStable()) && !pd->GetDecayTable();}
293 G4cout << __METHOD_NAME__ <<
"skipping particle with PDG ID: " << pdgcode << G4endl;
308 g4prim->GetTotalEnergy(),
311 if (!bunch->
AcceptParticle(local, rp, g4prim->GetKineticEnergy(), pdgcode))
328 G4double charge = g4prim->GetCharge();
329 G4double momentum = g4prim->GetTotalMomentum();
333 brho *= CLHEP::tesla*CLHEP::m;
336 g4prim->GetTotalMomentum(),
341 vertexInfos.emplace_back(vertexInfo);
344 g4prim->SetMomentumDirection(G4ThreeVector(fullCoords.global.xp,
345 fullCoords.global.yp,
346 fullCoords.global.zp));
347 g4vtx->SetPrimary(g4prim);
350 if (nParticlesSkipped > 0 && warnAboutSkippedParticles)
351 {G4cout << __METHOD_NAME__ << nParticlesSkipped <<
" particles skipped" << G4endl;}
354 if (g4vtx->GetNumberOfParticle() == 0)
358 if (warnAboutSkippedParticles)
359 {G4cout << __METHOD_NAME__ <<
"no particles found in event number: " << currentFileEventIndex <<
" in the file" << G4endl;}
364 g4event->AddPrimaryVertex(g4vtx);
365 vertexGeneratedSuccessfully =
true;
366 nEventsReadThatPassedFilters++;
372void _SymbolToPreventWarningHEPMC3Reader(){;}
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.
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 SkipEvents(G4int nEventsToSkip)
virtual void RecreateAdvanceToEvent(G4int eventOffset)
Advance to the correct event number in the file for recreation.
BDSPrimaryGeneratorFileHEPMC()=delete
Do not require default constructor.
G4long CountEventsInFile()
virtual void GeneratePrimaryVertex(G4Event *anEvent)
void HepMC2G4(const HepMC3::GenEvent *hepmcevt, G4Event *g4event)
Conversion from HepMC::GenEvent to G4Event.
void OpenFile(G4bool usualPrintOut=true)
Construct the member "reader" and open the file for reading.
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
type underlying() const
return underlying value (can be used in switch statement)
std::pair< G4String, G4String > SplitOnColon(const G4String &formatAndPath)
static const G4double cOverGeV
speed of light / 1 GeV, used for scaling in brho calculation
BDSEventGeneratorFileType DetermineEventGeneratorFileType(G4String distrType)
Function that gives corresponding enum value for string (case-insensitive).
G4bool IsFinite(G4double value, G4double tolerance=std::numeric_limits< double >::epsilon())