HepMC3 event record library
convert_example.cc
1// -*- C++ -*-
2//
3// This file is part of HepMC
4// Copyright (C) 2014-2023 The HepMC collaboration (see AUTHORS for details)
5//
6/// @example convert_example.cc
7/// @brief Utility to convert between different types of event records
8///
9#include "HepMC3/Print.h"
10#include "HepMC3/GenEvent.h"
11#include "HepMC3/Reader.h"
14#include "HepMC3/ReaderAscii.h"
15#include "HepMC3/WriterAscii.h"
16#include "HepMC3/WriterHEPEVT.h"
17#include "HepMC3/WriterPlugin.h"
18#include "HepMC3/ReaderHEPEVT.h"
19#include "HepMC3/ReaderLHEF.h"
20#include "HepMC3/ReaderPlugin.h"
22
23#ifdef HEPMC3_ROOTIO
24#include "HepMC3/ReaderRoot.h"
25#include "HepMC3/WriterRoot.h"
28#endif
29#if HEPMC3_USE_COMPRESSION
30#include "HepMC3/ReaderGZ.h"
31#include "HepMC3/WriterGZ.h"
32#endif
33#ifdef HEPMC3_PROTOBUFIO
36#endif
37
38/* Extension example*/
39#ifdef HEPMCCONVERT_EXTENSION_ROOTTREEOPAL
40#ifndef HEPMC3_ROOTIO
41#warning "HEPMCCONVERT_EXTENSION_ROOTTREEOPAL requires compilation with of HepMC with ROOT, i.e. HEPMC3_ROOTIO.This extension will be disabled."
42#undef HEPMCCONVERT_EXTENSION_ROOTTREEOPAL
43#else
44#include "WriterRootTreeOPAL.h"
45#endif
46#endif
47#ifdef HEPMCCONVERT_EXTENSION_HEPEVTZEUS
48#include "WriterHEPEVTZEUS.h"
49#endif
50#ifdef HEPMCCONVERT_EXTENSION_DOT
51#include "WriterDOT.h"
52#endif
53
54
55#include "cmdline.h"
56using namespace HepMC3;
57enum formats {autodetect, hepmc2, hepmc3, hpe,root, treeroot, treerootopal, hpezeus, lhef, dump, dot, plugin, none, proto};
58
59template <class T>
60std::shared_ptr<Reader> get_input_file(const char* name, const bool input_is_stdin, const bool use_compression) {
61 std::string n(name);
62#if HEPMC3_USE_COMPRESSION
63 if (use_compression) {
64 return (input_is_stdin?std::make_shared<ReaderGZ<T> >(std::cin):std::make_shared<ReaderGZ<T> >(n));
65 }
66#endif
67 return (input_is_stdin?std::make_shared<T>(std::cin):std::make_shared<T>(n));
68}
69template <class T>
70std::shared_ptr<Writer> get_output_file(const char* name, const char* use_compression) {
71 std::string n(name);
72#if HEPMC3_USE_COMPRESSION
73 if (std::string(use_compression) == "z" ) return std::make_shared< WriterGZ<T,Compression::z> >(n);
74 if (std::string(use_compression) == "lzma" ) return std::make_shared< WriterGZ<T,Compression::lzma> >(n);
75 if (std::string(use_compression) == "bz2" ) return std::make_shared< WriterGZ<T,Compression::bz2> >(n);
76#endif
77 return std::make_shared<T>(n);
78}
79
80int main(int argc, char** argv)
81{
82 gengetopt_args_info ai{};
83 if (cmdline_parser (argc, argv, &ai) != 0) {
84 exit(1);
85 }
86 if ( !(
87 ( ai.inputs_num == 2 && ( std::string(ai.output_format_arg) != "none" && std::string(ai.output_format_arg) != "dump" )) ||
88 ( ai.inputs_num == 1 && ( std::string(ai.output_format_arg) == "none" || std::string(ai.output_format_arg) == "dump" ))
89 )
90 )
91 {
92 printf("Exactly two arguments are requred: the name of input and output files if the output format in not \"none\" or \"dump\" \n");
93 printf("In case the output format is \"none\" or \"dump\" exactly one argument should be given: the name of input file.\n");
94 exit(1);
95 }
96 std::map<std::string,formats> format_map;
97 format_map.insert(std::pair<std::string,formats> ( "auto", autodetect ));
98 format_map.insert(std::pair<std::string,formats> ( "hepmc2", hepmc2 ));
99 format_map.insert(std::pair<std::string,formats> ( "hepmc3", hepmc3 ));
100 format_map.insert(std::pair<std::string,formats> ( "hpe", hpe ));
101 format_map.insert(std::pair<std::string,formats> ( "root", root ));
102 format_map.insert(std::pair<std::string,formats> ( "treeroot", treeroot ));
103 format_map.insert(std::pair<std::string,formats> ( "treerootopal", treerootopal ));
104 format_map.insert(std::pair<std::string,formats> ( "hpezeus", hpezeus ));
105 format_map.insert(std::pair<std::string,formats> ( "lhef", lhef ));
106 format_map.insert(std::pair<std::string,formats> ( "dump", dump ));
107 format_map.insert(std::pair<std::string,formats> ( "dot", dot ));
108 format_map.insert(std::pair<std::string,formats> ( "plugin", plugin ));
109 format_map.insert(std::pair<std::string,formats> ( "none", none ));
110 format_map.insert(std::pair<std::string,formats> ( "proto", proto ));
111 std::map<std::string, std::string> options;
112 for (size_t i=0; i<ai.extensions_given; i++)
113 {
114 std::string optarg(ai.extensions_arg[i]);
115 size_t pos = optarg.find_first_of('=');
116 if ( pos < optarg.length() ) {
117 options[std::string(optarg,0,pos)] = std::string(optarg, pos+1, optarg.length());
118 }
119 }
120 long int events_parsed = 0;
121 long int events_limit = ai.events_limit_arg;
122 long int first_event_number = ai.first_event_number_arg;
123 long int last_event_number = ai.last_event_number_arg;
124 long int print_each_events_parsed = ai.print_every_events_parsed_arg;
125 std::string InputPluginLibrary;
126 std::string InputPluginName;
127
128 std::string OutputPluginLibrary;
129 std::string OutputPluginName;
130
131 std::shared_ptr<Reader> input_file;
132 bool input_is_stdin = (std::string(ai.inputs[0]) == std::string("-"));
133 if (input_is_stdin) std::ios_base::sync_with_stdio(false);
134#ifdef _LIBCPP_VERSION
135 if (input_is_stdin) {
136 printf("The program cannot process inputs from standard input as std::ios_base::sync_with_stdio(bool) is not implemented in libc++, please use another C++ standard library.\n");
137 exit(4);
138 }
139#endif
140
141 bool ignore_writer = false;
142 switch (format_map.at(std::string(ai.input_format_arg)))
143 {
144 case autodetect:
145 input_file = (input_is_stdin?deduce_reader(std::cin):deduce_reader(ai.inputs[0]));
146 if (!input_file)
147 {
148 input_is_stdin?printf("Input format detection for std input has failed\n"):printf("Input format detection for file %s has failed\n",ai.inputs[0]);
149 exit(2);
150 }
151 break;
152 case hepmc2:
153 input_file = get_input_file<ReaderAsciiHepMC2>(ai.inputs[0], input_is_stdin, ai.compressed_input_flag);
154 break;
155 case hepmc3:
156 input_file = get_input_file<ReaderAscii>(ai.inputs[0], input_is_stdin, ai.compressed_input_flag);
157 break;
158 case hpe:
159 input_file = get_input_file<ReaderHEPEVT>(ai.inputs[0], input_is_stdin,ai.compressed_input_flag);
160 break;
161 case lhef:
162 input_file = get_input_file<ReaderLHEF>(ai.inputs[0], input_is_stdin, ai.compressed_input_flag);
163 break;
164 case treeroot:
165#ifdef HEPMC3_ROOTIO
166 input_file = std::make_shared<ReaderRootTree>(ai.inputs[0]);
167 break;
168#else
169 printf("Input format %s is not supported\n", ai.input_format_arg);
170 exit(2);
171#endif
172 case root:
173#ifdef HEPMC3_ROOTIO
174 input_file = std::make_shared<ReaderRoot>(ai.inputs[0]);
175 break;
176#else
177 printf("Input format %s is not supported\n", ai.input_format_arg);
178 exit(2);
179#endif
180 case proto:
181#ifdef HEPMC3_PROTOBUFIO
182 input_file = std::make_shared<Readerprotobuf>(ai.inputs[0]);
183 break;
184#else
185 printf("Input format %s is not supported\n", ai.input_format_arg);
186 exit(2);
187#endif
188 case plugin:
189 if (options.find("InputPluginLibrary") == options.end()) {
190 printf("InputPluginLibrary option required\n");
191 exit(2);
192 }
193 else InputPluginLibrary = options.at("InputPluginLibrary");
194 if (options.find("InputPluginName") == options.end()) {
195 printf("InputPluginName option required\n");
196 exit(2);
197 }
198 else InputPluginName = options.at("InputPluginName");
199 input_file = std::make_shared<ReaderPlugin>(std::string(ai.inputs[0]), InputPluginLibrary, InputPluginName);
200 if (input_file->failed()) {
201 printf("Plugin initialization failed\n");
202 exit(2);
203 }
204 break;
205 default:
206 printf("Input format %s is not known\n", ai.input_format_arg);
207 exit(2);
208 break;
209 }
210 std::shared_ptr<Writer> output_file;
211 switch (format_map.at(std::string(ai.output_format_arg)))
212 {
213 case hepmc2:
214 output_file = get_output_file<WriterAsciiHepMC2>(ai.inputs[1], ai.compressed_output_arg);
215 break;
216 case hepmc3:
217 output_file = get_output_file<WriterAscii>(ai.inputs[1], ai.compressed_output_arg);
218 break;
219 case hpe:
220 output_file = get_output_file<WriterHEPEVT>(ai.inputs[1], ai.compressed_output_arg);
221 break;
222 case root:
223#ifdef HEPMC3_ROOTIO
224 output_file = std::make_shared<WriterRoot>(ai.inputs[1]);
225 break;
226#else
227 printf("Output format %s is not supported\n", ai.output_format_arg);
228 exit(2);
229#endif
230 case proto:
231#ifdef HEPMC3_PROTOBUFIO
232 output_file = std::make_shared<Writerprotobuf>(ai.inputs[1]);
233 break;
234#else
235 printf("Output format %s is not supported\n", ai.output_format_arg);
236 exit(2);
237#endif
238 case treeroot:
239#ifdef HEPMC3_ROOTIO
240 output_file = std::make_shared<WriterRootTree>(ai.inputs[1]);
241 break;
242#else
243 printf("Output format %s is not supported\n",ai.output_format_arg);
244 exit(2);
245#endif
246 /* Extension example*/
247 case treerootopal:
248#ifdef HEPMCCONVERT_EXTENSION_ROOTTREEOPAL
249 output_file = std::make_shared<WriterRootTreeOPAL>(ai.inputs[1]);
250 (std::dynamic_pointer_cast<WriterRootTreeOPAL>(output_file))->init_branches();
251 if (options.find("Run") != options.end()) (std::dynamic_pointer_cast<WriterRootTreeOPAL>(output_file))->set_run_number(std::atoi(options.at("Run").c_str()));
252 break;
253#else
254 printf("Output format %s is not supported\n",ai.output_format_arg);
255 exit(2);
256 break;
257#endif
258 case hpezeus:
259#ifdef HEPMCCONVERT_EXTENSION_HEPEVTZEUS
260 output_file = std::make_shared<WriterHEPEVTZEUS>(ai.inputs[1]);
261 break;
262#else
263 printf("Output format %s is not supported\n",ai.output_format_arg);
264 exit(2);
265#endif
266 case dot:
267#ifdef HEPMCCONVERT_EXTENSION_DOT
268 output_file = std::make_shared<WriterDOT>(ai.inputs[1]);
269 if (options.find("Style") != options.end()) (std::dynamic_pointer_cast<WriterDOT>(output_file))->set_style(std::atoi(options.at("Style").c_str()));
270 break;
271#else
272 printf("Output format %s is not supported\n",ai.output_format_arg);
273 exit(2);
274 break;
275#endif
276 case plugin:
277 if (options.find("OutputPluginLibrary") == options.end()) {
278 printf("OutputPluginLibrary option required, e.g. OutputPluginLibrary=libAnalysis.so\n");
279 exit(2);
280 }
281 else OutputPluginLibrary = options.at("OutputPluginLibrary");
282 if (options.find("OutputPluginName") == options.end()) {
283 printf("OutputPluginName option required, e.g. OutputPluginName=newAnalysisExamplefile\n");
284 exit(2);
285 }
286 else OutputPluginName = options.at("OutputPluginName");
287 output_file = std::make_shared<WriterPlugin>(std::string(ai.inputs[1]), OutputPluginLibrary, OutputPluginName);
288 if (output_file->failed()) {
289 printf("Plugin initialization failed\n");
290 exit(2);
291 }
292 break;
293 case dump:
294 output_file = nullptr;
295 break;
296 case none:
297 output_file = nullptr;
298 ignore_writer = true;
299 break;
300 default:
301 printf("Output format %s is not known\n", ai.output_format_arg);
302 exit(2);
303 break;
304 }
305 while( !input_file->failed() )
306 {
307 GenEvent evt(Units::GEV, Units::MM);
308 bool res_read = input_file->read_event(evt);
309
310 if( input_file->failed() ) {
311 printf("End of file reached. Exit.\n");
312 break;
313 }
314 if ( !res_read && ai.strict_read_arg) {
315 printf("Broken event. Exit.\n");
316 exit(3);
317 }
318 if (evt.event_number() < first_event_number) continue;
319 if (evt.event_number() > last_event_number) continue;
320 evt.set_run_info(input_file->run_info());
321 //Note the difference between ROOT and Ascii readers. The former read GenRunInfo before first event and the later at the same time as first event.
322 if (!ignore_writer)
323 {
324 if (output_file)
325 {
326 output_file->write_event(evt);
327 }
328 else
329 {
330 Print::content(evt);
331 }
332 }
333 evt.clear();
334 ++events_parsed;
335 if( events_parsed%print_each_events_parsed == 0 ) printf("Events parsed: %li\n", events_parsed);
336 if( events_parsed >= events_limit ) {
337 printf("Event limit reached:->events_parsed(%li) >= events_limit(%li)<-. Exit.\n", events_parsed, events_limit);
338 break;
339 }
340 }
341
342 if (input_file) input_file->close();
343 if (output_file) output_file->close();
344 cmdline_parser_free(&ai);
345 return EXIT_SUCCESS;
346}
Definition of class GenEvent.
Definition of static class Print.
Definition of class ReaderAsciiHepMC2.
Definition of class ReaderAscii.
Declaration of deduce_reader and related functions.
Definition of class ReaderGZ.
Definition of class ReaderHEPEVT.
Definition of class ReaderLHEF.
Definition of class ReaderPlugin.
Definition of class ReaderRootTree.
Definition of class ReaderRoot.
Definition of interface Reader.
Definition of class Readerprotobuf.
Definition of class WriterAsciiHepMC2.
Definition of class WriterAscii.
Definition of class WriterDOT converter of GenEvent into .dot format.
Definition of class WriterGZ.
Definition of class WriterHEPEVTZEUS.
Definition of class WriterHEPEVT.
Definition of class WriterPlugin.
Definition of class WriterRootTreeOPAL.
Definition of class WriterRootTree.
Definition of class WriterRoot.
Definition of class Writerprotobuf.
Stores event-related information.
Definition GenEvent.h:47
static void content(std::ostream &os, const GenEvent &event)
Print content of all GenEvent containers.
Definition Print.cc:17
GenEvent I/O parsing for compressed files.
Definition ReaderGZ.h:27
HepMC3 main namespace.
std::shared_ptr< Reader > deduce_reader(const std::string &filename)
This function deduces the type of input file based on the name/URL and its content,...