LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
Decay0Gen_module.cc
Go to the documentation of this file.
1 
8 
9 #include <bxdecay0/event.h> // Decay event data model
10 #include <bxdecay0/i_random.h>
11 #if defined __clang__
12 #pragma clang diagnostic push
13 #pragma clang diagnostic ignored "-Wmismatched-tags"
14 #include <bxdecay0/decay0_generator.h> // Decay0 generator with OOP interface
15 #pragma clang diagnostic pop
16 #else
17 #include <bxdecay0/decay0_generator.h> // Decay0 generator with OOP interface
18 #endif
19 #include <bxdecay0/particle.h>
20 
21 namespace evgen {
24 
25  class Decay0Gen : public evgen::BaseRadioGen {
26  public:
27  explicit Decay0Gen(fhicl::ParameterSet const& pset);
29  {
30  for (auto& i : m_decay0_generator) {
31  i->reset();
32  }
33  }
34 
35  private:
36  // This is called for each event.
38  void beginJob_radio();
39  void endJob_radio();
40 
41  std::shared_ptr<clhep_random> m_random_decay0;
42 
43  // Declare a Decay0 generator:
44  std::vector<std::unique_ptr<bxdecay0::decay0_generator>> m_decay0_generator;
47  };
48 
50  class clhep_random : public bxdecay0::i_random {
51  public:
53  clhep_random(CLHEP::HepRandomEngine& gen) : m_generator(gen), m_rand_flat(gen) {}
54 
56  virtual double operator()()
57  {
58  double v = m_rand_flat.fire(0., 1.);
59  return v;
60  }
61  CLHEP::HepRandomEngine& m_generator;
62  CLHEP::RandFlat m_rand_flat;
63  virtual ~clhep_random(){};
64  };
65 
66 }
67 
68 namespace evgen {
69 
71  {
72  std::string isotope = "";
73  m_single_isotope_mode = pset.get_if_present<std::string>("isotope", isotope);
74 
75  if (not m_single_isotope_mode) {
76  fhicl::ParameterSet decay_chain = pset.get<fhicl::ParameterSet>("decay_chain");
77  int index = 0;
78 
79  while (
80  decay_chain.get_if_present<std::string>("isotope_" + std::to_string(index++), isotope)) {
81  m_isotope.push_back(isotope);
82  }
83  }
84  else {
85  m_isotope.push_back(isotope);
86  }
87 
88  m_random_decay0 = std::make_shared<clhep_random>(GetRandomEngine());
89 
90  for (auto const& isotope : m_isotope) {
91  auto generator = std::make_unique<bxdecay0::decay0_generator>();
92  generator->reset();
93 
94  // Configure the Decay0 generator:
95  generator->set_decay_category(bxdecay0::decay0_generator::DECAY_CATEGORY_BACKGROUND);
96  generator->set_decay_isotope(isotope.c_str());
97  try {
98  generator->initialize(*m_random_decay0);
99  }
100  catch (...) {
101  throw cet::exception("Decay0Gen") << "The inialisation of Decay0 failed. Maybe the isotope "
102  << isotope << " doesn't exists?\n";
103  }
104  m_decay0_generator.push_back(std::move(generator));
105  }
106  }
107 
109  {
111  double T0 = 0, T1 = 0;
112  GetTs(T0, T1);
114  tfs->make<TH1D>("TimeDiff", ";Time Diff[ns];n particles", (int)((T1) / 10000), 0, T1);
115  }
116 
118  {
119  if (GetNEvents()) m_timediff_TH1D->Scale(1. / GetNEvents());
120  }
121 
122  //____________________________________________________________________________
124  {
125  //unique_ptr allows ownership to be transferred to the art::Event after the put statement
126  std::unique_ptr<std::vector<simb::MCTruth>> truthcol(new std::vector<simb::MCTruth>);
127 
128  simb::MCTruth truth;
130  int track_id = -1;
131  const std::string primary_str("primary");
132  int bad_position = 0;
133  int tentative_decay = 0;
134  for (auto const& decay0_gen : m_decay0_generator) {
135  int n_decay = GetNDecays();
136 
137  tentative_decay += n_decay;
138  for (int iDecay = 0; iDecay < n_decay; ++iDecay) {
139  TLorentzVector position;
140  if (GetGoodPositionTime(position)) {
141 
142  bxdecay0::event gendecay; // Declare an empty decay event
143  decay0_gen->shoot(*m_random_decay0, gendecay); // Randomize the decay event
144  std::vector<bxdecay0::particle> part = gendecay.get_particles();
145 
146  double t_alpha = 0;
147  double t_electron = 0;
148  for (auto const& p : part) {
149  // alpha particles need a little help since they're not in the TDatabasePDG table
150  // so don't rely so heavily on default arguments to the MCParticle constructor
152  if (not p.is_valid()) {
153  p.print(std::cout);
154  throw cet::exception("Decay0Gen") << "Invalid part generated by Decay0, printed "
155  "above (no clue what that means so throw)";
156  }
157 
158  double mass = bxdecay0::particle_mass_MeV(p.get_code());
159  int pdg = 0;
160  //int simple_pdg=0; // simple_pdg is unused here
161 
162  if (p.is_alpha()) {
163  pdg = 1000020040;
164  part = simb::MCParticle(track_id, pdg, primary_str, -1, mass / 1000, 1);
165  }
166  else if (p.is_gamma()) {
167  pdg = 22;
168  part = simb::MCParticle(track_id, pdg, primary_str);
169  }
170  else if (p.is_positron()) {
171  pdg = -11;
172  part = simb::MCParticle(track_id, pdg, primary_str);
173  }
174  else if (p.is_electron()) {
175  pdg = 11;
176  part = simb::MCParticle(track_id, pdg, primary_str);
177  }
178  else if (p.is_neutron()) {
179  pdg = 2112;
180  part = simb::MCParticle(track_id, pdg, primary_str);
181  }
182  else if (p.is_proton()) {
183  pdg = 2212;
184  part = simb::MCParticle(track_id, pdg, primary_str);
185  }
186  else {
187  p.print(std::cout);
188  throw cet::exception("Decay0Gen") << "Particle above is weird, cannot recognise it.";
189  }
190 
191  if ((p.is_positron() or p.is_electron()) and t_electron == 0) {
192  t_electron = p.get_time();
193  }
194  if (p.is_alpha() and t_alpha == 0) { t_alpha = p.get_time(); }
195  track_id--;
196  TLorentzVector mom(p.get_px() / 1000.,
197  p.get_py() / 1000.,
198  p.get_pz() / 1000.,
199  sqrt(p.get_p() * p.get_p() + mass * mass) / 1000.);
200 
201  TLorentzVector this_part_position = position;
202  double t = position.T();
203  this_part_position.SetT(t + p.get_time() * 1e9);
204 
205  part.AddTrajectoryPoint(this_part_position, mom);
206 
207  truth.Add(part);
208 
209  FillHistos(part);
210  }
211  if (abs(t_alpha - t_electron) > 1.e-15) {
212  m_timediff_TH1D->Fill(1e9 * abs(t_alpha - t_electron));
213  }
214  gendecay.reset();
215  }
216  else { // !GetGoodPosition
217  ++bad_position;
218  }
219  } // idecay
220  } // m_decay_generators
221 
222  MF_LOG_DEBUG("Decay0Gen") << truth;
223  if (bad_position > 0) {
224  MF_LOG_ERROR("Decay0Gen")
225  << "There were " << bad_position
226  << " failed attempts to get a good position to generate a decay out of the target "
227  << tentative_decay << " decays.\n"
228  << "If these 2 numbers are close together, it means that the rate of your background is "
229  "wrong (underestimated).\n"
230  << "You can fix this by increasing the parameter \"max_tries_event\" to a bigger number "
231  "(default is 1M) in your fhicl.\n"
232  << "Another way is to change the \"volume_rand\" to a smaller one.\n";
233  }
234  truthcol->push_back(truth);
235  evt.put(std::move(truthcol));
236  }
237 
238 } //end namespace evgen
239 
void AddTrajectoryPoint(TLorentzVector const &position, TLorentzVector const &momentum)
Definition: MCParticle.h:258
CLHEP::RandFlat m_rand_flat
void SetOrigin(simb::Origin_t origin)
Definition: MCTruth.h:82
virtual double operator()()
Main operator.
constexpr auto abs(T v)
Returns the absolute value of the argument.
#define MF_LOG_ERROR(category)
Decay0Gen(fhicl::ParameterSet const &pset)
void FillHistos(simb::MCParticle &part)
Definition: BaseRadioGen.h:788
PutHandle< PROD > put(std::unique_ptr< PROD > &&edp, std::string const &instance={})
Definition: Event.h:77
TString part[npart]
Definition: Style.C:32
std::vector< std::unique_ptr< bxdecay0::decay0_generator > > m_decay0_generator
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:65
decltype(auto) constexpr to_string(T &&obj)
ADL-aware version of std::to_string.
single particles thrown at the detector
Definition: MCTruth.h:26
T get(std::string const &key) const
Definition: ParameterSet.h:314
CLHEP::HepRandomEngine & GetRandomEngine()
Definition: BaseRadioGen.h:92
std::vector< std::string > m_isotope
isotope to simulate. Example: "Ar39"
Definition: BaseRadioGen.h:90
CLHEP::HepRandomEngine & m_generator
Wrapper functor for a standard random number generator.
bool GetGoodPositionTime(TLorentzVector &position)
Definition: BaseRadioGen.h:521
void Add(simb::MCParticle const &part)
Definition: MCTruth.h:80
void GetTs(double &T0, double &T1)
Definition: BaseRadioGen.h:94
std::optional< T > get_if_present(std::string const &key) const
Definition: ParameterSet.h:267
#define MF_LOG_DEBUG(id)
void produce_radio(art::Event &evt)
TCEvent evt
Definition: DataStructs.cxx:8
Event generator information.
Definition: MCTruth.h:32
clhep_random(CLHEP::HepRandomEngine &gen)
Constructor.
Float_t e
Definition: plot.C:35
std::shared_ptr< clhep_random > m_random_decay0
Event Generation using GENIE, cosmics or single particles.
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33