21 #include <CLHEP/Units/SystemOfUnits.h>
22 #include <CLHEP/Units/PhysicalConstants.h>
26 #include <G4PrimaryVertex.hh>
27 #include <G4PrimaryParticle.hh>
28 #include <G4ParticleDefinition.hh>
44 v->time = g4->GetT0();
52 const G4PrimaryParticle* g4p)
57 p->
pdgID = g4p->GetPDGcode();
58 p->
psx = g4p->GetPx();
59 p->
psy = g4p->GetPy();
60 p->
psz = g4p->GetPz();
61 p->
time = g4p->GetProperTime();
76 p->
mass = g4p->GetMass();
77 p->
charge = int(3.0 * g4p->GetCharge());
87 G4PrimaryParticle* gp)
94 int pid = int(interaction->
particles.size());
96 G4PrimaryParticle* dau = gp->GetDaughter();
98 int mask = interaction->
mask;
103 particle_origine->
out.insert(p->
id);
113 dv->
in.insert(p->
id);
115 interaction->
vertices[mask].emplace_back(dv) ;
117 for(; dau; dau = dau->GetNext())
118 collectPrimaries(pm, interaction, dv, dau);
126 std::set<G4PrimaryVertex*>
const& primaries)
129 interaction->
locked =
true;
130 interaction->
mask = mask;
131 for (
auto const& gv: primaries) {
134 interaction->
vertices[mask].emplace_back(
v);
135 for (G4PrimaryParticle *gp = gv->GetPrimary(); gp; gp = gp->GetNext()) {
136 collectPrimaries(pm, interaction,
v, gp);
175 static void appendInteraction(
const Geant4Action* caller,
179 Geant4PrimaryInteraction::ParticleMap::iterator ip, ipend;
184 Geant4PrimaryInteraction::VertexMap::iterator ivfnd, iv, ivend;
185 for( iv=input->
vertices.begin(), ivend=input->
vertices.end(); iv != ivend; ++iv ) {
186 int theMask = input->
mask;
187 ivfnd = output->
vertices.find(theMask);
188 if ( ivfnd != output->
vertices.end() ) {
189 caller->
abortRun(
"Duplicate primary interaction identifier!",
190 "Cannot handle 2 interactions with identical identifiers!");
198 Geant4PrimaryInteraction::ParticleMap::iterator ip, ipend;
201 for( ip=particles.begin(), ipend=particles.end(); ip != ipend; ++ip ) {
204 mx_id = p->
id+1 > mx_id ? p->
id+1 : mx_id;
210 Geant4PrimaryInteraction::VertexMap::iterator iv, ivend;
211 std::set<int> in, out;
212 std::set<int>::iterator i;
214 for(iv=vertices.begin(), ivend=vertices.end(); iv != ivend; ++iv) {
218 for(in=
v->in, i=in.begin(),
v->in.clear(); i != in.end(); ++i)
219 v->in.insert((*i)+part_offset);
220 for(out=
v->out, i=out.begin(),
v->out.clear(); i != out.end(); ++i)
221 v->out.insert((*i)+part_offset);
230 typedef std::vector<Interaction*> Interactions;
233 Interaction* output =
event.
extension<Interaction>();
235 int particle_offset = 0;
237 for(Interactions::const_iterator i=inter.begin(); i != inter.end(); ++i) {
238 Interaction* interaction = *i;
239 int vertex_offset = particle_offset;
240 if ( !interaction->applyMask() ) {
241 caller->
abortRun(
"Found single interaction with multiple primary vertices!",
242 "Cannot merge individual interactions with more than one primary!");
244 rebaseParticles(interaction->particles,particle_offset);
245 rebaseVertices(interaction->vertices,vertex_offset);
246 appendInteraction(caller,output,interaction);
248 output->setNextPID(particle_offset);
249 Geant4PrimaryInteraction::ParticleMap::iterator ip, ipend;
250 caller->
debug(
"+++ Merging MC input record from %d interactions:",(
int)inter.size());
251 for( ip=output->particles.begin(), ipend=output->particles.end(); ip != ipend; ++ip )
262 Geant4PrimaryEvent::Interaction::VertexMap::iterator iv;
263 Geant4PrimaryEvent::Interaction::ParticleMap::iterator ip;
264 double gamma = std::sqrt(1 +
SQR(tan(alpha)));
265 double betagamma = std::tan(alpha);
268 caller->
abortRun(
"Locked interactions may not be boosted!",
269 "Cannot boost interactions with a native G4 primary record!");
271 else if ( alpha != 0.0 ) {
275 double t = gamma *
v->time + betagamma *
v->x / CLHEP::c_light;
276 double x = gamma *
v->x + betagamma * CLHEP::c_light *
v->time;
288 double t = gamma * p->
time + betagamma * p->
vsx / CLHEP::c_light;
289 double x = gamma * p->
vsx + betagamma * CLHEP::c_light * p->
time;
295 double px = betagamma * std::sqrt(e2) + gamma * p->
psx;
315 double dx,
double dy,
double dz,
double dt)
317 Geant4PrimaryEvent::Interaction::VertexMap::iterator iv;
318 Geant4PrimaryEvent::Interaction::ParticleMap::iterator ip;
321 caller->
abortRun(
"Locked interactions may not be smeared!",
322 "Cannot smear interactions with a native G4 primary record!");
349 G4PrimaryParticle* g4 = 0;
350 const G4ParticleDefinition* def = p.
definition();
352 double energy = p.
energy();
354 double mass2 = energy*energy - mom2;
357 mass2 = def->GetPDGMass() * def->GetPDGMass();
359 energy = std::sqrt(mom2 + mass2);
360 if ( std::fabs(p.
energy()-energy) > 0e0 ) {
361 dd4hep::printout(dd4hep::INFO,
"createG4Primary",
362 "Change particle %s energy from %10.5f MeV by %g ppm to avoid negative Energy^2",
363 (def) ? def->GetParticleName().c_str() :
"???", p.
energy(), std::fabs(p.
energy()-energy)*1e6);
366 if ( 0 != p->
pdgID ) {
369 g4 =
new G4PrimaryParticle(pdgID, p->
psx, p->
psy, p->
psz, energy);
372 g4 =
new G4PrimaryParticle(def, p->
psx, p->
psy, p->
psz, energy);
373 g4->SetCharge(
double(p.
charge())/3.0);
381 static std::vector< std::pair<Geant4Particle*,G4PrimaryParticle*> >
382 getRelevant(std::set<int>& visited,
383 std::map<int,G4PrimaryParticle*>& prim,
388 typedef std::vector< std::pair<Geant4Particle*,G4PrimaryParticle*> > Primaries;
389 using dd4hep::printout;
392 visited.insert(p->
id);
395 bool rejectParticle =
false
398 printout(dd4hep::DEBUG,
"Input",
399 "Checking rejection of stable: PDG(%-10d), Definition(%s), reject(%s)",
402 rejectParticle ?
"true" :
"false");
403 if (not rejectParticle and prim.find(p->
id) == prim.end() ) {
404 G4PrimaryParticle* p4 = createG4Primary(p);
406 res.emplace_back(p,p4);
411 int first_daughter = *(dau.begin());
416 double proper_time = fabs(dp->
time-p->
time) * me;
417 double proper_time_Precision = pow(10.,-DBL_DIG)*fabs(me)*fmax(fabs(p->
time),fabs(dp->
time));
418 bool isProperTimeZero = (fabs(proper_time) <= fabs(proper_time_Precision));
423 or (isProperTimeZero and p.definition()->GetPDGStable() )
424 or (isProperTimeZero and primaryConfig.m_zeroTimePDGs.count(abs(p->pdgID)) != 0 )
428 printout(
dd4hep::DEBUG, "Input",
429 "Checking rejection: PDG(%-10d), Definition(%s), isProperTimeZero(%s, %3.15f), stable(%s), doc(%s), reject(%s)",
431 p.definition() ? "true" : "false",
432 isProperTimeZero ? "true" : "false", proper_time,
433 (
bool(p.definition()) ? p.definition()->GetPDGStable() : false) ? "true" : "false",
435 rejectParticle ? "true" : "false");
437 bool failStableWithChildren = (not rejectParticle and p.definition()->GetPDGStable());
438 if (failStableWithChildren) {
439 printout(dd4hep::FATAL,
"Input",
440 "+++ Stable particle (PDG: %-10d) with daughters! check your MC record, adapt particle.tbl file...",
442 throw std::runtime_error(
"Cannot Simmulate this MC Record");
444 if (not rejectParticle) {
445 std::map<int, G4PrimaryParticle*>::iterator ip4 = prim.find(p->
id);
446 G4PrimaryParticle* p4 = (ip4 == prim.end()) ? 0 : (*ip4).second;
448 p4 = createG4Primary(p);
449 p4->SetProperTime(proper_time);
452 for(Geant4Particle::Particles::const_iterator i=dau.begin(); i!=dau.end(); ++i) {
453 if ( visited.find(*i) == visited.end() ) {
454 Primaries tmp = getRelevant(visited,prim,pm,primaryConfig,pm[*i]);
455 daughters.insert(daughters.end(), tmp.begin(),tmp.end());
458 for(Primaries::iterator i=daughters.begin(); i!=daughters.end(); ++i)
459 p4->SetDaughter((*i).second);
461 res.emplace_back(p,p4);
464 for(Geant4Particle::Particles::const_iterator i=dau.begin(); i!=dau.end(); ++i) {
465 if ( visited.find(*i) == visited.end() ) {
466 Primaries tmp = getRelevant(visited,prim,pm,primaryConfig,pm[*i]);
467 res.insert(res.end(), tmp.begin(),tmp.end());
480 typedef std::vector< std::pair<Geant4Particle*,G4PrimaryParticle*> > Primaries;
483 Interaction* interaction = context->
event().
extension<Interaction>();
484 Interaction::ParticleMap& pm = interaction->particles;
485 Interaction::VertexMap& vm = interaction->vertices;
486 std::map<int,G4PrimaryParticle*> prim;
487 std::set<int> visited;
490 auto const& primaryConfig = primHandler ? primHandler->m_primaryConfig :
Geant4PrimaryConfig();
492 caller->
debug(
"PrimaryConfiguration:%s", primaryConfig.
toString().c_str());
494 if ( interaction->locked ) {
495 caller->
abortRun(
"Locked interactions may not be used to generate primaries!",
496 "Cannot handle a native G4 primary record!");
500 Geant4PrimaryInteraction::VertexMap::iterator ivfnd, iv, ivend;
501 for(Interaction::VertexMap::const_iterator iend=vm.end(),i=vm.begin(); i!=iend; ++i) {
505 G4PrimaryVertex* v4 =
new G4PrimaryVertex(
v->x,
v->y,
v->z,
v->time);
506 event->AddPrimaryVertex(v4);
507 caller->
print(
"+++++ G4PrimaryVertex at (%+.2e,%+.2e,%+.2e) [mm] %+.2e [ns]",
508 v->x/CLHEP::mm,
v->y/CLHEP::mm,
v->z/CLHEP::mm,
v->time/CLHEP::ns);
509 for(Geant4Vertex::Particles::const_iterator ip=
v->out.begin(); ip!=
v->out.end(); ++ip) {
515 if ( p->
parents.size() == 0 ) {
516 Primaries relevant = getRelevant(visited,prim,pm,primaryConfig,p);
517 for(Primaries::const_iterator j=relevant.begin(); j!= relevant.end(); ++j) {
519 G4PrimaryParticle* p4 = (*j).second;
525 ::snprintf(text,
sizeof(text),
"-> G4Primary[%3d]",num_part);
536 for(
const auto& vtx : prim ) {
538 primaries->
insert(vtx.second, p);