All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
HepMCFileGen_module.cc
Go to the documentation of this file.
1 /**
2  * @file HepMCFileGen_module.cc
3  * @brief Producer generating Monte Carlo truth record in LArSoft format from a text file in HepMC format
4  * @date Dec 2019
5  * @author Marco Del Tutto
6  * @comment adapted from TxtFileGen by Brian Rebel
7  */
8 /**
9  * @class evgen::HepMCFileGen
10  *
11  * This module assumes that the input file has the hepevt format for
12  * each event to be simulated. In brief each event contains at least two
13  * lines. The first line contains two entries, the event number (which is
14  * ignored in ART/LArSoft) and the number of particles in the event. Each
15  * following line containes 15 entries to describe each particle. The entries
16  * are:
17  *
18  * 1. status code (should be set to 1 for any particle to be tracked, others
19  * won't be tracked)
20  * 2. the pdg code for the particle
21  * 3. the entry of the first mother for this particle in the event,
22  * 0 means no mother
23  * 4. the entry of the second mother for this particle in the event,
24  * 0 means no mother
25  * 5. the entry of the first daughter for this particle in the event,
26  * 0 means no daughter
27  * 6. the entry of the second daughter for this particle in the event,
28  * 0 means no daughter
29  * 7. x component of the particle momentum
30  * 8. y component of the particle momentum
31  * 9. z component of the particle momentum
32  * 10. energy of the particle
33  * 11. mass of the particle
34  * 12. x position of the particle initial position
35  * 13. y position of the particle initial position
36  * 14. z position of the particle initial position
37  * 15. time of the particle production
38  *
39  * For example, if you want to simulate a single muon with a 5 GeV energy
40  * moving only in the z direction, the entry would be (see onemuon.hepmc):
41  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
42  * 0 1
43  * 1 13 0 0 0 0 0. 0. 1.0 5.0011 0.105 1.0 1.0 1.0 0.0
44  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
45  * Or if you want to simulate a muon neutrino event (see oneneutrino.hepmc):
46  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
47  * 0 3
48  * 0 14 0 0 0 0 0.00350383 0.002469 0.589751 0.589766 0 208.939 63.9671 10.9272 4026.32
49  * 1 13 1 0 0 0 -0.168856 -0.0498011 0.44465 0.489765 105.658 208.939 63.9671 10.9272 4026.32
50  * 1 2212 1 0 0 0 0.151902 -0.124578 0.0497377 0.959907 938.272 208.939 63.9671 10.9272 4026.32
51  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
52  * here the first particle is the initial state neutrino (status code 0, meaning initial state,
53  * not to be prooagated by GEANT). The other particles are the initial state particles.
54  * For the neutrino, write ccnc in place of 1st daugther, and mode (qe, res, ...)
55  * in place of 2nd daugther.
56  *
57  * There are some assumptions that go into using this format that may not
58  * be obvious. The first is that only particles with status code = 1
59  * are tracked in the LArSoft/Geant4 combination making the mother daughter
60  * relations somewhat irrelevant. That also means that you should let
61  * Geant4 handle any decays.
62  *
63  * The units in LArSoft are cm for distances and ns for time.
64  * The use of `TLorentzVector` below does not imply space and time have the same units
65  * (do not use `TLorentzVector::Boost()`).
66  */
67 #include <string>
68 #include <fstream>
69 #include <math.h>
70 #include <map>
71 #include <iomanip>
72 #include <algorithm>
73 #include <sstream>
74 #include <glob.h>
75 #include <cstdlib> // for unsetenv()
76 #include "art/Framework/Core/EDProducer.h"
77 #include "art/Framework/Core/ModuleMacros.h"
78 #include "art/Framework/Principal/Event.h"
79 #include "art/Framework/Principal/SubRun.h"
80 #include "fhiclcpp/ParameterSet.h"
81 #include "cetlib_except/exception.h"
82 #include "art/Framework/Services/Registry/ServiceHandle.h"
83 #include "cetlib/search_path.h"
84 #include "cetlib/getenv.h"
85 #include "cetlib/split_path.h"
86 #include "cetlib_except/exception.h"
87 #include "messagefacility/MessageLogger/MessageLogger.h"
88 #include "TLorentzVector.h"
92 #include "nusimdata/SimulationBase/MCTruth.h"
93 #include "nusimdata/SimulationBase/MCParticle.h"
94 #include "ifdh.h"
95 #include "ifdh_art/IFDHService/IFDH_service.h" // ifdh_ns::IFDH
96 #undef USE_IFDH_SERVICE // ifdh for now
97 
98 namespace evgen {
99  class HepMCFileGen;
100 }
101 class evgen::HepMCFileGen : public art::EDProducer {
102 public:
103  explicit HepMCFileGen(fhicl::ParameterSet const & p);
104  void produce(art::Event & e) override;
105  void beginJob() override;
106  void beginRun(art::Run & run) override;
107  void endSubRun(art::SubRun& sr) override;
108 private:
109  std::ifstream open_file();
110  std::string fInputFilePath; ///< Path to the HEPMC input file, relative to `FW_SEARCH_PATH`.
111  std::ifstream* fInputFile;
112 
113  double fEventsPerPOT; ///< Number of events per POT (to be set)
114  int fEventsPerSubRun; ///< Keeps track of the number of processed events per subrun
115  // ifdh_ns::ifdh* fIFDH; ///< (optional) flux file handling
116 };
117 //------------------------------------------------------------------------------
118 evgen::HepMCFileGen::HepMCFileGen(fhicl::ParameterSet const & p)
119  : EDProducer{p}
120  , fInputFilePath(p.get<std::string>("InputFilePath"))
121  , fInputFile(nullptr)
122  , fEventsPerPOT{p.get<double>("EventsPerPOT", -1.)}
123  , fEventsPerSubRun(0)
124 {
125  produces< std::vector<simb::MCTruth> >();
126  produces< sumdata::RunData, art::InRun >();
127  produces< sumdata::POTSummary, art::InSubRun >();
128 }
129 //------------------------------------------------------------------------------
130 
132 {
133  /*
134  * The plan:
135  * 1. expand the path in FW_SEARCH_PATH (only if relative path)
136  * 2. copy it into scratch area (only if starts with `/pnfs`)
137  * 3. open the file (original or copy) and return the opened file
138  *
139  * Throws a cet::exception if eventually file is not found.
140  */
141 
142  std::string fullFileName = fInputFilePath;
143 
144  cet::search_path searchPath("FW_SEARCH_PATH");
145  if (searchPath.find_file(fInputFilePath, fullFileName)) {
146  mf::LogDebug("HepMCFileGen")
147  << "Input file '" << fInputFilePath << "' found in FW_SEARCH_PATH:\n"
148  << fullFileName
149  ;
150  }
151 
152  //
153  // prepare the file with IFDH, if path starts with `/pnfs`
154  //
155  if (fullFileName.compare(0, 6, "/pnfs/") == 0) {
156  fullFileName = art::ServiceHandle<IFDH>()->fetchInput(fullFileName);
157  mf::LogDebug("HepMCFileGen")
158  << "IFDH fetch: '" << fInputFilePath << "' -> '" << fullFileName << "'";
159  }
160 
161  //
162  // attempt to open
163  //
164  mf::LogDebug("HepMCFileGen")
165  << "Reading input file '" << fInputFilePath << "' as:\n" << fullFileName;
166  std::ifstream inputFile(fullFileName);
167  if (inputFile) return inputFile;
168 
169  // all attempts failed, give up:
170  throw cet::exception("HepMCFileGen")
171  << "HEPMC input file '" << fInputFilePath << "' can't be opened.\n";
172 
173 } // evgen::HepMCFileGen::open_file()
174 
175 
176 
177 //------------------------------------------------------------------------------
179 {
180  fInputFile = new std::ifstream(open_file());
181 
182 }
183 //------------------------------------------------------------------------------
184 void evgen::HepMCFileGen::beginRun(art::Run& run)
185 {
186  fEventsPerSubRun = 0;
187  art::ServiceHandle<geo::Geometry const> geo;
188  run.put(std::make_unique<sumdata::RunData>(geo->DetectorName()));
189  }
190 //------------------------------------------------------------------------------
191 void evgen::HepMCFileGen::endSubRun(art::SubRun& sr)
192  {
193  auto p = std::make_unique<sumdata::POTSummary>();
194  p->totpot = fEventsPerSubRun * fEventsPerPOT;
195  p->totgoodpot = fEventsPerSubRun * fEventsPerPOT;
196  sr.put(std::move(p));
197  return;
198  }
199 //------------------------------------------------------------------------------
200 void evgen::HepMCFileGen::produce(art::Event & e)
201 {
202  // check that the file is still good
203  if( !fInputFile->good() || fInputFile->peek() == EOF) {
204  open_file();
205  }
206  if( !fInputFile->good() || fInputFile->peek() == EOF) {
207  throw cet::exception("HepMCFileGen") << "input text file "
208  << " cannot be read in produce().\n";
209  }
210  std::unique_ptr< std::vector<simb::MCTruth> > truthcol(new std::vector<simb::MCTruth>);
211  simb::MCTruth truth;
212  // declare the variables for reading in the event record
213  int event = 0;
214  unsigned short nParticles = 0;
215  int status = 0;
216  int pdg = 0;
217  int firstMother = 0;
218  int secondMother = 0;
219  int firstDaughter = 0;
220  int secondDaughter = 0;
221  double xMomentum = 0.;
222  double yMomentum = 0.;
223  double zMomentum = 0.;
224  double energy = 0.;
225  double mass = 0.;
226  double xPosition = 0.;
227  double yPosition = 0.;
228  double zPosition = 0.;
229  double time = 0.;
230  bool set_neutrino = false;
231  // neutrino
232  int ccnc = -1, mode = -1, itype = -1, target = -1, nucleon = -1, quark = -1;
233  double w = -1, x = -1, y = -1, qsqr = -1;
234  // read in line to get event number and number of particles
235  std::string oneLine;
236  std::getline(*fInputFile, oneLine);
237  std::istringstream inputLine;
238  inputLine.str(oneLine);
239  inputLine >> event >> nParticles;
240  // now read in all the lines for the particles
241  // in this interaction. only particles with
242  // status = 1 get tracked in Geant4. see GENIE GHepStatus
243  for(unsigned short i = 0; i < nParticles; ++i){
244  std::getline(*fInputFile, oneLine);
245  inputLine.clear();
246  inputLine.str(oneLine);
247  inputLine >> status >> pdg
248  >> firstMother >> secondMother >> firstDaughter >> secondDaughter
249  >> xMomentum >> yMomentum >> zMomentum >> energy >> mass
250  >> xPosition >> yPosition >> zPosition >> time;
251  std::cout<<"pdg_all"<<pdg<<"xmomentum_all"<<xMomentum<<"ymomentum_all"<<yMomentum<<"zposition_all"<<zPosition<<std::endl;
252  TLorentzVector pos(xPosition, yPosition, zPosition, time);
253  TLorentzVector mom(xMomentum, yMomentum, zMomentum, energy);
254  simb::MCParticle part(i, pdg, "primary", firstMother, mass, status);
255  part.AddTrajectoryPoint(pos, mom);
256  //if (abs(pdg) == 18 || abs(pdg) == 12)
257  if (abs(pdg) == 52 ) // Animesh made changes
258  {
259  set_neutrino = true;
260  ccnc = firstDaughter; // for the neutrino we write ccnc in place of 1st daugther
261  mode = secondDaughter; // for the neutrino we write mode in place of 2nd daugther
262  itype = -1;
263  target = nucleon = quark = w = x = y = qsqr = -1;
264  std::cout<<"pdg_mother"<<pdg<<"xmomentum_mother"<<xMomentum<<"ymomentum_mother"<<yMomentum<<"zposition_mother"<<zPosition<<std::endl;
265  }
266  truth.Add(part);
267  std::cout << i << " Particle added with Pdg " << part.PdgCode() << ", Mother " << part.Mother() << ", track id " << part.TrackId() << ", ene " << part.E() << std::endl;
268  }
269 
270  if (set_neutrino) {
271  truth.SetNeutrino(ccnc,
272  mode,
273  itype,
274  target,
275  nucleon,
276  quark,
277  w,
278  x,
279  y,
280  qsqr);
281  // set the neutrino information in MCTruth
282  truth.SetOrigin(simb::kBeamNeutrino);
283  // truth.SetGeneratorInfo(simb::Generator_t::kGENIE,
284  // __GENIE_RELEASE__,
285  // {{"tune", fTuneName}});
286  }
287  //std::cout << " neutrino " << truth.GetNeutrino() << std::endl;
288  //std::cout << " lepton pdg " << truth.GetNeutrino().Lepton().PdgCode() << " ene " << truth.GetNeutrino().Lepton().E() << std::endl;
289  truthcol->push_back(truth);
290  e.put(std::move(truthcol));
291  fEventsPerSubRun++;
292  return;
293 }
294 DEFINE_ART_MODULE(evgen::HepMCFileGen)
295 
std::ifstream * fInputFile
var pdg
Definition: selectors.fcl:14
int fEventsPerSubRun
Keeps track of the number of processed events per subrun.
std::string fInputFilePath
Path to the HEPMC input file, relative to FW_SEARCH_PATH.
process_name opflash particleana ie x
pdgs p
Definition: selectors.fcl:22
void endSubRun(art::SubRun &sr) override
T abs(T value)
process_name opflash particleana ie ie y
void beginRun(art::Run &run) override
const char mode
Definition: noise_ana.cxx:20
HepMCFileGen(fhicl::ParameterSet const &p)
double fEventsPerPOT
Number of events per POT (to be set)
float mass
Definition: dedx.py:47
do i e
art framework interface to geometry description
BEGIN_PROLOG could also be cout
void produce(art::Event &e) override