MARLEY (Model of Argon Reaction Low Energy Yields) v2.0.0
A Monte Carlo event generator for tens-of-MeV neutrino interactions
Loading...
Searching...
No Matches
EventFileReader.cc
1
4//
5// This file is part of MARLEY (Model of Argon Reaction Low Energy Yields)
6//
7// MARLEY is free software: you can redistribute it and/or modify it under the
8// terms of version 3 of the GNU General Public License as published by the
9// Free Software Foundation.
10//
11// For the full text of the license please see COPYING or
12// visit http://opensource.org/licenses/GPL-3.0
13//
14// Please respect the MCnet academic usage guidelines. See GUIDELINES
15// or visit https://www.montecarlonet.org/GUIDELINES for details.
16
17// Standard library includes
18#include <iterator>
19
20// HepMC3 includes
21#include "HepMC3/GenEvent.h"
22#include "HepMC3/ReaderAscii.h"
23
24// MARLEY includes
25#include "marley/marley_utils.hh"
26#include "marley/Error.hh"
27#include "marley/FileManager.hh"
28#include "marley/EventFileReader.hh"
29
30#ifdef USE_ROOT
31 #include "TError.h"
32 #include "TFile.h"
33 #include "TTree.h"
34
35 #include "HepMC3/Data/GenEventData.h"
36#endif
37
38
39marley::EventFileReader::EventFileReader( const std::string& file_name )
40 : file_name_( file_name )
41{
42}
43
44// Try to read an event from the file using each possible format. If we
45// succeed, set the appropriate format code and return true. If all fail,
46// return false.
48
49 // Before we bother to check anything else, see if the file exists and is
50 // readable. Skip the MARLEY search path in this case (the event file should
51 // have been passed to the constructor with any needed path specification).
52 // Complain if the file cannot be read.
53 const auto& fm = marley::FileManager::Instance();
54 if ( fm.find_file(file_name_, "").empty() ) throw marley::Error( "Could"
55 " not read from the file \"" + file_name_ + '\"' );
56
57 // Create a temporary event object to use for the following format checks
58 HepMC3::GenEvent temp_event;
59
60 #ifdef USE_ROOT
61 // Before checking if the file is in ROOT format, completely suppress any
62 // error messages from ROOT.
63 auto temp_error_level = gErrorIgnoreLevel;
64 gErrorIgnoreLevel = kFatal;
65
66 // Try to read in a HepMC3::GenEvent from the file assuming that the ROOT
67 // output format was used
68 tfile_ = std::unique_ptr<TFile>( TFile::Open(file_name_.c_str(), "read") );
69
70 // We've completed the ROOT format check, so restore the old error messaging
71 // behavior
72 gErrorIgnoreLevel = temp_error_level;
73
74 if ( tfile_ ) {
75 format_ = marley::OutputFile::Format::ROOT;
76 return true;
77 }
78 #endif
79
80 // Try to read in a HepMC3::GenEvent from the file assuming that the ASCII
81 // output format was used
82 HepMC3::ReaderAscii temp_reader( file_name_ );
83 bool read_ok = temp_reader.read_event( temp_event );
84 if ( read_ok ) {
85
86 // Save the flux-averaged total xsec from the run information for easy
87 // retrieval
88 auto run_info = temp_event.run_info();
89 if ( !run_info ) {
90 throw marley::Error( "Missing run information while parsing an"
91 " ASCII-format HepMC3 file" );
92 }
93
94 this->get_flux_averaged_xsec( *run_info );
95
96 format_ = marley::OutputFile::Format::ASCII;
97 return true;
98 }
99
100 // TODO: add other formats here as needed
101
102 // If everything else failed, then complain that events could not be read
103 return false;
104}
105
107 switch ( format_ ) {
108
109 case marley::OutputFile::Format::ASCII:
110 {
111 in_.open( file_name_ );
112 reader_ = std::make_shared< HepMC3::ReaderAscii >( in_ );
113 break;
114 }
115
116 #ifdef USE_ROOT
117 case marley::OutputFile::Format::ROOT:
118 {
119 tfile_->GetObject( "MARLEY_event_tree", ttree_ );
120 if ( !ttree_ ) throw marley::Error( "Failed to load MARLEY event TTree"
121 " from the ROOT file \"" + file_name_ + '\"' );
122
123 temp_event_data_ = std::make_unique< HepMC3::GenEventData >();
124 temp_event_data_ptr_ = temp_event_data_.get();
125 ttree_->SetBranchAddress( "event", &temp_event_data_ptr_ );
126
127 tfile_->GetObject( "MARLEY_run_info", temp_run_info_data_ );
128 if ( !temp_run_info_data_ ) throw marley::Error( "Failed to load"
129 " MARLEY run information from the ROOT file \"" + file_name_ + '\"' );
130
131 run_info_ = std::make_shared< HepMC3::GenRunInfo >();
132 run_info_->read_data( *temp_run_info_data_ );
133
134 this->get_flux_averaged_xsec( *run_info_ );
135
136 break;
137 }
138 #endif
139
140 default:
141 throw marley::Error( "Unrecognized file format encountered in"
142 " marley::EventFileReader::initialize()" );
143 }
144}
145
147{
148 this->ensure_initialized();
149 switch ( format_ ) {
150
151 case marley::OutputFile::Format::ASCII:
152 {
153 bool read_ok = reader_->read_event( ev );
154 return read_ok && in_;
155 break;
156 }
157
158 #ifdef USE_ROOT
159 case marley::OutputFile::Format::ROOT:
160 {
161 ++event_num_;
162 if ( event_num_ < ttree_->GetEntries() ) {
163
164 temp_event_data_->particles.clear();
165 temp_event_data_->vertices.clear();
166 temp_event_data_->links1.clear();
167 temp_event_data_->links2.clear();
168 temp_event_data_->attribute_id.clear();
169 temp_event_data_->attribute_name.clear();
170 temp_event_data_->attribute_string.clear();
171
172 ttree_->GetEntry( event_num_ );
173 ev.read_data( *temp_event_data_ );
174 ev.set_run_info( run_info_ );
175 return true;
176 }
177
178 ev = HepMC3::GenEvent();
179 return false;
180
181 break;
182 }
183 #endif
184
185 default:
186 throw marley::Error( "Unrecognized file format encountered in"
187 " marley::EventFileReader::next_event()" );
188 }
189
190 ev = HepMC3::GenEvent();
191 return false;
192}
193
194marley::EventFileReader::operator bool() const {
195
196 switch ( format_ ) {
197
198 case marley::OutputFile::Format::ASCII:
199 {
200 return static_cast< bool >( in_ );
201 break;
202 }
203
204 #ifdef USE_ROOT
205 case marley::OutputFile::Format::ROOT:
206 {
207 return ( tfile_ && ttree_ && event_num_ < ttree_->GetEntries() );
208 break;
209 }
210 #endif
211
212 default:
213 throw marley::Error( "Unrecognized file format encountered in"
214 " marley::EventFileReader::operator bool()" );
215 }
216
217 return false;
218}
219
221 if ( !initialized_ ) {
222
223 if ( !this->deduce_file_format() ) throw marley::Error( "Could not"
224 " read MARLEY events from the file \"" + file_name_ + '\"' );
225
226 this->initialize();
227 initialized_ = true;
228 }
229}
230
232 this->ensure_initialized();
233 if ( natural_units ) return flux_avg_tot_xs_;
234 double result = flux_avg_tot_xs_ * marley_utils::hbar_c2
235 * marley_utils::fm2_to_minus40_cm2 * 1e2; // 10^{-42} cm^2
236 return result;
237}
238
240 const HepMC3::GenRunInfo& run_info )
241{
242 auto avg_xsec_attr = run_info.attribute< HepMC3::DoubleAttribute >(
243 "NuHepMC.FluxAveragedTotalCrossSection" );
244 if ( !avg_xsec_attr ) {
245 throw marley::Error( "Missing flux-averaged total cross section while"
246 " parsing a HepMC3 file" );
247 }
248
249 // Retrieve the flux-averaged total cross section and convert it back to
250 // natural units (MeV^{-2}) from picobarn
251 flux_avg_tot_xs_ = avg_xsec_attr->value()
252 / ( marley_utils::hbar_c2 * marley_utils::fm2_to_picobarn );
253}
Attribute that holds a real number as a double.
Definition Attribute.h:245
Stores event-related information.
Definition GenEvent.h:47
void set_run_info(std::shared_ptr< GenRunInfo > run)
Set the GenRunInfo object by smart pointer.
Definition GenEvent.h:148
void read_data(const GenEventData &data)
Fill GenEvent based on GenEventData.
std::shared_ptr< GenRunInfo > run_info() const
Get a pointer to the the GenRunInfo object.
Definition GenEvent.h:144
Stores run-related information.
Definition GenRunInfo.h:33
std::shared_ptr< T > attribute(const std::string &name) const
Get attribute of type T.
Definition GenRunInfo.h:181
GenEvent I/O parsing for structured text files.
Definition ReaderAscii.h:31
bool read_event(GenEvent &evt) override
Load event from file.
Base class for all exceptions thrown by MARLEY functions.
Definition Error.hh:26
virtual void initialize()
Prepares the file for reading the events.
virtual bool deduce_file_format()
Helper function that auto-detects which of the available output formats is appropriate for the reques...
bool initialized_
Flag that indicates whether initialize() has been called or not.
double flux_avg_tot_xs_
Flux-averaged total cross section (MeV -2) used to produce the events in the file,...
virtual bool next_event(HepMC3::GenEvent &ev)
Read the next MARLEY event record from the file.
void ensure_initialized()
This function should be called at the beginning of all public member functions of EventFileReader tha...
std::string file_name_
Name of the file (with any needed path specification) to be read.
void get_flux_averaged_xsec(const HepMC3::GenRunInfo &run_info)
double flux_averaged_xsec(bool natural_units=false)
Returns the flux-averaged total cross section used to produce the events in the file.
std::shared_ptr< HepMC3::ReaderAscii > reader_
Helper object used to interpret ASCII-format HepMC3 files.
OutputFile::Format format_
Format of the output file being read.
std::ifstream in_
Input stream used to read from textual output formats.
static const FileManager & Instance()
Get a const reference to the singleton instance of the FileManager.