15#include "FairPrimaryGenerator.h"
16#include "RtypesCore.h"
18#include <FairGenerator.h>
19#include <Math/GenVector/Cartesian3D.h>
20#include <Math/GenVector/Polar3D.h>
21#include <Math/GenVector/PxPyPzE4D.h>
26#include <fmt/format.h>
62 virtual auto ReadEvent(FairPrimaryGenerator* prim_gen) ->
bool = 0;
67 template <
typename AngleDist,
typename EnergyDist,
typename PositionDist>
72 : angle_dist_{ angle_dist }
73 , energy_dist_{ energy_dist }
74 , position_dist_{ position_dist }
76 muon_track_output_.init();
80 void set_rd_engine(TRandom* user_rd_engine)
override { rd_engine_ = user_rd_engine; }
81 void set_PID(
int PID)
override { PID_ = PID; }
84 using MomentumPosition = std::pair<ROOT::Math::PxPyPzE4D<double>, ROOT::Math::Cartesian3D<double>>;
85 using Momentum = ROOT::Math::PxPyPzE4D<double>;
86 using AngleRadius = ROOT::Math::Polar3D<double>;
91 AngleDist angle_dist_{};
92 EnergyDist energy_dist_{};
93 PositionDist position_dist_{};
94 TRandom* rd_engine_{ gRandom };
97 auto rd_num_gen_angles(
const AngleDist& angle_dist) -> AngleRadius;
98 auto calculate_momentum_energy(
const double& kinetic_energy,
const AngleInfo& angle_info) -> Momentum;
100 auto calculate_external_position_momentum(
const AngleDist& angle_dist,
101 const EnergyDist& energy_dist,
102 const PositionDist& position_dist) -> MomentumPosition;
103 auto ReadEvent(FairPrimaryGenerator* prim_gen) ->
bool override
105 muon_track_output_.clear();
106 auto& muon_track = muon_track_output_.get().emplace_back();
107 auto momentum_position =
108 MomentumPosition{ calculate_external_position_momentum(angle_dist_, energy_dist_, position_dist_) };
109 muon_track.momentum = momentum_position.first;
110 muon_track.position = momentum_position.second;
111 prim_gen->AddTrack(PID_,
112 momentum_position.first.Px(),
113 momentum_position.first.Py(),
114 momentum_position.first.Pz(),
115 momentum_position.second.X(),
116 momentum_position.second.Y(),
117 momentum_position.second.Z());
122 template <
typename AngleDist,
typename EnergyDist,
typename PositionDist>
123 auto TrackGeneratorImp<AngleDist, EnergyDist, PositionDist>::rd_num_gen_angles(
const AngleDist& angle_dist)
126 auto angles = AngleRadius{};
127 angles.SetPhi(rd_engine_->Uniform(0., 2 * M_PI));
129 angles.SetTheta(angle_dist(rd_engine_));
134 template <
typename AngleDist,
typename EnergyDist,
typename PositionDist>
135 auto TrackGeneratorImp<AngleDist, EnergyDist, PositionDist>::calculate_momentum_energy(
const double& kinetic_energy,
139 auto total_energy = kinetic_energy +
MUON_MASS;
140 auto momentum_energy = Momentum{ 0, 0, 0, total_energy };
141 momentum_energy.SetPx(kinetic_energy * angle_info.sin_theta * angle_info.cos_phi);
142 momentum_energy.SetPy(kinetic_energy * angle_info.cos_theta);
143 momentum_energy.SetPz(kinetic_energy * angle_info.sin_theta * angle_info.sin_phi);
144 return momentum_energy;
147 template <
typename AngleDist,
typename EnergyDist,
typename PositionDist>
148 auto TrackGeneratorImp<AngleDist, EnergyDist, PositionDist>::calculate_external_position_momentum(
153 auto const position = position_dist(rd_engine_);
158 auto const angles = rd_num_gen_angles(angle_dist);
159 auto const energy = energy_dist(rd_engine_);
162 angle_info.
sin_phi = std::sin(angles.Phi());
163 angle_info.cos_phi = std::cos(angles.Phi());
164 angle_info.sin_theta = std::sin(angles.Theta());
165 angle_info.cos_theta = std::cos(angles.Theta());
167 auto position_momentum = MomentumPosition{};
169 position_momentum.second.SetX(position.X() - angle_info.sin_theta * angle_info.cos_phi * detector_size_);
170 position_momentum.second.SetY(position.Y() - angle_info.cos_theta * detector_size_);
171 position_momentum.second.SetZ(position.Z() - angle_info.sin_theta * angle_info.sin_phi * detector_size_);
172 position_momentum.first = calculate_momentum_energy(energy, angle_info);
174 return position_momentum;
181 template <
typename AngleDist,
typename EnergyDist,
typename PositionDist>
189 void set_rd_engine(TRandom* user_rd_engine) { ptr_->set_rd_engine(user_rd_engine); }
195 std::unique_ptr<TrackGeneratorAbstract> ptr_;
196 auto ReadEvent(FairPrimaryGenerator* prim_gen) -> Bool_t
override
198 ptr_->ReadEvent(prim_gen);
205 template <
typename AngleDist,
typename EnergyDist,
typename PositionDist>
210 return std::make_unique<TrackGenerator>(angle_dist, energy_dist, position_dist);
virtual void set_rd_engine(TRandom *user_rd_engine)=0
auto operator=(TrackGeneratorAbstract &&) -> TrackGeneratorAbstract &=default
TrackGeneratorAbstract(TrackGeneratorAbstract &&)=default
virtual void set_detector_size(double detector_size)=0
TrackGeneratorAbstract(const TrackGeneratorAbstract &)=default
auto operator=(const TrackGeneratorAbstract &) -> TrackGeneratorAbstract &=default
virtual auto ReadEvent(FairPrimaryGenerator *prim_gen) -> bool=0
TrackGeneratorAbstract()=default
virtual ~TrackGeneratorAbstract()=default
virtual void set_PID(int PID)=0
TrackGenerator(AngleDist angle_dist, EnergyDist energy_dist, PositionDist position_dist)
void set_detector_size(double detector_size)
auto ReadEvent(FairPrimaryGenerator *prim_gen) -> Bool_t override
auto get_ptr() -> TrackGeneratorAbstract *
void set_rd_engine(TRandom *user_rd_engine)
void set_detector_size(double detector_size) override
TrackGeneratorImp(const AngleDist &angle_dist, const EnergyDist &energy_dist, const PositionDist &position_dist)
auto ReadEvent(FairPrimaryGenerator *prim_gen) -> bool override
void set_PID(int PID) override
void set_rd_engine(TRandom *user_rd_engine) override
Simulation of NeuLAND Bar/Paddle.
constexpr auto default_PID
constexpr auto default_detector_size
auto CreateTrackGenerator(const AngleDist &angle_dist, const EnergyDist &energy_dist, const PositionDist &position_dist)
OutputConnector< std::vector< ElementType > > OutputVectorConnector
ROOT::Math::PxPyPzE4D< double > momentum
ClassDefNV(MuonTrackInfo, 1)
ROOT::Math::Cartesian3D< double > position