From c01f45605ecadf987b15ee5e4e9676fffed50eb9 Mon Sep 17 00:00:00 2001 From: tmadlener Date: Fri, 3 May 2024 11:17:10 +0200 Subject: [PATCH] Make it possible to map names in standalone converter --- .../k4EDM4hep2LcioConv/k4Lcio2EDM4hepConv.h | 16 ++-- k4EDM4hep2LcioConv/src/k4Lcio2EDM4hepConv.cpp | 22 ++++-- standalone/lcio2edm4hep.cpp | 76 ++++++++++++++----- 3 files changed, 80 insertions(+), 34 deletions(-) diff --git a/k4EDM4hep2LcioConv/include/k4EDM4hep2LcioConv/k4Lcio2EDM4hepConv.h b/k4EDM4hep2LcioConv/include/k4EDM4hep2LcioConv/k4Lcio2EDM4hepConv.h index 62ee84b..2aeacba 100644 --- a/k4EDM4hep2LcioConv/include/k4EDM4hep2LcioConv/k4Lcio2EDM4hepConv.h +++ b/k4EDM4hep2LcioConv/include/k4EDM4hep2LcioConv/k4Lcio2EDM4hepConv.h @@ -68,6 +68,7 @@ using MutableTrackerHit3D = edm4hep::TrackerHit; #include #include #include +#include #include namespace LCIO2EDM4hepConv { @@ -103,13 +104,16 @@ podio::Frame convertRunHeader(EVENT::LCRunHeader* rheader); /** * Convert a complete LCEvent from LCIO to EDM4hep. * - * A second, optional argument can be passed to limit the collections to - * convert to the subset that is passed. NOTE: There is an implicit assumption - * here that collsToConvert only contains collection names that are present in - * the passed evt. There is no exception handling internally to guard against - * collections that are missing. + * A second, optional argument can be passed to limit the collections to convert + * to the subset that is passed. Additionally, it allows to rename collections + * on the fly where the first element of each pair is the (original) LCIO name + * and the second one is the one that is used for the EDM4hep collection. + * + * NOTE: There is an implicit assumption here that collsToConvert only contains + * collection names that are present in the passed evt. There is no exception + * handling internally to guard against collections that are missing. */ -podio::Frame convertEvent(EVENT::LCEvent* evt, const std::vector& collsToConvert = {}); +podio::Frame convertEvent(EVENT::LCEvent* evt, const std::vector>& = {}); /** * Convert an LCIOCollection by dispatching to the specific conversion diff --git a/k4EDM4hep2LcioConv/src/k4Lcio2EDM4hepConv.cpp b/k4EDM4hep2LcioConv/src/k4Lcio2EDM4hepConv.cpp index f378bdb..ce7ce4d 100644 --- a/k4EDM4hep2LcioConv/src/k4Lcio2EDM4hepConv.cpp +++ b/k4EDM4hep2LcioConv/src/k4Lcio2EDM4hepConv.cpp @@ -62,20 +62,26 @@ std::vector getPIDMetaInfo(const EVENT::LCCollec return pidInfos; } -podio::Frame convertEvent(EVENT::LCEvent* evt, const std::vector& collsToConvert) { +podio::Frame convertEvent(EVENT::LCEvent* evt, const std::vector>& collsToConvert) { auto typeMapping = LcioEdmTypeMapping{}; std::vector edmevent; std::vector> LCRelations; - const auto& lcioNames = [&collsToConvert, &evt]() { + const auto collNames = [&collsToConvert, &evt]() { if (collsToConvert.empty()) { - return *evt->getCollectionNames(); + const auto evtColls = evt->getCollectionNames(); + std::vector> collNames{}; + collNames.reserve(evtColls->size()); + for (const auto& name : *evtColls) { + collNames.emplace_back(name, name); + } + return collNames; } - return collsToConvert; + return std::move(collsToConvert); }(); // In this loop the data gets converted. - for (const auto& lcioname : lcioNames) { + for (const auto& [lcioname, edm4hepName] : collNames) { const auto& lcioColl = evt->getCollection(lcioname); const auto& lciotype = lcioColl->getTypeName(); if (lciotype == "LCRelation") { @@ -86,7 +92,7 @@ podio::Frame convertEvent(EVENT::LCEvent* evt, const std::vector& c } if (!lcioColl->isSubset()) { - for (auto&& [name, edmColl] : convertCollection(lcioname, lcioColl, typeMapping)) { + for (auto&& [name, edmColl] : convertCollection(edm4hepName, lcioColl, typeMapping)) { if (edmColl != nullptr) { edmevent.emplace_back(std::move(name), std::move(edmColl)); } @@ -94,14 +100,14 @@ podio::Frame convertEvent(EVENT::LCEvent* evt, const std::vector& c } } // Filling of the Subset Colections - for (const auto& lcioname : lcioNames) { + for (const auto& [lcioname, edm4hepName] : collNames) { auto lcioColl = evt->getCollection(lcioname); if (lcioColl->isSubset()) { const auto& lciotype = lcioColl->getTypeName(); auto edmColl = fillSubset(lcioColl, typeMapping, lciotype); if (edmColl != nullptr) { - edmevent.emplace_back(lcioname, std::move(edmColl)); + edmevent.emplace_back(edm4hepName, std::move(edmColl)); } } } diff --git a/standalone/lcio2edm4hep.cpp b/standalone/lcio2edm4hep.cpp index 1746e62..6a3cd59 100644 --- a/standalone/lcio2edm4hep.cpp +++ b/standalone/lcio2edm4hep.cpp @@ -20,29 +20,58 @@ using ROOTWriter = podio::ROOTFrameWriter; #include #include #include +#include #include #include #include -std::vector> getNamesAndTypes(const std::string& collTypeFile) { +/// Simple helper struct to group information about a collection to be converted +struct NamesType { + std::string lcioName{}; ///< The name in the lcio file + std::string edm4hepName{}; ///< The name in the edm4hep file + std::string typeName{}; ///< The LCIO type +}; + +/// Convert a config file line into a NamesType struct +std::optional fromConfigLine(std::string line) { + NamesType info; + std::stringstream sline(std::move(line)); + std::string name; + // This only looks for the first two words in the line and ignores + // everything that comes after that. + if (!(sline >> name >> info.typeName)) { + std::cerr << "need a name (mapping) and a type per line" << std::endl; + return std::nullopt; + } + + if (const auto colon = name.find(':'); colon != std::string::npos) { + info.lcioName = name.substr(0, colon); + info.edm4hepName = name.substr(colon + 1); + } else { + info.lcioName = name; + info.edm4hepName = name; + } + + return info; +} + +std::vector getNamesAndTypes(const std::string& collTypeFile) { std::ifstream input_file(collTypeFile); - std::vector> names_types; + std::vector names_types; if (!input_file.is_open()) { - std::cerr << "Failed to open file countaining the names and types of the LCIO Collections." << std::endl; + std::cerr << "Failed to open file containing the names and types of the " + "LCIO Collections." + << std::endl; } std::string line; while (std::getline(input_file, line)) { - std::stringstream sline(std::move(line)); - std::string name, type; - // This only looks for the first two words in the line and ignores everything that comes after that. - if (!(sline >> name >> type)) { - std::cerr << "need a name and a type per line" << std::endl; + auto lineInfo = fromConfigLine(std::move(line)); + if (!lineInfo) { return {}; } - names_types.emplace_back(std::move(name), std::move(type)); + names_types.emplace_back(std::move(lineInfo.value())); } - input_file.close(); return names_types; @@ -132,26 +161,32 @@ int main(int argc, char* argv[]) { const auto args = parseArgs({argv, argv + argc}); UTIL::CheckCollections colPatcher{}; - std::vector> namesTypes{}; + std::vector namesTypes{}; const bool patching = !args.patchFile.empty(); if (patching) { namesTypes = getNamesAndTypes(args.patchFile); if (namesTypes.empty()) { - std::cerr << "The provided list of collection names and types does not satisfy the required format: Pair of Name " + std::cerr << "The provided list of collection names and types does not " + "satisfy the required format: Pair of Name (mapping) " "and Type per line separated by space" << std::endl; return 1; } - colPatcher.addPatchCollections(namesTypes); + std::vector> patchNamesTypes{}; + patchNamesTypes.reserve(namesTypes.size()); + for (const auto& [name, _, type] : namesTypes) { + patchNamesTypes.emplace_back(name, type); + } + colPatcher.addPatchCollections(patchNamesTypes); } - // Construct a vector of collections to convert. If namesTypes is empty, this - // will be empty, and convertEvent will fall back to use the collections in - // the event + // Construct a vector of collections to convert. If namesTypes is empty, + // this will be empty, and convertEvent will fall back to use the + // collections in the event const auto collsToConvert = [&namesTypes]() { - std::vector names; + std::vector> names{}; names.reserve(namesTypes.size()); - for (const auto& [name, type] : namesTypes) { - names.emplace_back(name); + for (const auto& [lcioName, edm4hepName, _] : namesTypes) { + names.emplace_back(lcioName, edm4hepName); } return names; }(); @@ -181,7 +216,8 @@ int main(int argc, char* argv[]) { std::cout << "processing Event: " << i << std::endl; } auto evt = lcreader->readNextEvent(); - // Patching the Event to make sure all events contain the same Collections. + // Patching the Event to make sure all events contain the same + // Collections. if (patching == true) { colPatcher.patchCollections(evt); }