From 0fcb8375e276cce6b26bcab12b84a9164f52431c Mon Sep 17 00:00:00 2001 From: tmadlener Date: Wed, 24 Jul 2024 11:39:59 +0200 Subject: [PATCH 01/15] Add AssociationNavigator utility class and tests --- include/podio/AssociationNavigator.h | 106 ++++++++++++++++++++++ include/podio/detail/LinkCollectionImpl.h | 2 + tests/unittests/links.cpp | 49 ++++++++++ 3 files changed, 157 insertions(+) create mode 100644 include/podio/AssociationNavigator.h diff --git a/include/podio/AssociationNavigator.h b/include/podio/AssociationNavigator.h new file mode 100644 index 000000000..fccd2a328 --- /dev/null +++ b/include/podio/AssociationNavigator.h @@ -0,0 +1,106 @@ +#ifndef PODIO_ASSOCIATIONNAVIGATOR_H +#define PODIO_ASSOCIATIONNAVIGATOR_H + +#include "podio/detail/AssociationFwd.h" + +#include +#include +#include +#include + +namespace podio { + +namespace detail::associations { + /// A small struct that simply bundles an object and its weight for a more + /// convenient return value for the AssociationNavigator + /// + /// @note In most uses the names of the members should not really matter as it + /// is possible to us this via structured bindings + template + struct WeightedObject { + WeightedObject(T obj, float w) : o(obj), weight(w) { + } + T o; ///< The object + float weight; ///< The weight in the association + }; +} // namespace detail::associations + +/// A helper class to more easily handle one-to-many associations. +/// +/// Internally simply populates two maps in its constructor and then queries +/// them to retrieve objects that are associated with another. +/// +/// @note There are no guarantees on the order of the objects in these maps. +/// Hence, there are also no guarantees on the order of the returned objects, +/// even if there inherintly is an order to them in the underlying associations +/// collection. +template +class AssociationNavigator { + using FromT = AssociationCollT::from_type; + using ToT = AssociationCollT::to_type; + + template + using WeightedObject = detail::associations::WeightedObject; + +public: + /// Construct a navigator from an association collection + AssociationNavigator(const AssociationCollT& associations); + + /// We do only construct from a collection + AssociationNavigator() = delete; + AssociationNavigator(const AssociationNavigator&) = default; + AssociationNavigator& operator=(const AssociationNavigator&) = default; + AssociationNavigator(AssociationNavigator&&) = default; + AssociationNavigator& operator=(AssociationNavigator&&) = default; + ~AssociationNavigator() = default; + + /// Get all the objects and weights that are associated to the passed object + /// + /// @param object The object that is labeled *to* in the association + /// + /// @returns A vector of all objects and their weights that are associated to + /// the passed object + std::vector> getAssociated(const ToT& object) const { + const auto& [begin, end] = m_to2from.equal_range(object); + std::vector> result; + result.reserve(std::distance(begin, end)); + + for (auto it = begin; it != end; ++it) { + result.emplace_back(it->second); + } + return result; + } + + /// Get all the objects and weights that are associated to the passed object + /// + /// @param object The object that is labeled *from* in the association + /// + /// @returns A vector of all objects and their weights that are associated to + /// the passed object + std::vector> getAssociated(const FromT& object) const { + const auto& [begin, end] = m_from2to.equal_range(object); + std::vector> result; + result.reserve(std::distance(begin, end)); + + for (auto it = begin; it != end; ++it) { + result.emplace_back(it->second); + } + return result; + } + +private: + std::multimap> m_from2to; ///< Map the from to the to objects + std::multimap> m_to2from; ///< Map the to to the from objects +}; + +template +AssociationNavigator::AssociationNavigator(const AssociationCollT& associations) { + for (const auto& [from, to, weight] : associations) { + m_from2to.emplace(std::piecewise_construct, std::forward_as_tuple(from), std::forward_as_tuple(to, weight)); + m_to2from.emplace(std::piecewise_construct, std::forward_as_tuple(to), std::forward_as_tuple(from, weight)); + } +} + +} // namespace podio + +#endif // PODIO_ASSOCIATIONNAVIGATOR_H diff --git a/include/podio/detail/LinkCollectionImpl.h b/include/podio/detail/LinkCollectionImpl.h index de62b2c4f..c4b9c20ce 100644 --- a/include/podio/detail/LinkCollectionImpl.h +++ b/include/podio/detail/LinkCollectionImpl.h @@ -40,6 +40,8 @@ class LinkCollection : public podio::CollectionBase { using CollectionDataT = podio::LinkCollectionData; public: + using from_type = FromT; + using to_type = ToT; using value_type = Link; using mutable_type = MutableLink; using const_iterator = LinkCollectionIterator; diff --git a/tests/unittests/links.cpp b/tests/unittests/links.cpp index aa8a9ef38..75595212b 100644 --- a/tests/unittests/links.cpp +++ b/tests/unittests/links.cpp @@ -1,5 +1,6 @@ #include "catch2/catch_test_macros.hpp" +#include "podio/AssociationNavigator.h" #include "podio/LinkCollection.h" #include "datamodel/ExampleClusterCollection.h" @@ -473,3 +474,51 @@ TEST_CASE("Link JSON conversion", "[links][json]") { } #endif + +TEST_CASE("AssociationNavigator basics", "[asssociations]") { + TestAColl coll{}; + std::vector hits(11); + std::vector clusters(3); + + for (size_t i = 0; i < 10; ++i) { + auto a = coll.create(); + a.set(hits[i]); + a.set(clusters[i % 3]); + a.setWeight(i * 0.1f); + } + + auto a = coll.create(); + a.set(hits[10]); + + podio::AssociationNavigator nav{coll}; + + for (size_t i = 0; i < 10; ++i) { + const auto& hit = hits[i]; + const auto assocClusters = nav.getAssociated(hit); + REQUIRE(assocClusters.size() == 1); + const auto& [cluster, weight] = assocClusters[0]; + REQUIRE(cluster == clusters[i % 3]); + REQUIRE(weight == i * 0.1f); + } + + const auto& cluster1 = clusters[0]; + auto assocHits = nav.getAssociated(cluster1); + REQUIRE(assocHits.size() == 4); + for (size_t i = 0; i < 4; ++i) { + const auto& [hit, weight] = assocHits[i]; + REQUIRE(hit == hits[i * 3]); + REQUIRE(weight == i * 3 * 0.1f); + } + + const auto& cluster2 = clusters[1]; + assocHits = nav.getAssociated(cluster2); + REQUIRE(assocHits.size() == 3); + for (size_t i = 0; i < 3; ++i) { + const auto& [hit, weight] = assocHits[i]; + REQUIRE(hit == hits[i * 3 + 1]); + REQUIRE(weight == (i * 3 + 1) * 0.1f); + } + + const auto [noCluster, noWeight] = nav.getAssociated(hits[10])[0]; + REQUIRE_FALSE(noCluster.isAvailable()); +} From 0c445b020f2d04ec3cc9964176dee31cc8c442a9 Mon Sep 17 00:00:00 2001 From: tmadlener Date: Tue, 30 Jul 2024 14:28:00 +0200 Subject: [PATCH 02/15] Rename Association to Link --- ...AssociationNavigator.h => LinkNavigator.h} | 36 +++++++++---------- tests/unittests/links.cpp | 8 ++--- 2 files changed, 22 insertions(+), 22 deletions(-) rename include/podio/{AssociationNavigator.h => LinkNavigator.h} (76%) diff --git a/include/podio/AssociationNavigator.h b/include/podio/LinkNavigator.h similarity index 76% rename from include/podio/AssociationNavigator.h rename to include/podio/LinkNavigator.h index fccd2a328..5922c7073 100644 --- a/include/podio/AssociationNavigator.h +++ b/include/podio/LinkNavigator.h @@ -1,7 +1,7 @@ -#ifndef PODIO_ASSOCIATIONNAVIGATOR_H -#define PODIO_ASSOCIATIONNAVIGATOR_H +#ifndef PODIO_LINKNAVIGATOR_H +#define PODIO_LINKNAVIGATOR_H -#include "podio/detail/AssociationFwd.h" +#include "podio/detail/LinkFwd.h" #include #include @@ -12,7 +12,7 @@ namespace podio { namespace detail::associations { /// A small struct that simply bundles an object and its weight for a more - /// convenient return value for the AssociationNavigator + /// convenient return value for the LinkNavigator /// /// @note In most uses the names of the members should not really matter as it /// is possible to us this via structured bindings @@ -34,25 +34,25 @@ namespace detail::associations { /// Hence, there are also no guarantees on the order of the returned objects, /// even if there inherintly is an order to them in the underlying associations /// collection. -template -class AssociationNavigator { - using FromT = AssociationCollT::from_type; - using ToT = AssociationCollT::to_type; +template +class LinkNavigator { + using FromT = LinkCollT::from_type; + using ToT = LinkCollT::to_type; template using WeightedObject = detail::associations::WeightedObject; public: /// Construct a navigator from an association collection - AssociationNavigator(const AssociationCollT& associations); + LinkNavigator(const LinkCollT& associations); /// We do only construct from a collection - AssociationNavigator() = delete; - AssociationNavigator(const AssociationNavigator&) = default; - AssociationNavigator& operator=(const AssociationNavigator&) = default; - AssociationNavigator(AssociationNavigator&&) = default; - AssociationNavigator& operator=(AssociationNavigator&&) = default; - ~AssociationNavigator() = default; + LinkNavigator() = delete; + LinkNavigator(const LinkNavigator&) = default; + LinkNavigator& operator=(const LinkNavigator&) = default; + LinkNavigator(LinkNavigator&&) = default; + LinkNavigator& operator=(LinkNavigator&&) = default; + ~LinkNavigator() = default; /// Get all the objects and weights that are associated to the passed object /// @@ -93,8 +93,8 @@ class AssociationNavigator { std::multimap> m_to2from; ///< Map the to to the from objects }; -template -AssociationNavigator::AssociationNavigator(const AssociationCollT& associations) { +template +LinkNavigator::LinkNavigator(const LinkCollT& associations) { for (const auto& [from, to, weight] : associations) { m_from2to.emplace(std::piecewise_construct, std::forward_as_tuple(from), std::forward_as_tuple(to, weight)); m_to2from.emplace(std::piecewise_construct, std::forward_as_tuple(to), std::forward_as_tuple(from, weight)); @@ -103,4 +103,4 @@ AssociationNavigator::AssociationNavigator(const AssociationCo } // namespace podio -#endif // PODIO_ASSOCIATIONNAVIGATOR_H +#endif // PODIO_LINKNAVIGATOR_H diff --git a/tests/unittests/links.cpp b/tests/unittests/links.cpp index 75595212b..debfdf139 100644 --- a/tests/unittests/links.cpp +++ b/tests/unittests/links.cpp @@ -1,7 +1,7 @@ #include "catch2/catch_test_macros.hpp" -#include "podio/AssociationNavigator.h" #include "podio/LinkCollection.h" +#include "podio/LinkNavigator.h" #include "datamodel/ExampleClusterCollection.h" #include "datamodel/ExampleHitCollection.h" @@ -475,8 +475,8 @@ TEST_CASE("Link JSON conversion", "[links][json]") { #endif -TEST_CASE("AssociationNavigator basics", "[asssociations]") { - TestAColl coll{}; +TEST_CASE("LinkNavigator basics", "[links]") { + TestLColl coll{}; std::vector hits(11); std::vector clusters(3); @@ -490,7 +490,7 @@ TEST_CASE("AssociationNavigator basics", "[asssociations]") { auto a = coll.create(); a.set(hits[10]); - podio::AssociationNavigator nav{coll}; + podio::LinkNavigator nav{coll}; for (size_t i = 0; i < 10; ++i) { const auto& hit = hits[i]; From e7cad2897639301fec6e1b8bf59c7fea8e94d102 Mon Sep 17 00:00:00 2001 From: tmadlener Date: Wed, 31 Jul 2024 18:46:27 +0200 Subject: [PATCH 03/15] Default initialize the internal maps --- include/podio/LinkNavigator.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/podio/LinkNavigator.h b/include/podio/LinkNavigator.h index 5922c7073..d525e6067 100644 --- a/include/podio/LinkNavigator.h +++ b/include/podio/LinkNavigator.h @@ -89,8 +89,8 @@ class LinkNavigator { } private: - std::multimap> m_from2to; ///< Map the from to the to objects - std::multimap> m_to2from; ///< Map the to to the from objects + std::multimap> m_from2to{}; ///< Map the from to the to objects + std::multimap> m_to2from{}; ///< Map the to to the from objects }; template From 90b6cde26c3ebee4db0689dacded71073d779c48 Mon Sep 17 00:00:00 2001 From: Thomas Madlener Date: Mon, 2 Dec 2024 10:53:51 +0100 Subject: [PATCH 04/15] Make navigator work with links between same types --- include/podio/LinkNavigator.h | 49 ++++++++++++++++++++++++++++++++-- tests/unittests/CMakeLists.txt | 2 +- tests/unittests/links.cpp | 42 +++++++++++++++++++++++++++++ 3 files changed, 90 insertions(+), 3 deletions(-) diff --git a/include/podio/LinkNavigator.h b/include/podio/LinkNavigator.h index d525e6067..64e7a96bb 100644 --- a/include/podio/LinkNavigator.h +++ b/include/podio/LinkNavigator.h @@ -5,6 +5,7 @@ #include #include +#include #include #include @@ -22,6 +23,10 @@ namespace detail::associations { } T o; ///< The object float weight; ///< The weight in the association + + bool operator==(const WeightedObject& other) const { + return other.o == o && other.weight == weight; + } }; } // namespace detail::associations @@ -56,11 +61,15 @@ class LinkNavigator { /// Get all the objects and weights that are associated to the passed object /// + /// @note This overload works always, even if the LinkCollection that was used + /// to construct this instance of the LinkNavigator has the same From and To + /// types. + /// /// @param object The object that is labeled *to* in the association /// /// @returns A vector of all objects and their weights that are associated to /// the passed object - std::vector> getAssociated(const ToT& object) const { + std::vector> getAssociatedTo(const ToT& object) const { const auto& [begin, end] = m_to2from.equal_range(object); std::vector> result; result.reserve(std::distance(begin, end)); @@ -73,11 +82,31 @@ class LinkNavigator { /// Get all the objects and weights that are associated to the passed object /// + /// @note This overload will automatically do the right thing (TM) in case the + /// LinkCollection that has been passed to construct this LinkNavigator has + /// different From and To types. + /// + /// @param object The object that is labeled *to* in the association + /// + /// @returns A vector of all objects and their weights that are associated to + /// the passed object + template + std::enable_if_t, std::vector>> + getAssociated(const ToT& object) const { + return getAssociatedTo(object); + } + + /// Get all the objects and weights that are associated to the passed object + /// + /// @note This overload works always, even if the LinkCollection that was used + /// to construct this instance of the LinkNavigator has the same From and To + /// types. + /// /// @param object The object that is labeled *from* in the association /// /// @returns A vector of all objects and their weights that are associated to /// the passed object - std::vector> getAssociated(const FromT& object) const { + std::vector> getAssociatedFrom(const FromT& object) const { const auto& [begin, end] = m_from2to.equal_range(object); std::vector> result; result.reserve(std::distance(begin, end)); @@ -88,6 +117,22 @@ class LinkNavigator { return result; } + /// Get all the objects and weights that are associated to the passed object + /// + /// @note This overload will automatically do the right thing (TM) in case the + /// LinkCollection that has been passed to construct this LinkNavigator has + /// different From and To types. + /// + /// @param object The object that is labeled *from* in the association + /// + /// @returns A vector of all objects and their weights that are associated to + /// the passed object + template + std::enable_if_t, std::vector>> + getAssociated(const FromT& object) const { + return getAssociatedFrom(object); + } + private: std::multimap> m_from2to{}; ///< Map the from to the to objects std::multimap> m_to2from{}; ///< Map the to to the from objects diff --git a/tests/unittests/CMakeLists.txt b/tests/unittests/CMakeLists.txt index 07c304a57..620d1da4a 100644 --- a/tests/unittests/CMakeLists.txt +++ b/tests/unittests/CMakeLists.txt @@ -1,7 +1,7 @@ if(CMAKE_CXX_STANDARD GREATER_EQUAL 20) set(CATCH2_MIN_VERSION 3.4) else() - set(CATCH2_MIN_VERSION 3.1) + set(CATCH2_MIN_VERSION 3.3) endif() if(USE_EXTERNAL_CATCH2) if (USE_EXTERNAL_CATCH2 STREQUAL AUTO) diff --git a/tests/unittests/links.cpp b/tests/unittests/links.cpp index debfdf139..a1eea29c9 100644 --- a/tests/unittests/links.cpp +++ b/tests/unittests/links.cpp @@ -1,4 +1,5 @@ #include "catch2/catch_test_macros.hpp" +#include "catch2/matchers/catch_matchers_vector.hpp" #include "podio/LinkCollection.h" #include "podio/LinkNavigator.h" @@ -522,3 +523,44 @@ TEST_CASE("LinkNavigator basics", "[links]") { const auto [noCluster, noWeight] = nav.getAssociated(hits[10])[0]; REQUIRE_FALSE(noCluster.isAvailable()); } + +TEST_CASE("LinkNavigator same types", "[links]") { + std::vector clusters(3); + auto linkColl = podio::LinkCollection{}; + auto link = linkColl.create(); + link.setFrom(clusters[0]); + link.setTo(clusters[1]); + link.setWeight(0.5f); + + link = linkColl.create(); + link.setFrom(clusters[0]); + link.setTo(clusters[2]); + link.setWeight(0.25f); + + link = linkColl.create(); + link.setFrom(clusters[1]); + link.setTo(clusters[2]); + link.setWeight(0.66f); + + auto navigator = podio::LinkNavigator{linkColl}; + auto linkedClusters = navigator.getAssociatedFrom(clusters[1]); + REQUIRE(linkedClusters.size() == 1); + REQUIRE(linkedClusters[0].o == clusters[2]); + REQUIRE(linkedClusters[0].weight == 0.66f); + + linkedClusters = navigator.getAssociatedTo(clusters[1]); + REQUIRE(linkedClusters.size() == 1); + REQUIRE(linkedClusters[0].o == clusters[0]); + REQUIRE(linkedClusters[0].weight == 0.5f); + + using Catch::Matchers::UnorderedEquals; + using podio::detail::associations::WeightedObject; + using WeightedObjVec = std::vector>; + linkedClusters = navigator.getAssociatedFrom(clusters[0]); + REQUIRE_THAT(linkedClusters, + UnorderedEquals(WeightedObjVec{WeightedObject(clusters[1], 0.5f), WeightedObject{clusters[2], 0.25f}})); + + linkedClusters = navigator.getAssociatedTo(clusters[2]); + REQUIRE_THAT(linkedClusters, + UnorderedEquals(WeightedObjVec{WeightedObject{clusters[0], 0.25f}, WeightedObject{clusters[1], 0.66f}})); +} From 8de96ad243a8d046036ce1b08dc1eb0e08af310d Mon Sep 17 00:00:00 2001 From: Thomas Madlener Date: Mon, 2 Dec 2024 10:56:25 +0100 Subject: [PATCH 05/15] Remove more mentions of assocations --- include/podio/LinkNavigator.h | 60 +++++++++++++++++------------------ tests/unittests/links.cpp | 30 +++++++++--------- 2 files changed, 44 insertions(+), 46 deletions(-) diff --git a/include/podio/LinkNavigator.h b/include/podio/LinkNavigator.h index 64e7a96bb..ca07036f7 100644 --- a/include/podio/LinkNavigator.h +++ b/include/podio/LinkNavigator.h @@ -11,7 +11,7 @@ namespace podio { -namespace detail::associations { +namespace detail::links { /// A small struct that simply bundles an object and its weight for a more /// convenient return value for the LinkNavigator /// @@ -22,22 +22,22 @@ namespace detail::associations { WeightedObject(T obj, float w) : o(obj), weight(w) { } T o; ///< The object - float weight; ///< The weight in the association + float weight; ///< The weight in the link bool operator==(const WeightedObject& other) const { return other.o == o && other.weight == weight; } }; -} // namespace detail::associations +} // namespace detail::links -/// A helper class to more easily handle one-to-many associations. +/// A helper class to more easily handle one-to-many links. /// /// Internally simply populates two maps in its constructor and then queries -/// them to retrieve objects that are associated with another. +/// them to retrieve objects that are linked with another. /// /// @note There are no guarantees on the order of the objects in these maps. /// Hence, there are also no guarantees on the order of the returned objects, -/// even if there inherintly is an order to them in the underlying associations +/// even if there inherintly is an order to them in the underlying links /// collection. template class LinkNavigator { @@ -45,11 +45,11 @@ class LinkNavigator { using ToT = LinkCollT::to_type; template - using WeightedObject = detail::associations::WeightedObject; + using WeightedObject = detail::links::WeightedObject; public: - /// Construct a navigator from an association collection - LinkNavigator(const LinkCollT& associations); + /// Construct a navigator from an link collection + LinkNavigator(const LinkCollT& links); /// We do only construct from a collection LinkNavigator() = delete; @@ -59,17 +59,17 @@ class LinkNavigator { LinkNavigator& operator=(LinkNavigator&&) = default; ~LinkNavigator() = default; - /// Get all the objects and weights that are associated to the passed object + /// Get all the objects and weights that are linked to the passed object /// /// @note This overload works always, even if the LinkCollection that was used /// to construct this instance of the LinkNavigator has the same From and To /// types. /// - /// @param object The object that is labeled *to* in the association + /// @param object The object that is labeled *to* in the link /// - /// @returns A vector of all objects and their weights that are associated to + /// @returns A vector of all objects and their weights that are linked to /// the passed object - std::vector> getAssociatedTo(const ToT& object) const { + std::vector> getLinkedTo(const ToT& object) const { const auto& [begin, end] = m_to2from.equal_range(object); std::vector> result; result.reserve(std::distance(begin, end)); @@ -80,33 +80,32 @@ class LinkNavigator { return result; } - /// Get all the objects and weights that are associated to the passed object + /// Get all the objects and weights that are linked to the passed object /// /// @note This overload will automatically do the right thing (TM) in case the /// LinkCollection that has been passed to construct this LinkNavigator has /// different From and To types. /// - /// @param object The object that is labeled *to* in the association + /// @param object The object that is labeled *to* in the link /// - /// @returns A vector of all objects and their weights that are associated to + /// @returns A vector of all objects and their weights that are linked to /// the passed object template - std::enable_if_t, std::vector>> - getAssociated(const ToT& object) const { - return getAssociatedTo(object); + std::enable_if_t, std::vector>> getLinked(const ToT& object) const { + return getLinkedTo(object); } - /// Get all the objects and weights that are associated to the passed object + /// Get all the objects and weights that are linked to the passed object /// /// @note This overload works always, even if the LinkCollection that was used /// to construct this instance of the LinkNavigator has the same From and To /// types. /// - /// @param object The object that is labeled *from* in the association + /// @param object The object that is labeled *from* in the link /// - /// @returns A vector of all objects and their weights that are associated to + /// @returns A vector of all objects and their weights that are linked to /// the passed object - std::vector> getAssociatedFrom(const FromT& object) const { + std::vector> getLinkedFrom(const FromT& object) const { const auto& [begin, end] = m_from2to.equal_range(object); std::vector> result; result.reserve(std::distance(begin, end)); @@ -117,20 +116,19 @@ class LinkNavigator { return result; } - /// Get all the objects and weights that are associated to the passed object + /// Get all the objects and weights that are linked to the passed object /// /// @note This overload will automatically do the right thing (TM) in case the /// LinkCollection that has been passed to construct this LinkNavigator has /// different From and To types. /// - /// @param object The object that is labeled *from* in the association + /// @param object The object that is labeled *from* in the link /// - /// @returns A vector of all objects and their weights that are associated to + /// @returns A vector of all objects and their weights that are linked to /// the passed object template - std::enable_if_t, std::vector>> - getAssociated(const FromT& object) const { - return getAssociatedFrom(object); + std::enable_if_t, std::vector>> getLinked(const FromT& object) const { + return getLinkedFrom(object); } private: @@ -139,8 +137,8 @@ class LinkNavigator { }; template -LinkNavigator::LinkNavigator(const LinkCollT& associations) { - for (const auto& [from, to, weight] : associations) { +LinkNavigator::LinkNavigator(const LinkCollT& links) { + for (const auto& [from, to, weight] : links) { m_from2to.emplace(std::piecewise_construct, std::forward_as_tuple(from), std::forward_as_tuple(to, weight)); m_to2from.emplace(std::piecewise_construct, std::forward_as_tuple(to), std::forward_as_tuple(from, weight)); } diff --git a/tests/unittests/links.cpp b/tests/unittests/links.cpp index a1eea29c9..4e7f3c5ba 100644 --- a/tests/unittests/links.cpp +++ b/tests/unittests/links.cpp @@ -495,32 +495,32 @@ TEST_CASE("LinkNavigator basics", "[links]") { for (size_t i = 0; i < 10; ++i) { const auto& hit = hits[i]; - const auto assocClusters = nav.getAssociated(hit); - REQUIRE(assocClusters.size() == 1); - const auto& [cluster, weight] = assocClusters[0]; + const auto linkedClusters = nav.getLinked(hit); + REQUIRE(linkedClusters.size() == 1); + const auto& [cluster, weight] = linkedClusters[0]; REQUIRE(cluster == clusters[i % 3]); REQUIRE(weight == i * 0.1f); } const auto& cluster1 = clusters[0]; - auto assocHits = nav.getAssociated(cluster1); - REQUIRE(assocHits.size() == 4); + auto linkedHits = nav.getLinked(cluster1); + REQUIRE(linkedHits.size() == 4); for (size_t i = 0; i < 4; ++i) { - const auto& [hit, weight] = assocHits[i]; + const auto& [hit, weight] = linkedHits[i]; REQUIRE(hit == hits[i * 3]); REQUIRE(weight == i * 3 * 0.1f); } const auto& cluster2 = clusters[1]; - assocHits = nav.getAssociated(cluster2); - REQUIRE(assocHits.size() == 3); + linkedHits = nav.getLinked(cluster2); + REQUIRE(linkedHits.size() == 3); for (size_t i = 0; i < 3; ++i) { - const auto& [hit, weight] = assocHits[i]; + const auto& [hit, weight] = linkedHits[i]; REQUIRE(hit == hits[i * 3 + 1]); REQUIRE(weight == (i * 3 + 1) * 0.1f); } - const auto [noCluster, noWeight] = nav.getAssociated(hits[10])[0]; + const auto [noCluster, noWeight] = nav.getLinked(hits[10])[0]; REQUIRE_FALSE(noCluster.isAvailable()); } @@ -543,24 +543,24 @@ TEST_CASE("LinkNavigator same types", "[links]") { link.setWeight(0.66f); auto navigator = podio::LinkNavigator{linkColl}; - auto linkedClusters = navigator.getAssociatedFrom(clusters[1]); + auto linkedClusters = navigator.getLinkedFrom(clusters[1]); REQUIRE(linkedClusters.size() == 1); REQUIRE(linkedClusters[0].o == clusters[2]); REQUIRE(linkedClusters[0].weight == 0.66f); - linkedClusters = navigator.getAssociatedTo(clusters[1]); + linkedClusters = navigator.getLinkedTo(clusters[1]); REQUIRE(linkedClusters.size() == 1); REQUIRE(linkedClusters[0].o == clusters[0]); REQUIRE(linkedClusters[0].weight == 0.5f); using Catch::Matchers::UnorderedEquals; - using podio::detail::associations::WeightedObject; + using podio::detail::links::WeightedObject; using WeightedObjVec = std::vector>; - linkedClusters = navigator.getAssociatedFrom(clusters[0]); + linkedClusters = navigator.getLinkedFrom(clusters[0]); REQUIRE_THAT(linkedClusters, UnorderedEquals(WeightedObjVec{WeightedObject(clusters[1], 0.5f), WeightedObject{clusters[2], 0.25f}})); - linkedClusters = navigator.getAssociatedTo(clusters[2]); + linkedClusters = navigator.getLinkedTo(clusters[2]); REQUIRE_THAT(linkedClusters, UnorderedEquals(WeightedObjVec{WeightedObject{clusters[0], 0.25f}, WeightedObject{clusters[1], 0.66f}})); } From 38aee33951b8a16ef73573969422daf9f7993055 Mon Sep 17 00:00:00 2001 From: Thomas Madlener Date: Mon, 2 Dec 2024 11:08:56 +0100 Subject: [PATCH 06/15] Avoid depending on an order in the linked objects --- tests/unittests/links.cpp | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/tests/unittests/links.cpp b/tests/unittests/links.cpp index 4e7f3c5ba..fec08226e 100644 --- a/tests/unittests/links.cpp +++ b/tests/unittests/links.cpp @@ -502,23 +502,19 @@ TEST_CASE("LinkNavigator basics", "[links]") { REQUIRE(weight == i * 0.1f); } - const auto& cluster1 = clusters[0]; - auto linkedHits = nav.getLinked(cluster1); - REQUIRE(linkedHits.size() == 4); - for (size_t i = 0; i < 4; ++i) { - const auto& [hit, weight] = linkedHits[i]; - REQUIRE(hit == hits[i * 3]); - REQUIRE(weight == i * 3 * 0.1f); - } + using Catch::Matchers::UnorderedEquals; + using podio::detail::links::WeightedObject; + using WeightedHits = std::vector>; - const auto& cluster2 = clusters[1]; - linkedHits = nav.getLinked(cluster2); - REQUIRE(linkedHits.size() == 3); - for (size_t i = 0; i < 3; ++i) { - const auto& [hit, weight] = linkedHits[i]; - REQUIRE(hit == hits[i * 3 + 1]); - REQUIRE(weight == (i * 3 + 1) * 0.1f); - } + auto linkedHits = nav.getLinked(clusters[0]); + REQUIRE_THAT(linkedHits, + UnorderedEquals(WeightedHits{WeightedObject{hits[0], 0.f}, WeightedObject{hits[3], 3 * 0.1f}, + WeightedObject{hits[6], 6 * 0.1f}, WeightedObject{hits[9], 9 * 0.1f}})); + + linkedHits = nav.getLinked(clusters[1]); + REQUIRE_THAT(linkedHits, + UnorderedEquals(WeightedHits{WeightedObject{hits[1], 0.1f}, WeightedObject{hits[4], 0.4f}, + WeightedObject{hits[7], 0.7f}})); const auto [noCluster, noWeight] = nav.getLinked(hits[10])[0]; REQUIRE_FALSE(noCluster.isAvailable()); From bd447e38e93f211b19e64f672221ce12c092ab68 Mon Sep 17 00:00:00 2001 From: Thomas Madlener Date: Mon, 2 Dec 2024 11:14:46 +0100 Subject: [PATCH 07/15] Remove unnecessary include --- include/podio/LinkNavigator.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/podio/LinkNavigator.h b/include/podio/LinkNavigator.h index ca07036f7..58bce92bc 100644 --- a/include/podio/LinkNavigator.h +++ b/include/podio/LinkNavigator.h @@ -1,8 +1,6 @@ #ifndef PODIO_LINKNAVIGATOR_H #define PODIO_LINKNAVIGATOR_H -#include "podio/detail/LinkFwd.h" - #include #include #include From af1e4f86e8abbd07d88104c1ae5905dfbed90913 Mon Sep 17 00:00:00 2001 From: Thomas Madlener Date: Mon, 2 Dec 2024 11:37:25 +0100 Subject: [PATCH 08/15] Add documentation --- doc/links.md | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/doc/links.md b/doc/links.md index d2c9f874a..dda9aaf40 100644 --- a/doc/links.md +++ b/doc/links.md @@ -136,6 +136,40 @@ and have that compiled into the library. This is necessary if you want to use the python bindings, since they rely on dynamically loading the datamodel libraries. +## The `LinkNavigator` utility + +`podio::LinkCollection`s store each link separately even if a given object is +present in several links. Additionally, they don't offer any real way to look up +objects that are linked easily (apart from manually looping and comparing +elements). To alleviate these issues, we provide the `podio::LinkNavigator` +utility class that facilitates navigating links and lookups. It can be +constructed from any `podio::LinkCollection` and can then be used to retrieve +linked objects. E.g. + +```cpp +const auto& recoMcLinks = event.get("mcrecolinks"); +const auto linkNavigator = podio::LinkNavigator(recoMcLinks); + +// For podio::LinkCollections with disparate types just use getLinked +const auto linkedRecs = linkNavigator.getLinked(mcParticle); +// If you want to make a point about the direction use getLinked{From,To} +// This is also necessary if the From and To type in the link collection are the same +const auto linkedMCs = linkNavigator.getLinkedFrom(recoParticle); +``` + +The return type of all methods is a `std::vector`, where the +`WeightedObject` is a simple template class that wraps the object and its +weight. It supports structured bindings, so you can e.g. do the following + +```cpp +for (const auto& [reco, weight] : linkedRecs) { + // do something with the reco particle and its weight +} +``` + +Alternatively, you can access the object via the `o` member and the weight via +the `weight` member. + ## Implementation details In order to give a slightly easier entry to the details of the implementation From 58aa60719375219582db0364e89ca9924ecdb656 Mon Sep 17 00:00:00 2001 From: Thomas Madlener Date: Mon, 2 Dec 2024 13:17:46 +0100 Subject: [PATCH 09/15] Make dependent types usable in c++17 --- include/podio/LinkNavigator.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/podio/LinkNavigator.h b/include/podio/LinkNavigator.h index 58bce92bc..053946fe6 100644 --- a/include/podio/LinkNavigator.h +++ b/include/podio/LinkNavigator.h @@ -39,8 +39,8 @@ namespace detail::links { /// collection. template class LinkNavigator { - using FromT = LinkCollT::from_type; - using ToT = LinkCollT::to_type; + using FromT = typename LinkCollT::from_type; + using ToT = typename LinkCollT::to_type; template using WeightedObject = detail::links::WeightedObject; From 46bc442c56e233906dfc16f1a3efe5c7d60506d6 Mon Sep 17 00:00:00 2001 From: Thomas Madlener Date: Mon, 2 Dec 2024 13:19:17 +0100 Subject: [PATCH 10/15] Documentation fixes as suggested --- doc/links.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/links.md b/doc/links.md index dda9aaf40..baa6ed4e6 100644 --- a/doc/links.md +++ b/doc/links.md @@ -139,15 +139,15 @@ libraries. ## The `LinkNavigator` utility `podio::LinkCollection`s store each link separately even if a given object is -present in several links. Additionally, they don't offer any real way to look up -objects that are linked easily (apart from manually looping and comparing +present in several links. Additionally, they don't offer any really easy way to +look up objects that are linked (apart from manually looping and comparing elements). To alleviate these issues, we provide the `podio::LinkNavigator` utility class that facilitates navigating links and lookups. It can be constructed from any `podio::LinkCollection` and can then be used to retrieve linked objects. E.g. ```cpp -const auto& recoMcLinks = event.get("mcrecolinks"); +const auto& recoMcLinks = event.get("RecoMCLinks"); const auto linkNavigator = podio::LinkNavigator(recoMcLinks); // For podio::LinkCollections with disparate types just use getLinked From 6dadc4ab4f05a4a87c0d234e94f364b96342f21a Mon Sep 17 00:00:00 2001 From: Thomas Madlener Date: Mon, 2 Dec 2024 15:58:56 +0100 Subject: [PATCH 11/15] Make directional overloads take a tag argument Now all overloads have the same name, and selection is done via a tag argument. --- doc/links.md | 10 +++++++--- include/podio/LinkNavigator.h | 28 ++++++++++++++++++++++++---- tests/unittests/links.cpp | 8 ++++---- 3 files changed, 35 insertions(+), 11 deletions(-) diff --git a/doc/links.md b/doc/links.md index baa6ed4e6..18ddb21ca 100644 --- a/doc/links.md +++ b/doc/links.md @@ -152,9 +152,13 @@ const auto linkNavigator = podio::LinkNavigator(recoMcLinks); // For podio::LinkCollections with disparate types just use getLinked const auto linkedRecs = linkNavigator.getLinked(mcParticle); -// If you want to make a point about the direction use getLinked{From,To} -// This is also necessary if the From and To type in the link collection are the same -const auto linkedMCs = linkNavigator.getLinkedFrom(recoParticle); +``` + +If you want to be explicit about the lookup direction, e.g. in case you have a +link that has the same `From` and `To` type, you can use the overloads that take +a second *tag argument*: +```cpp +const auto linkedMCs = linkNavigator.getLinked(recoParticle, podio::LookupFrom); ``` The return type of all methods is a `std::vector`, where the diff --git a/include/podio/LinkNavigator.h b/include/podio/LinkNavigator.h index 053946fe6..fc7569d32 100644 --- a/include/podio/LinkNavigator.h +++ b/include/podio/LinkNavigator.h @@ -26,8 +26,20 @@ namespace detail::links { return other.o == o && other.weight == weight; } }; + + /// Simple struct tag for overload selection in LinkNavigator below + struct LookupFromTag {}; + /// Simple struct tag for overload selection in LinkNavigator below + struct LookupToTag {}; } // namespace detail::links +/// Tag variable to select the lookup of *From* objects that are linked from a +/// *To* object in podio::LinkNavigator::getLinked +static constexpr detail::links::LookupFromTag LookupFrom; +/// Tag variable to select the lookup of *To* objects that are linked from a +/// *From* object in podio::LinkNavigator::getLinked +static constexpr detail::links::LookupToTag LookupTo; + /// A helper class to more easily handle one-to-many links. /// /// Internally simply populates two maps in its constructor and then queries @@ -59,15 +71,19 @@ class LinkNavigator { /// Get all the objects and weights that are linked to the passed object /// + /// You will get this overload if you pass the podio::LookupFrom tag as second + /// argument + /// /// @note This overload works always, even if the LinkCollection that was used /// to construct this instance of the LinkNavigator has the same From and To /// types. /// /// @param object The object that is labeled *to* in the link + /// @param . tag variable for selecting this overload /// /// @returns A vector of all objects and their weights that are linked to /// the passed object - std::vector> getLinkedTo(const ToT& object) const { + std::vector> getLinked(const ToT& object, podio::detail::links::LookupFromTag) const { const auto& [begin, end] = m_to2from.equal_range(object); std::vector> result; result.reserve(std::distance(begin, end)); @@ -90,20 +106,24 @@ class LinkNavigator { /// the passed object template std::enable_if_t, std::vector>> getLinked(const ToT& object) const { - return getLinkedTo(object); + return getLinked(object, podio::LookupFrom); } /// Get all the objects and weights that are linked to the passed object /// + /// You will get this overload if you pass the podio::LookupTo tag as second + /// argument + /// /// @note This overload works always, even if the LinkCollection that was used /// to construct this instance of the LinkNavigator has the same From and To /// types. /// /// @param object The object that is labeled *from* in the link + /// @param . tag variable for selecting this overload /// /// @returns A vector of all objects and their weights that are linked to /// the passed object - std::vector> getLinkedFrom(const FromT& object) const { + std::vector> getLinked(const FromT& object, podio::detail::links::LookupToTag) const { const auto& [begin, end] = m_from2to.equal_range(object); std::vector> result; result.reserve(std::distance(begin, end)); @@ -126,7 +146,7 @@ class LinkNavigator { /// the passed object template std::enable_if_t, std::vector>> getLinked(const FromT& object) const { - return getLinkedFrom(object); + return getLinked(object, podio::LookupTo); } private: diff --git a/tests/unittests/links.cpp b/tests/unittests/links.cpp index fec08226e..b164d95b3 100644 --- a/tests/unittests/links.cpp +++ b/tests/unittests/links.cpp @@ -539,12 +539,12 @@ TEST_CASE("LinkNavigator same types", "[links]") { link.setWeight(0.66f); auto navigator = podio::LinkNavigator{linkColl}; - auto linkedClusters = navigator.getLinkedFrom(clusters[1]); + auto linkedClusters = navigator.getLinked(clusters[1], podio::LookupTo); REQUIRE(linkedClusters.size() == 1); REQUIRE(linkedClusters[0].o == clusters[2]); REQUIRE(linkedClusters[0].weight == 0.66f); - linkedClusters = navigator.getLinkedTo(clusters[1]); + linkedClusters = navigator.getLinked(clusters[1], podio::LookupTo); REQUIRE(linkedClusters.size() == 1); REQUIRE(linkedClusters[0].o == clusters[0]); REQUIRE(linkedClusters[0].weight == 0.5f); @@ -552,11 +552,11 @@ TEST_CASE("LinkNavigator same types", "[links]") { using Catch::Matchers::UnorderedEquals; using podio::detail::links::WeightedObject; using WeightedObjVec = std::vector>; - linkedClusters = navigator.getLinkedFrom(clusters[0]); + linkedClusters = navigator.getLinked(clusters[0], podio::LookupTo); REQUIRE_THAT(linkedClusters, UnorderedEquals(WeightedObjVec{WeightedObject(clusters[1], 0.5f), WeightedObject{clusters[2], 0.25f}})); - linkedClusters = navigator.getLinkedTo(clusters[2]); + linkedClusters = navigator.getLinked(clusters[2], podio::LookupFrom); REQUIRE_THAT(linkedClusters, UnorderedEquals(WeightedObjVec{WeightedObject{clusters[0], 0.25f}, WeightedObject{clusters[1], 0.66f}})); } From 98371821893010e251fcffcb6f9729dd981435c6 Mon Sep 17 00:00:00 2001 From: Thomas Madlener Date: Mon, 2 Dec 2024 19:25:34 +0100 Subject: [PATCH 12/15] Rename overload selection tags and refine docstring wording --- include/podio/LinkNavigator.h | 50 +++++++++++++++++++---------------- tests/unittests/links.cpp | 8 +++--- 2 files changed, 31 insertions(+), 27 deletions(-) diff --git a/include/podio/LinkNavigator.h b/include/podio/LinkNavigator.h index fc7569d32..ceb02df45 100644 --- a/include/podio/LinkNavigator.h +++ b/include/podio/LinkNavigator.h @@ -28,17 +28,17 @@ namespace detail::links { }; /// Simple struct tag for overload selection in LinkNavigator below - struct LookupFromTag {}; + struct ReturnFromTag {}; /// Simple struct tag for overload selection in LinkNavigator below - struct LookupToTag {}; + struct ReturnToTag {}; } // namespace detail::links -/// Tag variable to select the lookup of *From* objects that are linked from a -/// *To* object in podio::LinkNavigator::getLinked -static constexpr detail::links::LookupFromTag LookupFrom; -/// Tag variable to select the lookup of *To* objects that are linked from a +/// Tag variable to select the lookup of *From* objects have links with a *To* +/// object in podio::LinkNavigator::getLinked +static constexpr detail::links::ReturnFromTag ReturnFrom; +/// Tag variable to select the lookup of *To* objects that have links with a /// *From* object in podio::LinkNavigator::getLinked -static constexpr detail::links::LookupToTag LookupTo; +static constexpr detail::links::ReturnToTag ReturnTo; /// A helper class to more easily handle one-to-many links. /// @@ -69,7 +69,8 @@ class LinkNavigator { LinkNavigator& operator=(LinkNavigator&&) = default; ~LinkNavigator() = default; - /// Get all the objects and weights that are linked to the passed object + /// Get all the *From* objects and weights that have links with the passed + /// object /// /// You will get this overload if you pass the podio::LookupFrom tag as second /// argument @@ -78,12 +79,12 @@ class LinkNavigator { /// to construct this instance of the LinkNavigator has the same From and To /// types. /// - /// @param object The object that is labeled *to* in the link + /// @param object The object that is labeled *To* in the link /// @param . tag variable for selecting this overload /// - /// @returns A vector of all objects and their weights that are linked to + /// @returns A vector of all objects and their weights that have links with /// the passed object - std::vector> getLinked(const ToT& object, podio::detail::links::LookupFromTag) const { + std::vector> getLinked(const ToT& object, podio::detail::links::ReturnFromTag) const { const auto& [begin, end] = m_to2from.equal_range(object); std::vector> result; result.reserve(std::distance(begin, end)); @@ -94,22 +95,24 @@ class LinkNavigator { return result; } - /// Get all the objects and weights that are linked to the passed object + /// Get all the *From* objects and weights that have links with the passed + /// object /// /// @note This overload will automatically do the right thing (TM) in case the /// LinkCollection that has been passed to construct this LinkNavigator has /// different From and To types. /// - /// @param object The object that is labeled *to* in the link + /// @param object The object that is labeled *To* in the link /// - /// @returns A vector of all objects and their weights that are linked to + /// @returns A vector of all objects and their weights that have links with /// the passed object template std::enable_if_t, std::vector>> getLinked(const ToT& object) const { - return getLinked(object, podio::LookupFrom); + return getLinked(object, podio::ReturnFrom); } - /// Get all the objects and weights that are linked to the passed object + /// Get all the *To* objects and weights that have links with the passed + /// object /// /// You will get this overload if you pass the podio::LookupTo tag as second /// argument @@ -118,12 +121,12 @@ class LinkNavigator { /// to construct this instance of the LinkNavigator has the same From and To /// types. /// - /// @param object The object that is labeled *from* in the link + /// @param object The object that is labeled *From* in the link /// @param . tag variable for selecting this overload /// - /// @returns A vector of all objects and their weights that are linked to + /// @returns A vector of all objects and their weights that have links with /// the passed object - std::vector> getLinked(const FromT& object, podio::detail::links::LookupToTag) const { + std::vector> getLinked(const FromT& object, podio::detail::links::ReturnToTag) const { const auto& [begin, end] = m_from2to.equal_range(object); std::vector> result; result.reserve(std::distance(begin, end)); @@ -134,19 +137,20 @@ class LinkNavigator { return result; } - /// Get all the objects and weights that are linked to the passed object + /// Get all the *To* objects and weights that have links with the passed + /// object /// /// @note This overload will automatically do the right thing (TM) in case the /// LinkCollection that has been passed to construct this LinkNavigator has /// different From and To types. /// - /// @param object The object that is labeled *from* in the link + /// @param object The object that is labeled *From* in the link /// - /// @returns A vector of all objects and their weights that are linked to + /// @returns A vector of all objects and their weights that have links with /// the passed object template std::enable_if_t, std::vector>> getLinked(const FromT& object) const { - return getLinked(object, podio::LookupTo); + return getLinked(object, podio::ReturnTo); } private: diff --git a/tests/unittests/links.cpp b/tests/unittests/links.cpp index b164d95b3..6731d1193 100644 --- a/tests/unittests/links.cpp +++ b/tests/unittests/links.cpp @@ -539,12 +539,12 @@ TEST_CASE("LinkNavigator same types", "[links]") { link.setWeight(0.66f); auto navigator = podio::LinkNavigator{linkColl}; - auto linkedClusters = navigator.getLinked(clusters[1], podio::LookupTo); + auto linkedClusters = navigator.getLinked(clusters[1], podio::ReturnTo); REQUIRE(linkedClusters.size() == 1); REQUIRE(linkedClusters[0].o == clusters[2]); REQUIRE(linkedClusters[0].weight == 0.66f); - linkedClusters = navigator.getLinked(clusters[1], podio::LookupTo); + linkedClusters = navigator.getLinked(clusters[1], podio::ReturnTo); REQUIRE(linkedClusters.size() == 1); REQUIRE(linkedClusters[0].o == clusters[0]); REQUIRE(linkedClusters[0].weight == 0.5f); @@ -552,11 +552,11 @@ TEST_CASE("LinkNavigator same types", "[links]") { using Catch::Matchers::UnorderedEquals; using podio::detail::links::WeightedObject; using WeightedObjVec = std::vector>; - linkedClusters = navigator.getLinked(clusters[0], podio::LookupTo); + linkedClusters = navigator.getLinked(clusters[0], podio::ReturnTo); REQUIRE_THAT(linkedClusters, UnorderedEquals(WeightedObjVec{WeightedObject(clusters[1], 0.5f), WeightedObject{clusters[2], 0.25f}})); - linkedClusters = navigator.getLinked(clusters[2], podio::LookupFrom); + linkedClusters = navigator.getLinked(clusters[2], podio::ReturnFrom); REQUIRE_THAT(linkedClusters, UnorderedEquals(WeightedObjVec{WeightedObject{clusters[0], 0.25f}, WeightedObject{clusters[1], 0.66f}})); } From d6fed943ac14f1666660be15dd58a30397f542f9 Mon Sep 17 00:00:00 2001 From: Thomas Madlener Date: Mon, 2 Dec 2024 19:28:37 +0100 Subject: [PATCH 13/15] Use correct overload in tests --- tests/unittests/links.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unittests/links.cpp b/tests/unittests/links.cpp index 6731d1193..eb80b076f 100644 --- a/tests/unittests/links.cpp +++ b/tests/unittests/links.cpp @@ -544,7 +544,7 @@ TEST_CASE("LinkNavigator same types", "[links]") { REQUIRE(linkedClusters[0].o == clusters[2]); REQUIRE(linkedClusters[0].weight == 0.66f); - linkedClusters = navigator.getLinked(clusters[1], podio::ReturnTo); + linkedClusters = navigator.getLinked(clusters[1], podio::ReturnFrom); REQUIRE(linkedClusters.size() == 1); REQUIRE(linkedClusters[0].o == clusters[0]); REQUIRE(linkedClusters[0].weight == 0.5f); From d1371327df6091a201eed826e48fcba89b955b8e Mon Sep 17 00:00:00 2001 From: Thomas Madlener Date: Mon, 2 Dec 2024 19:49:27 +0100 Subject: [PATCH 14/15] Update docs to new naming scheme --- doc/links.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/links.md b/doc/links.md index 18ddb21ca..1389b0445 100644 --- a/doc/links.md +++ b/doc/links.md @@ -158,7 +158,7 @@ If you want to be explicit about the lookup direction, e.g. in case you have a link that has the same `From` and `To` type, you can use the overloads that take a second *tag argument*: ```cpp -const auto linkedMCs = linkNavigator.getLinked(recoParticle, podio::LookupFrom); +const auto linkedMCs = linkNavigator.getLinked(recoParticle, podio::ReturnTo); ``` The return type of all methods is a `std::vector`, where the From 3ddeb5cb110740c7302f616ca3064e5301d52360 Mon Sep 17 00:00:00 2001 From: Thomas Madlener Date: Tue, 3 Dec 2024 15:48:33 +0100 Subject: [PATCH 15/15] Make sure documentation and code are consistent Co-authored-by: Andre Sailer --- include/podio/LinkNavigator.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/podio/LinkNavigator.h b/include/podio/LinkNavigator.h index ceb02df45..360afc90e 100644 --- a/include/podio/LinkNavigator.h +++ b/include/podio/LinkNavigator.h @@ -72,7 +72,7 @@ class LinkNavigator { /// Get all the *From* objects and weights that have links with the passed /// object /// - /// You will get this overload if you pass the podio::LookupFrom tag as second + /// You will get this overload if you pass the podio::ReturnFrom tag as second /// argument /// /// @note This overload works always, even if the LinkCollection that was used @@ -114,7 +114,7 @@ class LinkNavigator { /// Get all the *To* objects and weights that have links with the passed /// object /// - /// You will get this overload if you pass the podio::LookupTo tag as second + /// You will get this overload if you pass the podio::ReturnTo tag as second /// argument /// /// @note This overload works always, even if the LinkCollection that was used