00001 // -*- C++ -*- 00002 #include "Rivet/Run.hh" 00003 #include "Rivet/AnalysisHandler.hh" 00004 #include "HepMC/IO_GenEvent.h" 00005 #include "Rivet/Projections/Beam.hh" 00006 #include "Rivet/Math/MathUtils.hh" 00007 #include <limits> 00008 00009 namespace Rivet { 00010 00011 00012 Run::Run(AnalysisHandler& ah) 00013 : _ah(ah), _fileweight(1.0), _xs(NAN) 00014 { } 00015 00016 00017 Run::~Run() { } 00018 00019 00020 Run& Run::setCrossSection(const double xs) { 00021 _xs = xs; 00022 return *this; 00023 } 00024 00025 00026 double Run::crossSection() const { 00027 return _ah.crossSection(); 00028 } 00029 00030 00031 Run& Run::setListAnalyses(const bool dolist) { 00032 _listAnalyses = dolist; 00033 return *this; 00034 } 00035 00036 00037 // Fill event and check for a bad read state 00038 bool Run::readEvent() { 00039 /// @todo Clear rather than new the GenEvent object per-event? 00040 _evt.reset(new GenEvent()); 00041 if (_io->rdstate() != 0 || !_io->fill_next_event(_evt.get()) ) { 00042 Log::getLog("Rivet.Run") << Log::DEBUG << "Read failed. End of file?" << endl; 00043 return false; 00044 } 00045 // Rescale event weights by file-level weight, if scaling is non-trivial 00046 if (!fuzzyEquals(_fileweight, 1.0)) { 00047 for (size_t i = 0; i < _evt->weights().size(); ++i) { 00048 _evt->weights()[i] *= _fileweight; 00049 } 00050 } 00051 return true; 00052 } 00053 00054 00055 bool Run::openFile(const std::string& evtfile, double weight) { 00056 // Set current weight-scaling member 00057 _fileweight = weight; 00058 00059 // Set up HepMC input reader objects 00060 if (evtfile == "-") { 00061 _io.reset(new HepMC::IO_GenEvent(std::cin)); 00062 } else { 00063 // Ignore the HepMC::IO_GenEvent(filename, ios) constructor, since it's only available from HepMC 2.4 00064 _istr.reset(new std::fstream(evtfile.c_str(), std::ios::in)); 00065 _io.reset(new HepMC::IO_GenEvent(*_istr)); 00066 } 00067 if (_io->rdstate() != 0) { 00068 Log::getLog("Rivet.Run") << Log::ERROR << "Read error on file " << evtfile << endl; 00069 return false; 00070 } 00071 return true; 00072 } 00073 00074 00075 bool Run::init(const std::string& evtfile, double weight) { 00076 if (!openFile(evtfile, weight)) return false; 00077 00078 // Read first event to define run conditions 00079 bool ok = readEvent(); 00080 if (!ok) return false; 00081 if (_evt->particles_size() == 0) { 00082 Log::getLog("Rivet.Run") << Log::ERROR << "Empty first event." << endl; 00083 return false; 00084 } 00085 00086 // Initialise AnalysisHandler with beam information from first event 00087 _ah.init(*_evt); 00088 00089 // Set cross-section from command line 00090 if (_xs >= 0.0) { 00091 Log::getLog("Rivet.Run") 00092 << Log::DEBUG << "Setting user cross-section = " << _xs << " pb" << endl; 00093 _ah.setCrossSection(_xs); 00094 } 00095 00096 // List the chosen & compatible analyses if requested 00097 if (_listAnalyses) { 00098 foreach (const std::string& ana, _ah.analysisNames()) { 00099 cout << ana << endl; 00100 } 00101 } 00102 00103 return true; 00104 } 00105 00106 00107 bool Run::processEvent() { 00108 // Set cross-section if found in event and not from command line 00109 #ifdef HEPMC_HAS_CROSS_SECTION 00110 if (std::isnan(_xs) && _evt->cross_section()) { 00111 const double xs = _evt->cross_section()->cross_section(); //< in pb 00112 Log::getLog("Rivet.Run") 00113 << Log::DEBUG << "Setting cross-section = " << xs << " pb" << endl; 00114 _ah.setCrossSection(xs); 00115 } 00116 #endif 00117 // Complain about absence of cross-section if required! 00118 if (_ah.needCrossSection() && !_ah.hasCrossSection()) { 00119 Log::getLog("Rivet.Run") 00120 << Log::ERROR 00121 << "Total cross-section needed for at least one of the analyses. " 00122 << "Please set it (on the command line with '-x' if using the 'rivet' program)" << endl; 00123 return false; 00124 } 00125 00126 // Analyze event 00127 _ah.analyze(*_evt); 00128 00129 return true; 00130 } 00131 00132 00133 bool Run::finalize() { 00134 _evt.reset(); 00135 _istr.reset(); 00136 _io.reset(); 00137 return true; 00138 } 00139 00140 00141 00142 00143 }