31 namespace ActsFatras {
56 template <
typename generator_t>
61 return std::make_pair(std::numeric_limits<Scalar>::infinity(),
62 std::numeric_limits<Scalar>::infinity());
66 if (particleParametrisation.first == particle.
pdg()) {
67 std::uniform_real_distribution<double> uniformDistribution{0., 1.};
71 singleParticleParametrisation = particleParametrisation.second;
74 singleParticleParametrisation,
78 const auto& distribution =
81 std::make_pair(std::numeric_limits<Scalar>::infinity(),
83 uniformDistribution(generator), distribution));
87 return std::make_pair(std::numeric_limits<Scalar>::infinity(),
88 std::numeric_limits<Scalar>::infinity());
99 template <
typename generator_t>
101 std::vector<Particle>& generated)
const {
109 if (particleParametrisation.first == particle.
pdg()) {
110 std::uniform_real_distribution<double> uniformDistribution{0., 1.};
114 singleParticleParametrisation = particleParametrisation.second;
117 singleParticleParametrisation,
120 std::normal_distribution<double> normalDistribution{0., 1.};
122 const bool interactSoft =
128 uniformDistribution(generator),
135 parametrisationOfType =
141 if (!parametrisationOfMultiplicity.validParametrisation) {
147 generator, parametrisationOfMultiplicity, parametrisation.
momentum);
148 if (!kinematics.has_value()) {
149 return run(generator, particle, generated);
153 const std::vector<int> pdgIds =
155 particle.
pdg(), interactSoft);
159 generator, pdgIds, kinematics->first, kinematics->second, particle,
160 parametrisation.
momentum, interactSoft);
167 generated.insert(generated.end(), particles.begin(), particles.end());
168 return !interactSoft;
186 float particleMomentum)
const;
195 return rnd <= probability;
219 template <
typename generator_t>
232 template <
typename generator_t>
236 ParametersWithFixedMultiplicity& parametrisation)
const;
246 template <
typename generator_t>
250 ParametersWithFixedMultiplicity& parametrisation,
251 float initialMomentum)
const;
264 float parametrizedMomentum)
const;
274 template <
typename generator_t>
275 std::optional<std::pair<Acts::ActsDynamicVector, Acts::ActsDynamicVector>>
294 std::pair<ActsFatras::Particle::Scalar, ActsFatras::Particle::Scalar>
311 template <
typename generator_t>
313 generator_t&
generator,
const std::vector<int>& pdgId,
316 float parametrizedMomentum,
bool soft)
const;
346 template <
typename generator_t>
352 if (multiplicity == 0) {
357 std::vector<int> pdgIds;
358 pdgIds.reserve(multiplicity);
360 std::uniform_real_distribution<float> uniformDistribution{0., 1.};
363 auto citProducer = pdgMap.cbegin();
364 while (citProducer->first != particlePdg && citProducer != pdgMap.end()) {
368 const std::vector<std::pair<int, float>>& mapInitial = citProducer->second;
372 pdgIds.push_back(particlePdg);
375 const float rndInitial = uniformDistribution(generator);
378 std::lower_bound(mapInitial.begin(), mapInitial.end(), rndInitial,
379 [](
const std::pair<int, float>&
element,
380 float random) {
return element.second < random; })
388 citProducer = pdgMap.cbegin();
389 while (citProducer->first != pdgIds[
i - 1] && citProducer != pdgMap.end()) {
394 const std::vector<std::pair<int, float>>& map = citProducer->second;
395 const float rnd = uniformDistribution(generator);
397 std::lower_bound(map.begin(), map.end(),
rnd,
398 [](
const std::pair<int, float>&
element,
399 float random) {
return element.second < random; })
405 template <
typename generator_t>
409 parametrisation)
const {
413 parameters.resize(size);
416 for (
unsigned int i = 0;
i <
size;
i++) {
418 std::normal_distribution<Acts::ActsScalar>
dist{
420 parameters[
i] =
dist(generator);
426 for (
unsigned int i = 0;
i <
size;
i++) {
427 const double cdf = (std::erff(parameters[
i]) + 1) * 0.5;
434 template <
typename generator_t>
439 float initialMomentum)
const {
443 parameters.resize(size);
446 for (
unsigned int i = 0;
i <
size;
i++) {
448 std::normal_distribution<Acts::ActsScalar>
dist{
450 parameters[
i] =
dist(generator);
457 for (
unsigned int i = 0;
i <
size;
i++) {
458 const float cdf = (std::erff(parameters[
i]) + 1) * 0.5;
465 const float sum = momenta.sum();
466 const float scale = parameters.template tail<1>()(0, 0) /
sum;
467 momenta *= scale * initialMomentum;
471 template <
typename generator_t>
472 std::optional<std::pair<Acts::ActsDynamicVector, Acts::ActsDynamicVector>>
478 unsigned int trials = 0;
484 while (!
match(momenta, invariantMasses, momentum)) {
495 return std::make_pair(momenta, invariantMasses);
498 template <
typename generator_t>
500 generator_t&
generator,
const std::vector<int>& pdgId,
503 float parametrizedMomentum,
bool soft)
const {
504 std::uniform_real_distribution<double> uniformDistribution{0., 1.};
505 const auto& initialDirection = initialParticle.
direction();
508 const unsigned int size = momenta.size();
510 std::vector<Particle> result;
511 result.reserve(size);
514 for (
unsigned int i = 0;
i <
size;
i++) {
516 const float invariantMass = invariantMasses[
i];
517 const float p1p2 = 2. * momentum * parametrizedMomentum;
518 const float costheta = 1. - invariantMass * invariantMass / p1p2;
520 const auto phiTheta =
521 globalAngle(phi, theta, uniformDistribution(generator) * 2. * M_PI,
522 std::acos(costheta));
523 const auto direction =
528 p.
setProcess(ProcessType::eNuclearInteraction)
530 .setAbsoluteMomentum(momentum)
535 if (
i == 0 && soft) {