File indexing completed on 2025-07-01 07:53:16
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "ActsExamples/Io/HepMC3/HepMC3Util.hpp"
0010
0011 #include "Acts/Utilities/ScopedTimer.hpp"
0012
0013 #include <stdexcept>
0014
0015 #include <HepMC3/GenEvent.h>
0016 #include <HepMC3/GenParticle.h>
0017 #include <HepMC3/GenVertex.h>
0018
0019 namespace ActsExamples {
0020
0021 namespace {
0022 template <typename T>
0023 void mergeEventsImpl(HepMC3::GenEvent& event, std::span<T> genEvents,
0024 const Acts::Logger& logger) {
0025 Acts::AveragingScopedTimer mergeTimer("Merging HepMC3 events", logger(),
0026 Acts::Logging::DEBUG);
0027
0028 std::vector<std::shared_ptr<HepMC3::GenParticle>> particles;
0029
0030
0031 std::size_t nParticles = 0;
0032 std::size_t nVertices = 0;
0033 for (const auto& genEvent : genEvents) {
0034 nParticles += genEvent->particles().size();
0035 nVertices += genEvent->vertices().size();
0036 }
0037
0038 event.reserve(nParticles, nVertices);
0039
0040 for (const auto& genEvent : genEvents) {
0041 auto sample = mergeTimer.sample();
0042 particles.clear();
0043 particles.reserve(genEvent->particles().size());
0044
0045 auto copyAttributes = [&](const auto& src, auto& dst) {
0046 for (const auto& attr : src.attribute_names()) {
0047 auto value = src.attribute_as_string(attr);
0048 dst.add_attribute(attr,
0049 std::make_shared<HepMC3::StringAttribute>(value));
0050 }
0051 };
0052
0053 copyAttributes(*genEvent, event);
0054
0055
0056 for (const auto& srcParticle : genEvent->particles()) {
0057 if (srcParticle->id() - 1 != static_cast<int>(particles.size())) {
0058 throw std::runtime_error("Particle id is not consecutive");
0059 }
0060 auto particle = std::make_shared<HepMC3::GenParticle>();
0061 particle->set_momentum(srcParticle->momentum());
0062 particle->set_generated_mass(srcParticle->generated_mass());
0063 particle->set_pid(srcParticle->pid());
0064 particle->set_status(srcParticle->status());
0065
0066 particles.push_back(particle);
0067 event.add_particle(particle);
0068
0069 copyAttributes(*srcParticle, *particle);
0070 }
0071
0072 for (const auto& srcVertex : genEvent->vertices()) {
0073 auto vertex = std::make_shared<HepMC3::GenVertex>(srcVertex->position());
0074 vertex->set_status(srcVertex->status());
0075
0076 event.add_vertex(vertex);
0077
0078 copyAttributes(*srcVertex, *vertex);
0079
0080 for (const auto& srcParticle : srcVertex->particles_in()) {
0081 const auto& particle = particles.at(srcParticle->id() - 1);
0082 vertex->add_particle_in(particle);
0083 }
0084 for (const auto& srcParticle : srcVertex->particles_out()) {
0085 const auto& particle = particles.at(srcParticle->id() - 1);
0086 vertex->add_particle_out(particle);
0087 }
0088 }
0089 }
0090 }
0091 }
0092
0093 void HepMC3Util::mergeEvents(HepMC3::GenEvent& event,
0094 std::span<const HepMC3::GenEvent*> genEvents,
0095 const Acts::Logger& logger) {
0096 mergeEventsImpl(event, genEvents, logger);
0097 }
0098
0099 void HepMC3Util::mergeEvents(
0100 HepMC3::GenEvent& event,
0101 std::span<std::shared_ptr<const HepMC3::GenEvent>> genEvents,
0102 const Acts::Logger& logger) {
0103 mergeEventsImpl(event, genEvents, logger);
0104 }
0105
0106 std::string_view HepMC3Util::compressionExtension(Compression compression) {
0107 switch (compression) {
0108 using enum Compression;
0109 case none:
0110 return "";
0111 case zlib:
0112 return ".gz";
0113 case lzma:
0114 return ".xz";
0115 case bzip2:
0116 return ".bz2";
0117 case zstd:
0118 return ".zst";
0119 default:
0120 throw std::invalid_argument{"Unknown compression value"};
0121 }
0122 }
0123
0124 std::span<const HepMC3Util::Compression>
0125 HepMC3Util::availableCompressionModes() {
0126 using enum Compression;
0127 static const auto values = []() -> std::vector<HepMC3Util::Compression> {
0128 return {
0129 none,
0130 #ifdef HEPMC3_Z_SUPPORT
0131 zlib,
0132 #endif
0133 #ifdef HEPMC3_LZMA_SUPPORT
0134 lzma,
0135 #endif
0136 #ifdef HEPMC3_BZ2_SUPPORT
0137 bzip2,
0138 #endif
0139 #ifdef HEPMC3_ZSTD_SUPPORT
0140 zstd,
0141 #endif
0142 };
0143 }();
0144 return values;
0145 }
0146
0147 std::ostream& HepMC3Util::operator<<(std::ostream& os,
0148 HepMC3Util::Compression compression) {
0149 switch (compression) {
0150 using enum HepMC3Util::Compression;
0151 case none:
0152 return os << "none";
0153 case zlib:
0154 return os << "zlib";
0155 case lzma:
0156 return os << "lzma";
0157 case bzip2:
0158 return os << "bzip2";
0159 case zstd:
0160 return os << "zstd";
0161 default:
0162 throw std::invalid_argument{"Unknown compression value"};
0163 }
0164 }
0165
0166 std::ostream& HepMC3Util::operator<<(std::ostream& os,
0167 HepMC3Util::Format format) {
0168 switch (format) {
0169 using enum HepMC3Util::Format;
0170 case ascii:
0171 return os << "ascii";
0172 case root:
0173 return os << "root";
0174 default:
0175 throw std::invalid_argument{"Unknown format value"};
0176 }
0177 }
0178
0179 std::span<const HepMC3Util::Format> HepMC3Util::availableFormats() {
0180 using enum Format;
0181 static const auto values = []() -> std::vector<HepMC3Util::Format> {
0182 return {
0183 ascii,
0184 #ifdef HEPMC3_ROOT_SUPPORT
0185 root,
0186 #endif
0187 };
0188 }();
0189 return values;
0190 }
0191
0192 HepMC3Util::Format HepMC3Util::formatFromFilename(std::string_view filename) {
0193 using enum Format;
0194
0195 for (auto compression : availableCompressionModes()) {
0196 auto ext = compressionExtension(compression);
0197
0198 if (filename.ends_with(".hepmc3" + std::string(ext)) ||
0199 filename.ends_with(".hepmc" + std::string(ext))) {
0200 return ascii;
0201 }
0202 }
0203 if (filename.ends_with(".root")) {
0204 return root;
0205 }
0206
0207 throw std::invalid_argument{"Unknown format extension: " +
0208 std::string{filename}};
0209 }
0210
0211 }