24#define BOOST_TEST_MODULE Test GeneratorHepMC indexed access
25#define BOOST_TEST_MAIN
26#define BOOST_TEST_DYN_LINK
27#include <boost/test/unit_test.hpp>
34#include <HepMC3/GenEvent.h>
35#include <HepMC3/GenParticle.h>
36#include <HepMC3/GenRunInfo.h>
37#include <HepMC3/ReaderAscii.h>
38#include <HepMC3/ReaderAsciiHepMC2.h>
39#include <HepMC3/WriterAsciiHepMC2.h>
54double expectedPx(
int i) {
return 10. +
i; }
58std::string writeInput(
const std::string&
name,
int nEvents)
60 std::ofstream out(
name);
61 out <<
"HepMC::Version 3.02.05\n"
62 <<
"HepMC::Asciiv3-START_EVENT_LISTING\n"
64 <<
"T unit-test|indexed-access|\n";
66 const double px = expectedPx(
i);
67 out <<
"E " <<
i + 1 <<
" 1 4\n"
70 <<
"P 1 0 2212 0.000000e+00 0.000000e+00 +6.500000e+03 6.500000e+03 9.383000e-01 4\n"
71 <<
"P 2 0 2212 0.000000e+00 0.000000e+00 -6.500000e+03 6.500000e+03 9.383000e-01 4\n"
72 <<
"V -1 0.000000e+00 0.000000e+00 0.000000e+00 [1,2]\n"
73 <<
"P 3 -1 211 " << px <<
" 1.000000e+00 1.000000e+00 " << px + 5. <<
" 1.395700e-01 1\n"
74 <<
"P 4 -1 -211 " << -px <<
" -1.000000e+00 -1.000000e+00 " << px + 5. <<
" 1.395700e-01 1\n";
76 out <<
"HepMC::Asciiv3-END_EVENT_LISTING\n";
82std::string writeInputHepMC2(
const std::string& asciiv3,
const std::string&
name)
84 HepMC3::ReaderAscii in(asciiv3);
85 HepMC3::WriterAsciiHepMC2 out(
name);
87 HepMC3::GenEvent
event;
92 out.write_event(
event);
100std::string fingerprint(
const HepMC3::GenEvent&
event)
107 for (
const auto& p :
event.particles()) {
108 snprintf(
buf,
sizeof buf,
" [%d,%d,%.9e,%.9e,%.9e,%.9e]", p->pid(), p->status(),
109 p->momentum().x(), p->momentum().y(), p->momentum().z(), p->momentum().t());
117 const std::string
key =
"forwarding-generator_inputEventNumber";
127int servedEntry(
const std::vector<o2::MCTrack>&
tracks)
129 auto outgoing = std::find_if(
tracks.begin(),
tracks.end(),
130 [](
const o2::MCTrack&
t) { return t.GetPdgCode() == 211; });
131 if (outgoing ==
tracks.end()) {
134 return (
int)std::lround(outgoing->Px() - expectedPx(0));
138void configure(
const std::string&
file,
int eventsToSkip = 0)
141 "GeneratorFileOrCmd.fileNames=" +
file +
142 ";HepMC.randomize=true;HepMC.roundRobin=true;HepMC.reshuffleOnRepeat=false"
143 ";HepMC.rngseed=12345;HepMC.eventsToSkip=" +
153void checkSeekEquivalence(
const std::string&
file,
bool hepmc2)
155 auto makeReader = [hepmc2](std::shared_ptr<std::istream>
stream) -> std::shared_ptr<HepMC3::Reader> {
157 return std::make_shared<HepMC3::ReaderAsciiHepMC2>(
stream);
159 return std::make_shared<HepMC3::ReaderAscii>(
stream);
163 std::vector<std::streamoff>
offsets;
164 std::vector<std::string> sequential;
166 auto stream = std::make_shared<std::ifstream>(
file);
167 BOOST_REQUIRE(
stream->good());
168 auto reader = makeReader(
stream);
170 auto here = (std::streamoff)
stream->tellg();
171 HepMC3::GenEvent
event;
172 reader->read_event(
event);
173 if (reader->failed()) {
177 sequential.push_back(fingerprint(
event));
180 BOOST_REQUIRE_MESSAGE(!
offsets.empty(),
"no event indexed in " <<
file);
183 auto stream = std::make_shared<std::ifstream>(
file);
184 BOOST_REQUIRE(
stream->good());
185 auto reader = makeReader(
stream);
188 reader->read_event(
header);
192 HepMC3::GenEvent
event;
193 reader->read_event(
event);
194 BOOST_REQUIRE_MESSAGE(!reader->failed(),
195 file <<
": could not read entry " <<
entry <<
" by seeking");
196 BOOST_CHECK_MESSAGE(fingerprint(
event) == sequential[
entry],
197 file <<
": entry " <<
entry <<
" read by seeking differs from the "
198 <<
"sequential read; the HepMC3 reader can no longer be "
199 <<
"repositioned and GeneratorHepMC's indexed access is unsafe");
200 BOOST_CHECK_MESSAGE(
event.run_info() !=
nullptr,
201 file <<
": entry " <<
entry <<
" lost its GenRunInfo");
212 auto asciiv3 = writeInput(
"test_GeneratorHepMCIndexed_seek.hepmc",
nEvents);
213 auto hepmc2 = writeInputHepMC2(asciiv3,
"test_GeneratorHepMCIndexed_seek2.hepmc");
215 checkSeekEquivalence(asciiv3,
false);
216 checkSeekEquivalence(hepmc2,
true);
218 std::remove(asciiv3.c_str());
219 std::remove(hepmc2.c_str());
230 auto name = writeInput(
"test_GeneratorHepMCIndexed_gen.hepmc",
nEvents);
237 std::vector<int> served;
242 "event " <<
i <<
" belongs to no entry of the input");
245 BOOST_CHECK_MESSAGE(announcedEntry(
event.second) ==
entry,
246 "event " <<
i <<
": the generator reports entry "
247 << announcedEntry(
event.second)
248 <<
" but handed out the event stored at entry " <<
entry);
249 served.push_back(
entry);
254 std::iota(all.begin(), all.end(), 0);
255 std::vector<int> pass1(served.begin(), served.begin() +
nEvents);
256 std::vector<int> pass2(served.begin() +
nEvents, served.begin() + 2 *
nEvents);
257 std::vector<int> sorted1 = pass1;
258 std::vector<int> sorted2 = pass2;
259 std::sort(sorted1.begin(), sorted1.end());
260 std::sort(sorted2.begin(), sorted2.end());
270 std::remove(
name.c_str());
279 constexpr int toSkip = 18;
280 auto name = writeInput(
"test_GeneratorHepMCIndexed_skip.hepmc",
nEvents);
281 configure(
name, toSkip);
286 std::vector<int> served;
287 for (
int i = 0;
i < 2 * (
nEvents - toSkip); ++
i) {
291 "event " <<
i <<
" came from entry " <<
entry
292 <<
", outside the requested range [" << toSkip <<
", "
294 BOOST_CHECK_MESSAGE(announcedEntry(
event.second) ==
entry,
295 "event " <<
i <<
": the generator reports entry "
296 << announcedEntry(
event.second)
297 <<
" but handed out the event stored at entry " <<
entry);
298 served.push_back(
entry);
301 std::vector<int> usable(
nEvents - toSkip);
302 std::iota(usable.begin(), usable.end(), toSkip);
303 std::vector<int> pass1(served.begin(), served.begin() + (
nEvents - toSkip));
305 std::sort(sorted.begin(), sorted.end());
308 std::remove(
name.c_str());
316 auto asciiv3 = writeInput(
"test_GeneratorHepMCIndexed_h2src.hepmc",
nEvents);
317 auto name = writeInputHepMC2(asciiv3,
"test_GeneratorHepMCIndexed_h2.hepmc");
318 std::remove(asciiv3.c_str());
324 std::vector<int> served;
329 "event " <<
i <<
" belongs to no entry of the HepMC2 input");
330 BOOST_CHECK_MESSAGE(announcedEntry(
event.second) ==
entry,
331 "event " <<
i <<
": the generator reports entry "
332 << announcedEntry(
event.second)
333 <<
" but handed out the event stored at entry " <<
entry);
334 served.push_back(
entry);
337 std::iota(all.begin(), all.end(), 0);
338 auto sorted = served;
339 std::sort(sorted.begin(), sorted.end());
343 std::remove(
name.c_str());
std::vector< std::string > header
configStandalone Light OpenGL display display_light Apply smoothing to points Enable Z buffer Highlight links Highlight seeds Highlight sector tracks Highlight final tracks Show individual Show related Highlight grid Show only individual collision Color clusters belonging to track objects Set line Enable drawing TPC data Enable drawing TOF data Enable drawing magnetic field Set field line step count Invert colors configStandalone Heavy OpenGL display display_heavy Show tracks with ITS contribution Show tracks with TOF contribution Enable propagation of loopers Show clusters at nominal x of pad row for early transformed data Split CE tracks when they cross the central Mark clusters Mark adjacent clusters Hide rejected tracks Apply filter on tracks to be displayed Separate increase X h configStandalone Camera window renderer OpenGL display display_camera Orient the camera such that the y axis is always upwards Full Screen MultiSample Anti Downsampling Anti Enable Vertical Sync Target frame or if the backend cannot limit to the refresh Use OpenGL indirect draws to reduce number of draw calls Display h configStandalone Vulkan display display_vulkan Have uniform buffers in host accessible device memory h configStandalone Internal display display_internal Number of updates the Qt GUI may send ahead of the last one the display has before it waits for the display Opacity of the console background Number of console lines the history is shortened to this when it reaches twice the size Time in seconds an info message fades out after setInfoTime h OpenGL display display Font size Do not use Freetype for font Renderer for event Frontend to use for event ROOT macros used as track filter Console script file
std::vector< o2::its::TrackITS > tracks
Definition of the MCTrack class.
static void updateFromString(std::string const &)
A class offering convenient generator configuration and encapsulation of lower level classes....
std::pair< std::vector< MCTrack >, o2::dataformats::MCEventHeader > generateEvent()
void initService(std::string const &generatorName, std::string const &triggerName, VertexOption const &vtxOption)
GLuint GLsizei const GLuint const GLintptr * offsets
GLuint const GLchar * name
GLenum GLuint GLenum GLsizei const GLchar * buf
std::string to_string(gsl::span< T, Size > span)
BOOST_AUTO_TEST_CASE(hepmc3_reader_can_be_seeked)